1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import taskpool from '@ohos.taskpool'; 17import { BusinessError } from '@ohos.base'; 18import worker, { MessageEvents } from '@ohos.worker'; 19import util from '@ohos.util'; 20import { offsetMomentum, energy, advance } from './NBody_ETS_6'; 21import Logger from '../utils/Logger'; 22 23const TAG: string = 'CalculateUtil'; 24let calculateResult: string = "Total time costed = %s ms." 25 26class WorkerMessage { 27 timeSteps: number; 28 29 constructor(timeSteps: number) { 30 this.timeSteps = timeSteps; 31 } 32} 33 34/** 35 * 运行天体轨道计算程序 36 * @param totalTimeSteps 时间推移量 37 * @returns 计算时间 38 */ 39@Concurrent 40export function computeTask(totalTimeSteps: number): number { 41 const tagInTask: string = 'computeTask'; 42 const timeStep: number = 0.01; // 单位:hour 43 const fractionDigits: number = 9; // 机械能数值小数位 44 let start: number = new Date().getTime(); 45 46 // 建立孤立系统的动量守恒 47 offsetMomentum(); 48 Logger.info(tagInTask, energy().toFixed(fractionDigits)); 49 50 // 更新天体在按指定的时间变化后的位置信息 51 for (let i: number = 0; i < totalTimeSteps; i++) { 52 advance(timeStep); 53 } 54 55 // 判断系统计算前后机械能守恒 56 Logger.info(tagInTask, energy().toFixed(fractionDigits)); 57 let end: number = new Date().getTime(); 58 return end - start; 59} 60 61/** 62 * 使用TaskPool开启子线程,执行轨道计算任务 63 * @param totalTimeSteps 时间推移量 64 */ 65export function computeNBodyByTaskPool(totalTimeSteps: number): void { 66 Logger.info(TAG, "computeNBodyByTaskPool: start executing"); 67 let task: taskpool.Task = new taskpool.Task(computeTask, totalTimeSteps); 68 try { 69 Logger.info(TAG, 'computeNBodyByTaskPool: start calculating...'); 70 71 // 向taskpool线程池派发子线程任务 72 taskpool.execute(task, taskpool.Priority.HIGH).then((res: number) => { 73 Logger.info(TAG, 'computeNBodyByTaskPool: executed successfully, total time costed = ' + res + ' ms.'); 74 AppStorage.set<String>('timeCost', util.format(calculateResult, res.toString())) 75 }) 76 } catch (err) { 77 Logger.error(TAG, "computeNBodyByTaskPool: execute failed, " + (err as BusinessError).toString()); 78 } 79 Logger.info(TAG, "computeNBodyByTaskPool: finish executing"); 80} 81 82/** 83 * 使用Worker开启子线程,执行轨道计算任务 84 * @param totalTimeSteps 时间推移量 85 */ 86export function computeNBodyByWorker(totalTimeSteps: number): void { 87 Logger.info(TAG, "computeNBodyByWorker: start executing"); 88 let workerInstance = new worker.ThreadWorker("entry/ets/workers/CalculateWorker.ts"); 89 90 // 设置如何处理,来自worker线程的消息 91 workerInstance.onmessage = (e: MessageEvents): void => { 92 let data: Record<string, Object> = e.data; 93 Logger.info(TAG, 'computeNBodyByWorker: executed successfully, total time costed = ' + data.result + ' ms.'); 94 AppStorage.set<String>('timeCost', util.format(calculateResult, data.result)); 95 } 96 97 // 设置由主线程向worker线程发送什么消息 98 workerInstance.postMessage(new WorkerMessage(totalTimeSteps)); 99}