@swmmrs/swmmrs 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +264 -264
- package/dist/README.md +264 -264
- package/dist/serial/README.md +264 -264
- package/dist/serial/swmmrs_bg.wasm +0 -0
- package/dist/swmmrs.d.ts +4 -4
- package/dist/swmmrs.js +13 -13
- package/dist/swmmrs_bg.wasm +0 -0
- package/index.d.ts +2 -2
- package/index.js +2 -2
- package/package.json +53 -33
- package/src/swmmrs/client.ts +76 -76
- package/src/swmmrs/enums.ts +73 -73
- package/src/swmmrs/exceptions.ts +120 -120
- package/src/swmmrs/index.ts +79 -79
- package/src/swmmrs/objects/amm.ts +113 -113
- package/src/swmmrs/objects/collections.ts +153 -153
- package/src/swmmrs/objects/definitions.ts +246 -246
- package/src/swmmrs/objects/lids.ts +487 -487
- package/src/swmmrs/objects/links.ts +626 -626
- package/src/swmmrs/objects/nodes.ts +504 -504
- package/src/swmmrs/objects/options.ts +114 -114
- package/src/swmmrs/objects/rtk.ts +79 -79
- package/src/swmmrs/objects/subcatchments.ts +650 -650
- package/src/swmmrs/output.ts +798 -798
- package/src/swmmrs/protocol.ts +62 -62
- package/src/swmmrs/runtime.ts +188 -188
- package/src/swmmrs/scenarios.ts +40 -40
- package/src/swmmrs/simulation.ts +406 -406
- package/src/swmmrs/snapshots.ts +199 -199
- package/src/swmmrs/worker.ts +233 -233
- package/worker-node.js +142 -142
- package/worker.js +1 -1
package/src/swmmrs/worker.ts
CHANGED
|
@@ -1,233 +1,233 @@
|
|
|
1
|
-
import type { Simulation as NativeSimulation, OutputReader as NativeOutputReader } from "../../dist/swmmrs.js";
|
|
2
|
-
import type { ConfigurationDiagnostic, ErrorDetails } from "./exceptions.js";
|
|
3
|
-
import type { Request, Response, Result, Method } from "./protocol.js";
|
|
4
|
-
import type { RunResults } from "./types.js";
|
|
5
|
-
import type { CheckpointBundle } from "./scenarios.js";
|
|
6
|
-
import { loadWasm } from "./runtime.js";
|
|
7
|
-
|
|
8
|
-
// This module runs in a dedicated worker; the public build also uses DOM types.
|
|
9
|
-
const host = globalThis as unknown as {
|
|
10
|
-
onmessage: ((event: MessageEvent<Request>) => void) | null;
|
|
11
|
-
postMessage(message: Response, transfer?: Transferable[]): void;
|
|
12
|
-
};
|
|
13
|
-
const decoder = new TextDecoder();
|
|
14
|
-
let simulation: NativeSimulation | undefined;
|
|
15
|
-
let outputReader: NativeOutputReader | undefined;
|
|
16
|
-
let terminateThreadPool: (() => void) | undefined;
|
|
17
|
-
let queue = Promise.resolve();
|
|
18
|
-
|
|
19
|
-
function shutdown(): void {
|
|
20
|
-
const errors: unknown[] = [];
|
|
21
|
-
try { simulation?.close(); } catch (error) { errors.push(error); }
|
|
22
|
-
try { simulation?.free(); } catch (error) { errors.push(error); }
|
|
23
|
-
simulation = undefined;
|
|
24
|
-
try { outputReader?.free(); } catch (error) { errors.push(error); }
|
|
25
|
-
outputReader = undefined;
|
|
26
|
-
try { terminateThreadPool?.(); } catch (error) { errors.push(error); }
|
|
27
|
-
if (errors.length) {
|
|
28
|
-
const [primary, ...secondary] = errors;
|
|
29
|
-
const error = primary instanceof Error ? primary : new Error(String(primary));
|
|
30
|
-
if (secondary.length) Object.assign(error, { cleanupError: secondary.map(String).join("; ") });
|
|
31
|
-
throw error;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function results(owner: NativeSimulation): RunResults {
|
|
36
|
-
return {
|
|
37
|
-
report: decoder.decode(owner.readFile("model.rpt")),
|
|
38
|
-
output: owner.status().saveResults ? owner.readFile("model.out") : new Uint8Array(),
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function dispatch(request: Request): Promise<void> {
|
|
43
|
-
const { id, method } = request;
|
|
44
|
-
try {
|
|
45
|
-
let result: Result<Method> = undefined;
|
|
46
|
-
if (request.method === "open" || request.method === "resumeCheckpoint" || request.method === "openOutput") {
|
|
47
|
-
if (simulation || outputReader) throw new Error("An owner is already open");
|
|
48
|
-
const threads = request.method === "open" ? request.args[2]
|
|
49
|
-
: request.method === "resumeCheckpoint" ? request.args[1] : 1;
|
|
50
|
-
const bindings = threads === 1
|
|
51
|
-
? await import("../../dist/serial/swmmrs.js")
|
|
52
|
-
: await import("../../dist/swmmrs.js");
|
|
53
|
-
const moduleUrl = threads === 1
|
|
54
|
-
? new URL("../../dist/serial/swmmrs.js", import.meta.url).href
|
|
55
|
-
: new URL("../../dist/swmmrs.js", import.meta.url).href;
|
|
56
|
-
terminateThreadPool = bindings.terminateThreadPool;
|
|
57
|
-
await loadWasm(bindings, moduleUrl);
|
|
58
|
-
await bindings.initThreadPool(threads, moduleUrl);
|
|
59
|
-
if (request.method === "openOutput") {
|
|
60
|
-
outputReader = new bindings.OutputReader(request.args[0]);
|
|
61
|
-
result = outputReader.outputMetadata();
|
|
62
|
-
} else {
|
|
63
|
-
simulation = request.method === "open"
|
|
64
|
-
? new bindings.Simulation(request.args[0], request.args[1])
|
|
65
|
-
: bindings.Simulation.resumeCheckpoint(request.args[0]);
|
|
66
|
-
result = simulation.info();
|
|
67
|
-
}
|
|
68
|
-
} else if (request.method === "close" || request.method === "closeOutput") {
|
|
69
|
-
shutdown();
|
|
70
|
-
} else if (request.method === "outputMetadata" || request.method === "outputReadBulkSeries" ||
|
|
71
|
-
request.method === "outputReadBulkSeriesByPeriod" || request.method === "outputReadStoredDates" ||
|
|
72
|
-
request.method === "outputSubcatchmentSeries" || request.method === "outputNodeSeries" ||
|
|
73
|
-
request.method === "outputLinkSeries" || request.method === "outputSystemSeries") {
|
|
74
|
-
if (!outputReader) throw new Error("Output reader is closed");
|
|
75
|
-
switch (request.method) {
|
|
76
|
-
case "outputMetadata": result = outputReader.outputMetadata(); break;
|
|
77
|
-
case "outputReadBulkSeries": result = outputReader.outputReadBulkSeries(...request.args); break;
|
|
78
|
-
case "outputReadBulkSeriesByPeriod": result = outputReader.outputReadBulkSeriesByPeriod(...request.args); break;
|
|
79
|
-
case "outputReadStoredDates": result = outputReader.outputReadStoredDates(...request.args); break;
|
|
80
|
-
case "outputSubcatchmentSeries": result = outputReader.outputSubcatchmentSeries(...request.args); break;
|
|
81
|
-
case "outputNodeSeries": result = outputReader.outputNodeSeries(...request.args); break;
|
|
82
|
-
case "outputLinkSeries": result = outputReader.outputLinkSeries(...request.args); break;
|
|
83
|
-
case "outputSystemSeries": result = outputReader.outputSystemSeries(...request.args); break;
|
|
84
|
-
}
|
|
85
|
-
} else {
|
|
86
|
-
if (!simulation) throw new Error("Simulation is closed");
|
|
87
|
-
switch (request.method) {
|
|
88
|
-
case "state": result = simulation.state as Result<"state">; break;
|
|
89
|
-
case "info": result = simulation.info(); break;
|
|
90
|
-
case "status": result = simulation.status(); break;
|
|
91
|
-
case "start": simulation.start(...request.args); break;
|
|
92
|
-
case "step": result = simulation.step() ?? null; break;
|
|
93
|
-
case "stride": result = simulation.stride(...request.args) ?? null; break;
|
|
94
|
-
case "node": result = simulation.node(...request.args); break;
|
|
95
|
-
case "link": result = simulation.link(...request.args); break;
|
|
96
|
-
case "nodes": result = simulation.nodes(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
97
|
-
case "links": result = simulation.links(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
98
|
-
case "subcatchment": result = simulation.subcatchment(...request.args); break;
|
|
99
|
-
case "nodeExternalInflow": result = simulation.nodeExternalInflow(...request.args); break;
|
|
100
|
-
case "outfallFixedStage": result = simulation.outfallFixedStage(...request.args) ?? null; break;
|
|
101
|
-
case "nodeQuality": result = simulation.nodeQuality(...request.args); break;
|
|
102
|
-
case "nodeQualitySnapshot": result = simulation.nodeQualitySnapshot(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
103
|
-
case "overrideNodePollutantConcentrations": simulation.overrideNodePollutantConcentrations(...request.args); break;
|
|
104
|
-
case "nodeExternalPollutantMassFlux": result = simulation.nodeExternalPollutantMassFlux(...request.args); break;
|
|
105
|
-
case "nodeExternalPollutantMassFluxValue": result = simulation.nodeExternalPollutantMassFluxValue(...request.args); break;
|
|
106
|
-
case "updateNodeExternalPollutantMassFlux": simulation.updateNodeExternalPollutantMassFlux(...request.args); break;
|
|
107
|
-
case "nodeStatistics": result = simulation.nodeStatistics(...request.args); break;
|
|
108
|
-
case "storageStatistics": result = simulation.storageStatistics(...request.args); break;
|
|
109
|
-
case "outfallStatistics": result = simulation.outfallStatistics(...request.args); break;
|
|
110
|
-
case "nodeStatisticsSnapshot": result = simulation.nodeStatisticsSnapshot(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
111
|
-
case "nodeTotalInflowVolume": result = simulation.nodeTotalInflowVolume(...request.args); break;
|
|
112
|
-
case "linkQuality": result = simulation.linkQuality(...request.args); break;
|
|
113
|
-
case "linkQualitySnapshot": result = simulation.linkQualitySnapshot(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
114
|
-
case "overrideLinkPollutantConcentrations": simulation.overrideLinkPollutantConcentrations(...request.args); break;
|
|
115
|
-
case "linkExternalPollutantMassFlux": result = simulation.linkExternalPollutantMassFlux(...request.args); break;
|
|
116
|
-
case "linkExternalPollutantMassFluxValue": result = simulation.linkExternalPollutantMassFluxValue(...request.args); break;
|
|
117
|
-
case "updateLinkExternalPollutantMassFlux": simulation.updateLinkExternalPollutantMassFlux(...request.args); break;
|
|
118
|
-
case "setLinkFlowLimit": simulation.setLinkFlowLimit(...request.args); break;
|
|
119
|
-
case "linkStatistics": result = simulation.linkStatistics(...request.args); break;
|
|
120
|
-
case "pumpStatistics": result = simulation.pumpStatistics(...request.args); break;
|
|
121
|
-
case "linkStatisticsSnapshot": result = simulation.linkStatisticsSnapshot(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
122
|
-
case "linkInlet": result = simulation.linkInlet(...request.args); break;
|
|
123
|
-
case "inletResults": result = simulation.inletResults(...request.args); break;
|
|
124
|
-
case "updateInlet": simulation.updateInlet(...request.args); break;
|
|
125
|
-
case "subcatchments": result = simulation.subcatchments(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
126
|
-
case "rainGage": result = simulation.rainGage(...request.args); break;
|
|
127
|
-
case "nodeConfiguration": result = simulation.nodeConfiguration(...request.args); break;
|
|
128
|
-
case "linkConfiguration": result = simulation.linkConfiguration(...request.args); break;
|
|
129
|
-
case "useRainGageExternalPrecipitation": simulation.useRainGageExternalPrecipitation(...request.args); break;
|
|
130
|
-
case "rainGageExternalPrecipitationRate": result = simulation.rainGageExternalPrecipitationRate(...request.args) ?? null; break;
|
|
131
|
-
case "rainGageRainfallOverride": result = simulation.rainGageRainfallOverride(...request.args) ?? null; break;
|
|
132
|
-
case "subcatchmentPrecipitationScaleFactors": result = simulation.subcatchmentPrecipitationScaleFactors(...request.args); break;
|
|
133
|
-
case "setSubcatchmentPrecipitationScaleFactors": simulation.setSubcatchmentPrecipitationScaleFactors(...request.args); break;
|
|
134
|
-
case "subcatchmentExternalForcing": result = simulation.subcatchmentExternalForcing(...request.args); break;
|
|
135
|
-
case "setSubcatchmentExternalRainfall": simulation.setSubcatchmentExternalRainfall(...request.args); break;
|
|
136
|
-
case "setSubcatchmentExternalSnowfall": simulation.setSubcatchmentExternalSnowfall(...request.args); break;
|
|
137
|
-
case "subcatchmentQuality": result = simulation.subcatchmentQuality(...request.args); break;
|
|
138
|
-
case "subcatchmentQualitySnapshot": result = simulation.subcatchmentQualitySnapshot(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
139
|
-
case "subcatchmentNamedSettings": result = simulation.subcatchmentNamedSettings(...request.args); break;
|
|
140
|
-
case "subcatchmentNamedSetting": result = simulation.subcatchmentNamedSetting(...request.args); break;
|
|
141
|
-
case "updateSubcatchmentNamedSettings": simulation.updateSubcatchmentNamedSettings(...request.args); break;
|
|
142
|
-
case "subcatchmentExternalPollutantBuildupIncrement": result = simulation.subcatchmentExternalPollutantBuildupIncrement(...request.args); break;
|
|
143
|
-
case "subcatchmentExternalPollutantBuildupIncrementValue": result = simulation.subcatchmentExternalPollutantBuildupIncrementValue(...request.args); break;
|
|
144
|
-
case "updateSubcatchmentExternalPollutantBuildupIncrement": simulation.updateSubcatchmentExternalPollutantBuildupIncrement(...request.args); break;
|
|
145
|
-
case "subcatchmentStatistics": result = simulation.subcatchmentStatistics(...request.args); break;
|
|
146
|
-
case "subcatchmentStatisticsSnapshot": result = simulation.subcatchmentStatisticsSnapshot(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
147
|
-
case "subcatchmentConfiguration": result = simulation.subcatchmentConfiguration(...request.args); break;
|
|
148
|
-
case "configureNode": simulation.configureNode(...request.args); break;
|
|
149
|
-
case "configureLink": simulation.configureLink(...request.args); break;
|
|
150
|
-
case "configureSubcatchment": simulation.configureSubcatchment(...request.args); break;
|
|
151
|
-
case "setNodeExternalInflow": simulation.setNodeExternalInflow(...request.args); break;
|
|
152
|
-
case "setLinkTargetSetting": simulation.setLinkTargetSetting(...request.args); break;
|
|
153
|
-
case "setOutfallStage": simulation.setOutfallStage(...request.args); break;
|
|
154
|
-
case "setRainGagePrecipitation": simulation.setRainGagePrecipitation(...request.args); break;
|
|
155
|
-
case "setRainGageRainfallOverride": simulation.setRainGageRainfallOverride(...request.args); break;
|
|
156
|
-
case "options": result = simulation.options(); break;
|
|
157
|
-
case "configureOptions": simulation.configureOptions(...request.args); break;
|
|
158
|
-
case "updateSchedule": simulation.updateSchedule(...request.args); break;
|
|
159
|
-
case "maximumRoutingStepSeconds": result = simulation.maximumRoutingStepSeconds(); break;
|
|
160
|
-
case "ammModelConfiguration": result = simulation.ammModelConfiguration(...request.args); break;
|
|
161
|
-
case "configureAmmModel": simulation.configureAmmModel(...request.args); break;
|
|
162
|
-
case "ammAssignments": result = simulation.ammAssignments(); break;
|
|
163
|
-
case "replaceAmmAssignments": simulation.replaceAmmAssignments(...request.args); break;
|
|
164
|
-
case "unitHydrographConfiguration": result = simulation.unitHydrographConfiguration(...request.args); break;
|
|
165
|
-
case "configureUnitHydrograph": simulation.configureUnitHydrograph(...request.args); break;
|
|
166
|
-
case "rdiiAssignments": result = simulation.rdiiAssignments(); break;
|
|
167
|
-
case "replaceRdiiAssignments": simulation.replaceRdiiAssignments(...request.args); break;
|
|
168
|
-
case "aquiferConfiguration": result = simulation.aquiferConfiguration(...request.args); break;
|
|
169
|
-
case "configureAquifer": simulation.configureAquifer(...request.args); break;
|
|
170
|
-
case "snowmeltConfiguration": result = simulation.snowmeltConfiguration(...request.args); break;
|
|
171
|
-
case "configureSnowmelt": simulation.configureSnowmelt(...request.args); break;
|
|
172
|
-
case "snowmeltSurfaceConfiguration": result = simulation.snowmeltSurfaceConfiguration(...request.args); break;
|
|
173
|
-
case "configureSnowmeltSurface": simulation.configureSnowmeltSurface(...request.args); break;
|
|
174
|
-
case "lidControlConfiguration": result = simulation.lidControlConfiguration(...request.args); break;
|
|
175
|
-
case "configureLidControl": simulation.configureLidControl(...request.args); break;
|
|
176
|
-
case "lidUnitCount": result = simulation.lidUnitCount(...request.args); break;
|
|
177
|
-
case "lidUnitConfiguration": result = simulation.lidUnitConfiguration(...request.args); break;
|
|
178
|
-
case "configureLidUnit": simulation.configureLidUnit(...request.args); break;
|
|
179
|
-
case "lidUnitSnapshot": result = simulation.lidUnitSnapshot(...request.args); break;
|
|
180
|
-
case "subcatchmentLidSnapshot": result = simulation.subcatchmentLidSnapshot(...request.args); break;
|
|
181
|
-
case "useHotstart": simulation.useHotstart(...request.args); break;
|
|
182
|
-
case "saveHotstart": result = simulation.saveHotstart(); break;
|
|
183
|
-
case "exportCheckpoint": result = simulation.exportCheckpoint(); break;
|
|
184
|
-
case "loadCheckpointState": simulation.loadCheckpointState(...request.args); break;
|
|
185
|
-
case "statistics": result = simulation.statistics(); break;
|
|
186
|
-
case "finish": simulation.finish(); result = results(simulation); break;
|
|
187
|
-
case "run": simulation.run(...request.args); result = results(simulation); break;
|
|
188
|
-
case "end": simulation.end(); break;
|
|
189
|
-
case "finalizeReport": simulation.finalizeReport(); break;
|
|
190
|
-
case "report": simulation.report(); break;
|
|
191
|
-
case "resetSolver": simulation.resetSolver(); break;
|
|
192
|
-
case "sleepWorkers": simulation.sleepWorkers(); break;
|
|
193
|
-
case "readFile": result = simulation.readFile(...request.args); break;
|
|
194
|
-
default: {
|
|
195
|
-
const unhandled: never = request;
|
|
196
|
-
throw new Error(`Unknown simulation operation: ${String(unhandled)}`);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
const transfers: ArrayBuffer[] = [];
|
|
201
|
-
if (result instanceof Uint8Array) transfers.push(result.buffer as ArrayBuffer);
|
|
202
|
-
else if (result && typeof result === "object") {
|
|
203
|
-
if ("output" in result && result.output instanceof Uint8Array) transfers.push(result.output.buffer as ArrayBuffer);
|
|
204
|
-
if (request.method === "exportCheckpoint") {
|
|
205
|
-
const checkpoint = result as CheckpointBundle;
|
|
206
|
-
transfers.push(checkpoint.manifest.buffer as ArrayBuffer);
|
|
207
|
-
for (const bytes of Object.values(checkpoint.files)) transfers.push(bytes.buffer as ArrayBuffer);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
host.postMessage({ id, ok: true, result }, transfers);
|
|
211
|
-
} catch (error) {
|
|
212
|
-
const fatal = error instanceof WebAssembly.RuntimeError || method === "open" || method === "resumeCheckpoint" || method === "openOutput" || method === "close" || method === "closeOutput";
|
|
213
|
-
const source = error && typeof error === "object" ? error as Record<string, unknown> : {};
|
|
214
|
-
const detail: ErrorDetails = {
|
|
215
|
-
message: error instanceof Error ? error.message : String(error),
|
|
216
|
-
code: typeof source.code === "number" ? source.code : error instanceof WebAssembly.RuntimeError ? 9999 : undefined,
|
|
217
|
-
operation: typeof source.operation === "string" ? source.operation : method,
|
|
218
|
-
detail: typeof source.detail === "string" ? source.detail : undefined,
|
|
219
|
-
semanticCode: typeof source.semanticCode === "string" ? source.semanticCode : undefined,
|
|
220
|
-
category: typeof source.category === "string" ? source.category : undefined,
|
|
221
|
-
diagnostics: Array.isArray(source.diagnostics) ? source.diagnostics as ConfigurationDiagnostic[] : undefined,
|
|
222
|
-
report: typeof source.report === "string" ? source.report : undefined,
|
|
223
|
-
cleanupError: typeof source.cleanupError === "string" ? source.cleanupError : undefined,
|
|
224
|
-
};
|
|
225
|
-
if (fatal && method !== "close") {
|
|
226
|
-
try { shutdown(); } catch (cleanupError) { detail.cleanupError = String(cleanupError); }
|
|
227
|
-
}
|
|
228
|
-
host.postMessage({ id, ok: false, error: detail, fatal });
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Native calls are synchronous. Initialization must finish before later requests.
|
|
233
|
-
host.onmessage = ({ data }) => { queue = queue.then(() => dispatch(data)); };
|
|
1
|
+
import type { Simulation as NativeSimulation, OutputReader as NativeOutputReader } from "../../dist/swmmrs.js";
|
|
2
|
+
import type { ConfigurationDiagnostic, ErrorDetails } from "./exceptions.js";
|
|
3
|
+
import type { Request, Response, Result, Method } from "./protocol.js";
|
|
4
|
+
import type { RunResults } from "./types.js";
|
|
5
|
+
import type { CheckpointBundle } from "./scenarios.js";
|
|
6
|
+
import { loadWasm } from "./runtime.js";
|
|
7
|
+
|
|
8
|
+
// This module runs in a dedicated worker; the public build also uses DOM types.
|
|
9
|
+
const host = globalThis as unknown as {
|
|
10
|
+
onmessage: ((event: MessageEvent<Request>) => void) | null;
|
|
11
|
+
postMessage(message: Response, transfer?: Transferable[]): void;
|
|
12
|
+
};
|
|
13
|
+
const decoder = new TextDecoder();
|
|
14
|
+
let simulation: NativeSimulation | undefined;
|
|
15
|
+
let outputReader: NativeOutputReader | undefined;
|
|
16
|
+
let terminateThreadPool: (() => void) | undefined;
|
|
17
|
+
let queue = Promise.resolve();
|
|
18
|
+
|
|
19
|
+
function shutdown(): void {
|
|
20
|
+
const errors: unknown[] = [];
|
|
21
|
+
try { simulation?.close(); } catch (error) { errors.push(error); }
|
|
22
|
+
try { simulation?.free(); } catch (error) { errors.push(error); }
|
|
23
|
+
simulation = undefined;
|
|
24
|
+
try { outputReader?.free(); } catch (error) { errors.push(error); }
|
|
25
|
+
outputReader = undefined;
|
|
26
|
+
try { terminateThreadPool?.(); } catch (error) { errors.push(error); }
|
|
27
|
+
if (errors.length) {
|
|
28
|
+
const [primary, ...secondary] = errors;
|
|
29
|
+
const error = primary instanceof Error ? primary : new Error(String(primary));
|
|
30
|
+
if (secondary.length) Object.assign(error, { cleanupError: secondary.map(String).join("; ") });
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function results(owner: NativeSimulation): RunResults {
|
|
36
|
+
return {
|
|
37
|
+
report: decoder.decode(owner.readFile("model.rpt")),
|
|
38
|
+
output: owner.status().saveResults ? owner.readFile("model.out") : new Uint8Array(),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function dispatch(request: Request): Promise<void> {
|
|
43
|
+
const { id, method } = request;
|
|
44
|
+
try {
|
|
45
|
+
let result: Result<Method> = undefined;
|
|
46
|
+
if (request.method === "open" || request.method === "resumeCheckpoint" || request.method === "openOutput") {
|
|
47
|
+
if (simulation || outputReader) throw new Error("An owner is already open");
|
|
48
|
+
const threads = request.method === "open" ? request.args[2]
|
|
49
|
+
: request.method === "resumeCheckpoint" ? request.args[1] : 1;
|
|
50
|
+
const bindings = threads === 1
|
|
51
|
+
? await import("../../dist/serial/swmmrs.js")
|
|
52
|
+
: await import("../../dist/swmmrs.js");
|
|
53
|
+
const moduleUrl = threads === 1
|
|
54
|
+
? new URL("../../dist/serial/swmmrs.js", import.meta.url).href
|
|
55
|
+
: new URL("../../dist/swmmrs.js", import.meta.url).href;
|
|
56
|
+
terminateThreadPool = bindings.terminateThreadPool;
|
|
57
|
+
await loadWasm(bindings, moduleUrl);
|
|
58
|
+
await bindings.initThreadPool(threads, moduleUrl);
|
|
59
|
+
if (request.method === "openOutput") {
|
|
60
|
+
outputReader = new bindings.OutputReader(request.args[0]);
|
|
61
|
+
result = outputReader.outputMetadata();
|
|
62
|
+
} else {
|
|
63
|
+
simulation = request.method === "open"
|
|
64
|
+
? new bindings.Simulation(request.args[0], request.args[1])
|
|
65
|
+
: bindings.Simulation.resumeCheckpoint(request.args[0]);
|
|
66
|
+
result = simulation.info();
|
|
67
|
+
}
|
|
68
|
+
} else if (request.method === "close" || request.method === "closeOutput") {
|
|
69
|
+
shutdown();
|
|
70
|
+
} else if (request.method === "outputMetadata" || request.method === "outputReadBulkSeries" ||
|
|
71
|
+
request.method === "outputReadBulkSeriesByPeriod" || request.method === "outputReadStoredDates" ||
|
|
72
|
+
request.method === "outputSubcatchmentSeries" || request.method === "outputNodeSeries" ||
|
|
73
|
+
request.method === "outputLinkSeries" || request.method === "outputSystemSeries") {
|
|
74
|
+
if (!outputReader) throw new Error("Output reader is closed");
|
|
75
|
+
switch (request.method) {
|
|
76
|
+
case "outputMetadata": result = outputReader.outputMetadata(); break;
|
|
77
|
+
case "outputReadBulkSeries": result = outputReader.outputReadBulkSeries(...request.args); break;
|
|
78
|
+
case "outputReadBulkSeriesByPeriod": result = outputReader.outputReadBulkSeriesByPeriod(...request.args); break;
|
|
79
|
+
case "outputReadStoredDates": result = outputReader.outputReadStoredDates(...request.args); break;
|
|
80
|
+
case "outputSubcatchmentSeries": result = outputReader.outputSubcatchmentSeries(...request.args); break;
|
|
81
|
+
case "outputNodeSeries": result = outputReader.outputNodeSeries(...request.args); break;
|
|
82
|
+
case "outputLinkSeries": result = outputReader.outputLinkSeries(...request.args); break;
|
|
83
|
+
case "outputSystemSeries": result = outputReader.outputSystemSeries(...request.args); break;
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
if (!simulation) throw new Error("Simulation is closed");
|
|
87
|
+
switch (request.method) {
|
|
88
|
+
case "state": result = simulation.state as Result<"state">; break;
|
|
89
|
+
case "info": result = simulation.info(); break;
|
|
90
|
+
case "status": result = simulation.status(); break;
|
|
91
|
+
case "start": simulation.start(...request.args); break;
|
|
92
|
+
case "step": result = simulation.step() ?? null; break;
|
|
93
|
+
case "stride": result = simulation.stride(...request.args) ?? null; break;
|
|
94
|
+
case "node": result = simulation.node(...request.args); break;
|
|
95
|
+
case "link": result = simulation.link(...request.args); break;
|
|
96
|
+
case "nodes": result = simulation.nodes(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
97
|
+
case "links": result = simulation.links(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
98
|
+
case "subcatchment": result = simulation.subcatchment(...request.args); break;
|
|
99
|
+
case "nodeExternalInflow": result = simulation.nodeExternalInflow(...request.args); break;
|
|
100
|
+
case "outfallFixedStage": result = simulation.outfallFixedStage(...request.args) ?? null; break;
|
|
101
|
+
case "nodeQuality": result = simulation.nodeQuality(...request.args); break;
|
|
102
|
+
case "nodeQualitySnapshot": result = simulation.nodeQualitySnapshot(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
103
|
+
case "overrideNodePollutantConcentrations": simulation.overrideNodePollutantConcentrations(...request.args); break;
|
|
104
|
+
case "nodeExternalPollutantMassFlux": result = simulation.nodeExternalPollutantMassFlux(...request.args); break;
|
|
105
|
+
case "nodeExternalPollutantMassFluxValue": result = simulation.nodeExternalPollutantMassFluxValue(...request.args); break;
|
|
106
|
+
case "updateNodeExternalPollutantMassFlux": simulation.updateNodeExternalPollutantMassFlux(...request.args); break;
|
|
107
|
+
case "nodeStatistics": result = simulation.nodeStatistics(...request.args); break;
|
|
108
|
+
case "storageStatistics": result = simulation.storageStatistics(...request.args); break;
|
|
109
|
+
case "outfallStatistics": result = simulation.outfallStatistics(...request.args); break;
|
|
110
|
+
case "nodeStatisticsSnapshot": result = simulation.nodeStatisticsSnapshot(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
111
|
+
case "nodeTotalInflowVolume": result = simulation.nodeTotalInflowVolume(...request.args); break;
|
|
112
|
+
case "linkQuality": result = simulation.linkQuality(...request.args); break;
|
|
113
|
+
case "linkQualitySnapshot": result = simulation.linkQualitySnapshot(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
114
|
+
case "overrideLinkPollutantConcentrations": simulation.overrideLinkPollutantConcentrations(...request.args); break;
|
|
115
|
+
case "linkExternalPollutantMassFlux": result = simulation.linkExternalPollutantMassFlux(...request.args); break;
|
|
116
|
+
case "linkExternalPollutantMassFluxValue": result = simulation.linkExternalPollutantMassFluxValue(...request.args); break;
|
|
117
|
+
case "updateLinkExternalPollutantMassFlux": simulation.updateLinkExternalPollutantMassFlux(...request.args); break;
|
|
118
|
+
case "setLinkFlowLimit": simulation.setLinkFlowLimit(...request.args); break;
|
|
119
|
+
case "linkStatistics": result = simulation.linkStatistics(...request.args); break;
|
|
120
|
+
case "pumpStatistics": result = simulation.pumpStatistics(...request.args); break;
|
|
121
|
+
case "linkStatisticsSnapshot": result = simulation.linkStatisticsSnapshot(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
122
|
+
case "linkInlet": result = simulation.linkInlet(...request.args); break;
|
|
123
|
+
case "inletResults": result = simulation.inletResults(...request.args); break;
|
|
124
|
+
case "updateInlet": simulation.updateInlet(...request.args); break;
|
|
125
|
+
case "subcatchments": result = simulation.subcatchments(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
126
|
+
case "rainGage": result = simulation.rainGage(...request.args); break;
|
|
127
|
+
case "nodeConfiguration": result = simulation.nodeConfiguration(...request.args); break;
|
|
128
|
+
case "linkConfiguration": result = simulation.linkConfiguration(...request.args); break;
|
|
129
|
+
case "useRainGageExternalPrecipitation": simulation.useRainGageExternalPrecipitation(...request.args); break;
|
|
130
|
+
case "rainGageExternalPrecipitationRate": result = simulation.rainGageExternalPrecipitationRate(...request.args) ?? null; break;
|
|
131
|
+
case "rainGageRainfallOverride": result = simulation.rainGageRainfallOverride(...request.args) ?? null; break;
|
|
132
|
+
case "subcatchmentPrecipitationScaleFactors": result = simulation.subcatchmentPrecipitationScaleFactors(...request.args); break;
|
|
133
|
+
case "setSubcatchmentPrecipitationScaleFactors": simulation.setSubcatchmentPrecipitationScaleFactors(...request.args); break;
|
|
134
|
+
case "subcatchmentExternalForcing": result = simulation.subcatchmentExternalForcing(...request.args); break;
|
|
135
|
+
case "setSubcatchmentExternalRainfall": simulation.setSubcatchmentExternalRainfall(...request.args); break;
|
|
136
|
+
case "setSubcatchmentExternalSnowfall": simulation.setSubcatchmentExternalSnowfall(...request.args); break;
|
|
137
|
+
case "subcatchmentQuality": result = simulation.subcatchmentQuality(...request.args); break;
|
|
138
|
+
case "subcatchmentQualitySnapshot": result = simulation.subcatchmentQualitySnapshot(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
139
|
+
case "subcatchmentNamedSettings": result = simulation.subcatchmentNamedSettings(...request.args); break;
|
|
140
|
+
case "subcatchmentNamedSetting": result = simulation.subcatchmentNamedSetting(...request.args); break;
|
|
141
|
+
case "updateSubcatchmentNamedSettings": simulation.updateSubcatchmentNamedSettings(...request.args); break;
|
|
142
|
+
case "subcatchmentExternalPollutantBuildupIncrement": result = simulation.subcatchmentExternalPollutantBuildupIncrement(...request.args); break;
|
|
143
|
+
case "subcatchmentExternalPollutantBuildupIncrementValue": result = simulation.subcatchmentExternalPollutantBuildupIncrementValue(...request.args); break;
|
|
144
|
+
case "updateSubcatchmentExternalPollutantBuildupIncrement": simulation.updateSubcatchmentExternalPollutantBuildupIncrement(...request.args); break;
|
|
145
|
+
case "subcatchmentStatistics": result = simulation.subcatchmentStatistics(...request.args); break;
|
|
146
|
+
case "subcatchmentStatisticsSnapshot": result = simulation.subcatchmentStatisticsSnapshot(request.args[0] === undefined ? undefined : [...request.args[0]]); break;
|
|
147
|
+
case "subcatchmentConfiguration": result = simulation.subcatchmentConfiguration(...request.args); break;
|
|
148
|
+
case "configureNode": simulation.configureNode(...request.args); break;
|
|
149
|
+
case "configureLink": simulation.configureLink(...request.args); break;
|
|
150
|
+
case "configureSubcatchment": simulation.configureSubcatchment(...request.args); break;
|
|
151
|
+
case "setNodeExternalInflow": simulation.setNodeExternalInflow(...request.args); break;
|
|
152
|
+
case "setLinkTargetSetting": simulation.setLinkTargetSetting(...request.args); break;
|
|
153
|
+
case "setOutfallStage": simulation.setOutfallStage(...request.args); break;
|
|
154
|
+
case "setRainGagePrecipitation": simulation.setRainGagePrecipitation(...request.args); break;
|
|
155
|
+
case "setRainGageRainfallOverride": simulation.setRainGageRainfallOverride(...request.args); break;
|
|
156
|
+
case "options": result = simulation.options(); break;
|
|
157
|
+
case "configureOptions": simulation.configureOptions(...request.args); break;
|
|
158
|
+
case "updateSchedule": simulation.updateSchedule(...request.args); break;
|
|
159
|
+
case "maximumRoutingStepSeconds": result = simulation.maximumRoutingStepSeconds(); break;
|
|
160
|
+
case "ammModelConfiguration": result = simulation.ammModelConfiguration(...request.args); break;
|
|
161
|
+
case "configureAmmModel": simulation.configureAmmModel(...request.args); break;
|
|
162
|
+
case "ammAssignments": result = simulation.ammAssignments(); break;
|
|
163
|
+
case "replaceAmmAssignments": simulation.replaceAmmAssignments(...request.args); break;
|
|
164
|
+
case "unitHydrographConfiguration": result = simulation.unitHydrographConfiguration(...request.args); break;
|
|
165
|
+
case "configureUnitHydrograph": simulation.configureUnitHydrograph(...request.args); break;
|
|
166
|
+
case "rdiiAssignments": result = simulation.rdiiAssignments(); break;
|
|
167
|
+
case "replaceRdiiAssignments": simulation.replaceRdiiAssignments(...request.args); break;
|
|
168
|
+
case "aquiferConfiguration": result = simulation.aquiferConfiguration(...request.args); break;
|
|
169
|
+
case "configureAquifer": simulation.configureAquifer(...request.args); break;
|
|
170
|
+
case "snowmeltConfiguration": result = simulation.snowmeltConfiguration(...request.args); break;
|
|
171
|
+
case "configureSnowmelt": simulation.configureSnowmelt(...request.args); break;
|
|
172
|
+
case "snowmeltSurfaceConfiguration": result = simulation.snowmeltSurfaceConfiguration(...request.args); break;
|
|
173
|
+
case "configureSnowmeltSurface": simulation.configureSnowmeltSurface(...request.args); break;
|
|
174
|
+
case "lidControlConfiguration": result = simulation.lidControlConfiguration(...request.args); break;
|
|
175
|
+
case "configureLidControl": simulation.configureLidControl(...request.args); break;
|
|
176
|
+
case "lidUnitCount": result = simulation.lidUnitCount(...request.args); break;
|
|
177
|
+
case "lidUnitConfiguration": result = simulation.lidUnitConfiguration(...request.args); break;
|
|
178
|
+
case "configureLidUnit": simulation.configureLidUnit(...request.args); break;
|
|
179
|
+
case "lidUnitSnapshot": result = simulation.lidUnitSnapshot(...request.args); break;
|
|
180
|
+
case "subcatchmentLidSnapshot": result = simulation.subcatchmentLidSnapshot(...request.args); break;
|
|
181
|
+
case "useHotstart": simulation.useHotstart(...request.args); break;
|
|
182
|
+
case "saveHotstart": result = simulation.saveHotstart(); break;
|
|
183
|
+
case "exportCheckpoint": result = simulation.exportCheckpoint(); break;
|
|
184
|
+
case "loadCheckpointState": simulation.loadCheckpointState(...request.args); break;
|
|
185
|
+
case "statistics": result = simulation.statistics(); break;
|
|
186
|
+
case "finish": simulation.finish(); result = results(simulation); break;
|
|
187
|
+
case "run": simulation.run(...request.args); result = results(simulation); break;
|
|
188
|
+
case "end": simulation.end(); break;
|
|
189
|
+
case "finalizeReport": simulation.finalizeReport(); break;
|
|
190
|
+
case "report": simulation.report(); break;
|
|
191
|
+
case "resetSolver": simulation.resetSolver(); break;
|
|
192
|
+
case "sleepWorkers": simulation.sleepWorkers(); break;
|
|
193
|
+
case "readFile": result = simulation.readFile(...request.args); break;
|
|
194
|
+
default: {
|
|
195
|
+
const unhandled: never = request;
|
|
196
|
+
throw new Error(`Unknown simulation operation: ${String(unhandled)}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const transfers: ArrayBuffer[] = [];
|
|
201
|
+
if (result instanceof Uint8Array) transfers.push(result.buffer as ArrayBuffer);
|
|
202
|
+
else if (result && typeof result === "object") {
|
|
203
|
+
if ("output" in result && result.output instanceof Uint8Array) transfers.push(result.output.buffer as ArrayBuffer);
|
|
204
|
+
if (request.method === "exportCheckpoint") {
|
|
205
|
+
const checkpoint = result as CheckpointBundle;
|
|
206
|
+
transfers.push(checkpoint.manifest.buffer as ArrayBuffer);
|
|
207
|
+
for (const bytes of Object.values(checkpoint.files)) transfers.push(bytes.buffer as ArrayBuffer);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
host.postMessage({ id, ok: true, result }, transfers);
|
|
211
|
+
} catch (error) {
|
|
212
|
+
const fatal = error instanceof WebAssembly.RuntimeError || method === "open" || method === "resumeCheckpoint" || method === "openOutput" || method === "close" || method === "closeOutput";
|
|
213
|
+
const source = error && typeof error === "object" ? error as Record<string, unknown> : {};
|
|
214
|
+
const detail: ErrorDetails = {
|
|
215
|
+
message: error instanceof Error ? error.message : String(error),
|
|
216
|
+
code: typeof source.code === "number" ? source.code : error instanceof WebAssembly.RuntimeError ? 9999 : undefined,
|
|
217
|
+
operation: typeof source.operation === "string" ? source.operation : method,
|
|
218
|
+
detail: typeof source.detail === "string" ? source.detail : undefined,
|
|
219
|
+
semanticCode: typeof source.semanticCode === "string" ? source.semanticCode : undefined,
|
|
220
|
+
category: typeof source.category === "string" ? source.category : undefined,
|
|
221
|
+
diagnostics: Array.isArray(source.diagnostics) ? source.diagnostics as ConfigurationDiagnostic[] : undefined,
|
|
222
|
+
report: typeof source.report === "string" ? source.report : undefined,
|
|
223
|
+
cleanupError: typeof source.cleanupError === "string" ? source.cleanupError : undefined,
|
|
224
|
+
};
|
|
225
|
+
if (fatal && method !== "close") {
|
|
226
|
+
try { shutdown(); } catch (cleanupError) { detail.cleanupError = String(cleanupError); }
|
|
227
|
+
}
|
|
228
|
+
host.postMessage({ id, ok: false, error: detail, fatal });
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Native calls are synchronous. Initialization must finish before later requests.
|
|
233
|
+
host.onmessage = ({ data }) => { queue = queue.then(() => dispatch(data)); };
|