@sdeverywhere/runtime 0.2.9 → 0.2.11

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/dist/index.cjs DELETED
@@ -1,2490 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
- var __spreadValues = (a, b) => {
9
- for (var prop in b || (b = {}))
10
- if (__hasOwnProp.call(b, prop))
11
- __defNormalProp(a, prop, b[prop]);
12
- if (__getOwnPropSymbols)
13
- for (var prop of __getOwnPropSymbols(b)) {
14
- if (__propIsEnum.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- }
17
- return a;
18
- };
19
- var __export = (target, all) => {
20
- for (var name in all)
21
- __defProp(target, name, { get: all[name], enumerable: true });
22
- };
23
- var __copyProps = (to, from, except, desc) => {
24
- if (from && typeof from === "object" || typeof from === "function") {
25
- for (let key of __getOwnPropNames(from))
26
- if (!__hasOwnProp.call(to, key) && key !== except)
27
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
28
- }
29
- return to;
30
- };
31
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
- var __async = (__this, __arguments, generator) => {
33
- return new Promise((resolve, reject) => {
34
- var fulfilled = (value) => {
35
- try {
36
- step(generator.next(value));
37
- } catch (e) {
38
- reject(e);
39
- }
40
- };
41
- var rejected = (value) => {
42
- try {
43
- step(generator.throw(value));
44
- } catch (e) {
45
- reject(e);
46
- }
47
- };
48
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
49
- step((generator = generator.apply(__this, __arguments)).next());
50
- });
51
- };
52
-
53
- // src/index.ts
54
- var index_exports = {};
55
- __export(index_exports, {
56
- BufferedRunModelParams: () => BufferedRunModelParams,
57
- MockJsModel: () => MockJsModel,
58
- MockWasmModule: () => MockWasmModule,
59
- ModelListing: () => ModelListing,
60
- ModelScheduler: () => ModelScheduler,
61
- MultiContextModelScheduler: () => MultiContextModelScheduler,
62
- Outputs: () => Outputs,
63
- ReferencedRunModelParams: () => ReferencedRunModelParams,
64
- Series: () => Series,
65
- createConstantDef: () => createConstantDef,
66
- createInputValue: () => createInputValue,
67
- createLookupDef: () => createLookupDef,
68
- createRunnableModel: () => createRunnableModel,
69
- createSynchronousModelRunner: () => createSynchronousModelRunner,
70
- decodeConstants: () => decodeConstants,
71
- decodeLookups: () => decodeLookups,
72
- encodeConstants: () => encodeConstants,
73
- encodeLookups: () => encodeLookups,
74
- encodeVarIndices: () => encodeVarIndices,
75
- execJsModel: () => execJsModel,
76
- getEncodedConstantBufferLengths: () => getEncodedConstantBufferLengths,
77
- getEncodedLookupBufferLengths: () => getEncodedLookupBufferLengths,
78
- getEncodedVarIndicesLength: () => getEncodedVarIndicesLength,
79
- getJsModelFunctions: () => getJsModelFunctions,
80
- initJsModel: () => initJsModel,
81
- initWasmModel: () => initWasmModel,
82
- perfElapsed: () => perfElapsed,
83
- perfNow: () => perfNow
84
- });
85
- module.exports = __toCommonJS(index_exports);
86
-
87
- // src/_shared/inputs.ts
88
- function createInputValue(varId, defaultValue, initialValue) {
89
- let currentValue = initialValue !== void 0 ? initialValue : defaultValue;
90
- const callbacks = {};
91
- const get = () => {
92
- return currentValue;
93
- };
94
- const set = (newValue) => {
95
- var _a;
96
- if (newValue !== currentValue) {
97
- currentValue = newValue;
98
- (_a = callbacks.onSet) == null ? void 0 : _a.call(callbacks);
99
- }
100
- };
101
- const reset = () => {
102
- set(defaultValue);
103
- };
104
- return { varId, get, set, reset, callbacks };
105
- }
106
-
107
- // src/_shared/outputs.ts
108
- var import_neverthrow = require("neverthrow");
109
- var Series = class _Series {
110
- /**
111
- * @param varId The ID for the output variable (as used by SDEverywhere).
112
- * @param points The data points for the variable, one point per time increment.
113
- */
114
- constructor(varId, points) {
115
- this.varId = varId;
116
- this.points = points;
117
- }
118
- /**
119
- * Return the Y value at the given time. Note that this does not attempt to interpolate
120
- * if there is no data point defined for the given time and will return undefined in
121
- * that case.
122
- *
123
- * @param time The x (time) value.
124
- * @return The y value for the given time, or undefined if there is no data point defined
125
- * for the given time.
126
- */
127
- getValueAtTime(time) {
128
- var _a;
129
- return (_a = this.points.find((p) => p.x === time)) == null ? void 0 : _a.y;
130
- }
131
- /**
132
- * Create a new `Series` instance that is a copy of this one.
133
- */
134
- copy() {
135
- const pointsCopy = this.points.map((p) => __spreadValues({}, p));
136
- return new _Series(this.varId, pointsCopy);
137
- }
138
- };
139
- var Outputs = class {
140
- /**
141
- * @param varIds The output variable identifiers.
142
- * @param startTime The start time for the model.
143
- * @param endTime The end time for the model.
144
- * @param saveFreq The frequency with which output values are saved (aka `SAVEPER`).
145
- */
146
- constructor(varIds, startTime, endTime, saveFreq = 1) {
147
- this.varIds = varIds;
148
- this.startTime = startTime;
149
- this.endTime = endTime;
150
- this.saveFreq = saveFreq;
151
- this.seriesLength = Math.round((endTime - startTime) / saveFreq) + 1;
152
- this.varSeries = new Array(varIds.length);
153
- for (let i = 0; i < varIds.length; i++) {
154
- const points = new Array(this.seriesLength);
155
- for (let j = 0; j < this.seriesLength; j++) {
156
- points[j] = { x: startTime + j * saveFreq, y: 0 };
157
- }
158
- const varId = varIds[i];
159
- this.varSeries[i] = new Series(varId, points);
160
- }
161
- }
162
- /**
163
- * The optional set of specs that dictate which variables from the model will be
164
- * stored in this `Outputs` instance. If undefined, the default set of outputs
165
- * will be stored (as configured in `varIds`).
166
- * @hidden This is not yet part of the public API; it is exposed here for use
167
- * in experimental testing tools.
168
- */
169
- setVarSpecs(varSpecs) {
170
- if (varSpecs.length !== this.varIds.length) {
171
- throw new Error("Length of output varSpecs must match that of varIds");
172
- }
173
- this.varSpecs = varSpecs;
174
- }
175
- /**
176
- * Parse the given raw float buffer (produced by the model) and store the values
177
- * into this `Outputs` instance.
178
- *
179
- * Note that the length of `outputsBuffer` must be greater than or equal to
180
- * the capacity of this `Outputs` instance. The `Outputs` instance is allowed
181
- * to be smaller to support the case where you want to extract a subset of
182
- * the time range in the buffer produced by the model.
183
- *
184
- * @param outputsBuffer The raw outputs buffer produced by the model.
185
- * @param rowLength The number of elements per row (one element per save point).
186
- * @return An `ok` result if the buffer is valid, otherwise an `err` result.
187
- */
188
- updateFromBuffer(outputsBuffer, rowLength) {
189
- const result = parseOutputsBuffer(outputsBuffer, rowLength, this);
190
- if (result.isOk()) {
191
- return (0, import_neverthrow.ok)(void 0);
192
- } else {
193
- return (0, import_neverthrow.err)(result.error);
194
- }
195
- }
196
- /**
197
- * Return the series for the given output variable.
198
- *
199
- * @param varId The ID of the output variable (as used by SDEverywhere).
200
- */
201
- getSeriesForVar(varId) {
202
- const seriesIndex = this.varIds.indexOf(varId);
203
- if (seriesIndex >= 0) {
204
- return this.varSeries[seriesIndex];
205
- } else {
206
- return void 0;
207
- }
208
- }
209
- };
210
- function parseOutputsBuffer(outputsBuffer, rowLength, outputs) {
211
- const varCount = outputs.varIds.length;
212
- const seriesLength = outputs.seriesLength;
213
- if (rowLength < seriesLength || outputsBuffer.length < varCount * seriesLength) {
214
- return (0, import_neverthrow.err)("invalid-point-count");
215
- }
216
- for (let outputVarIndex = 0; outputVarIndex < varCount; outputVarIndex++) {
217
- const series = outputs.varSeries[outputVarIndex];
218
- let sourceIndex = rowLength * outputVarIndex;
219
- for (let valueIndex = 0; valueIndex < seriesLength; valueIndex++) {
220
- series.points[valueIndex].y = validateNumber(outputsBuffer[sourceIndex]);
221
- sourceIndex++;
222
- }
223
- }
224
- return (0, import_neverthrow.ok)(outputs);
225
- }
226
- function validateNumber(x) {
227
- if (!isNaN(x) && x > -1e32) {
228
- return x;
229
- } else {
230
- return void 0;
231
- }
232
- }
233
-
234
- // src/_shared/var-indices.ts
235
- function getEncodedVarIndicesLength(varSpecs) {
236
- var _a;
237
- let length = 1;
238
- for (const varSpec of varSpecs) {
239
- length += 2;
240
- const subCount = ((_a = varSpec.subscriptIndices) == null ? void 0 : _a.length) || 0;
241
- length += subCount;
242
- }
243
- return length;
244
- }
245
- function encodeVarIndices(varSpecs, indicesArray) {
246
- let offset = 0;
247
- indicesArray[offset++] = varSpecs.length;
248
- for (const varSpec of varSpecs) {
249
- indicesArray[offset++] = varSpec.varIndex;
250
- const subs = varSpec.subscriptIndices;
251
- const subCount = (subs == null ? void 0 : subs.length) || 0;
252
- indicesArray[offset++] = subCount;
253
- for (let i = 0; i < subCount; i++) {
254
- indicesArray[offset++] = subs[i];
255
- }
256
- }
257
- }
258
- function getEncodedConstantBufferLengths(constantDefs) {
259
- var _a;
260
- let constantIndicesLength = 1;
261
- let constantsLength = 0;
262
- for (const constantDef of constantDefs) {
263
- const varSpec = constantDef.varRef.varSpec;
264
- if (varSpec === void 0) {
265
- throw new Error("Cannot compute constant buffer lengths until all constant var specs are defined");
266
- }
267
- constantIndicesLength += 2;
268
- const subCount = ((_a = varSpec.subscriptIndices) == null ? void 0 : _a.length) || 0;
269
- constantIndicesLength += subCount;
270
- constantsLength += 1;
271
- }
272
- return {
273
- constantIndicesLength,
274
- constantsLength
275
- };
276
- }
277
- function encodeConstants(constantDefs, constantIndicesArray, constantsArray) {
278
- let ci = 0;
279
- constantIndicesArray[ci++] = constantDefs.length;
280
- let constantDataOffset = 0;
281
- for (const constantDef of constantDefs) {
282
- const varSpec = constantDef.varRef.varSpec;
283
- constantIndicesArray[ci++] = varSpec.varIndex;
284
- const subs = varSpec.subscriptIndices;
285
- const subCount = (subs == null ? void 0 : subs.length) || 0;
286
- constantIndicesArray[ci++] = subCount;
287
- for (let i = 0; i < subCount; i++) {
288
- constantIndicesArray[ci++] = subs[i];
289
- }
290
- constantsArray[constantDataOffset++] = constantDef.value;
291
- }
292
- }
293
- function decodeConstants(constantIndicesArray, constantsArray) {
294
- const constantDefs = [];
295
- let ci = 0;
296
- const constantCount = constantIndicesArray[ci++];
297
- for (let i = 0; i < constantCount; i++) {
298
- const varIndex = constantIndicesArray[ci++];
299
- const subCount = constantIndicesArray[ci++];
300
- const subscriptIndices = subCount > 0 ? Array(subCount) : void 0;
301
- for (let subIndex = 0; subIndex < subCount; subIndex++) {
302
- subscriptIndices[subIndex] = constantIndicesArray[ci++];
303
- }
304
- const varSpec = {
305
- varIndex,
306
- subscriptIndices
307
- };
308
- const value = constantsArray[i];
309
- constantDefs.push({
310
- varRef: {
311
- varSpec
312
- },
313
- value
314
- });
315
- }
316
- return constantDefs;
317
- }
318
- function getEncodedLookupBufferLengths(lookupDefs) {
319
- var _a, _b;
320
- let lookupIndicesLength = 1;
321
- let lookupsLength = 0;
322
- for (const lookupDef of lookupDefs) {
323
- const varSpec = lookupDef.varRef.varSpec;
324
- if (varSpec === void 0) {
325
- throw new Error("Cannot compute lookup buffer lengths until all lookup var specs are defined");
326
- }
327
- lookupIndicesLength += 2;
328
- const subCount = ((_a = varSpec.subscriptIndices) == null ? void 0 : _a.length) || 0;
329
- lookupIndicesLength += subCount;
330
- lookupIndicesLength += 2;
331
- lookupsLength += ((_b = lookupDef.points) == null ? void 0 : _b.length) || 0;
332
- }
333
- return {
334
- lookupIndicesLength,
335
- lookupsLength
336
- };
337
- }
338
- function encodeLookups(lookupDefs, lookupIndicesArray, lookupsArray) {
339
- let li = 0;
340
- lookupIndicesArray[li++] = lookupDefs.length;
341
- let lookupDataOffset = 0;
342
- for (const lookupDef of lookupDefs) {
343
- const varSpec = lookupDef.varRef.varSpec;
344
- lookupIndicesArray[li++] = varSpec.varIndex;
345
- const subs = varSpec.subscriptIndices;
346
- const subCount = (subs == null ? void 0 : subs.length) || 0;
347
- lookupIndicesArray[li++] = subCount;
348
- for (let i = 0; i < subCount; i++) {
349
- lookupIndicesArray[li++] = subs[i];
350
- }
351
- if (lookupDef.points !== void 0) {
352
- lookupIndicesArray[li++] = lookupDataOffset;
353
- lookupIndicesArray[li++] = lookupDef.points.length;
354
- lookupsArray == null ? void 0 : lookupsArray.set(lookupDef.points, lookupDataOffset);
355
- lookupDataOffset += lookupDef.points.length;
356
- } else {
357
- lookupIndicesArray[li++] = -1;
358
- lookupIndicesArray[li++] = 0;
359
- }
360
- }
361
- }
362
- function decodeLookups(lookupIndicesArray, lookupsArray) {
363
- const lookupDefs = [];
364
- let li = 0;
365
- const lookupCount = lookupIndicesArray[li++];
366
- for (let i = 0; i < lookupCount; i++) {
367
- const varIndex = lookupIndicesArray[li++];
368
- const subCount = lookupIndicesArray[li++];
369
- const subscriptIndices = subCount > 0 ? Array(subCount) : void 0;
370
- for (let subIndex = 0; subIndex < subCount; subIndex++) {
371
- subscriptIndices[subIndex] = lookupIndicesArray[li++];
372
- }
373
- const lookupDataOffset = lookupIndicesArray[li++];
374
- const lookupDataLength = lookupIndicesArray[li++];
375
- const varSpec = {
376
- varIndex,
377
- subscriptIndices
378
- };
379
- let points;
380
- if (lookupDataOffset >= 0) {
381
- if (lookupsArray) {
382
- points = lookupsArray.slice(lookupDataOffset, lookupDataOffset + lookupDataLength);
383
- } else {
384
- points = new Float64Array(0);
385
- }
386
- } else {
387
- points = void 0;
388
- }
389
- lookupDefs.push({
390
- varRef: {
391
- varSpec
392
- },
393
- points
394
- });
395
- }
396
- return lookupDefs;
397
- }
398
-
399
- // src/_shared/constant-def.ts
400
- function createConstantDef(varRef, value) {
401
- return {
402
- varRef,
403
- value
404
- };
405
- }
406
-
407
- // src/_shared/lookup-def.ts
408
- function createLookupDef(varRef, points) {
409
- let flatPoints;
410
- if (points) {
411
- flatPoints = new Float64Array(points.length * 2);
412
- let i = 0;
413
- for (const p of points) {
414
- flatPoints[i++] = p.x;
415
- flatPoints[i++] = p.y;
416
- }
417
- }
418
- return {
419
- varRef,
420
- points: flatPoints
421
- };
422
- }
423
-
424
- // src/model-listing/model-listing.ts
425
- var ModelListing = class {
426
- constructor(listingObj) {
427
- this.varSpecs = /* @__PURE__ */ new Map();
428
- const dimensions = /* @__PURE__ */ new Map();
429
- for (const dimInfo of listingObj.dimensions) {
430
- const dimId = dimInfo.id;
431
- const subscripts = [];
432
- for (let i = 0; i < dimInfo.subIds.length; i++) {
433
- subscripts.push({
434
- id: dimInfo.subIds[i],
435
- index: i
436
- });
437
- }
438
- dimensions.set(dimId, {
439
- id: dimId,
440
- subscripts
441
- });
442
- }
443
- function dimensionForId(dimId) {
444
- const dim = dimensions.get(dimId);
445
- if (dim === void 0) {
446
- throw new Error(`No dimension info found for id=${dimId}`);
447
- }
448
- return dim;
449
- }
450
- const baseVarIds = /* @__PURE__ */ new Set();
451
- for (const v of listingObj.variables) {
452
- const baseVarId = varIdWithoutSubscripts(v.id);
453
- if (!baseVarIds.has(baseVarId)) {
454
- const dimIds = v.dimIds || [];
455
- const dimensions2 = dimIds.map(dimensionForId);
456
- if (dimensions2.length > 0) {
457
- const dimSubs = [];
458
- for (const dim of dimensions2) {
459
- dimSubs.push(dim.subscripts);
460
- }
461
- const combos = cartesianProductOf(dimSubs);
462
- for (const combo of combos) {
463
- const subs = combo.map((sub) => sub.id).join(",");
464
- const subIndices = combo.map((sub) => sub.index);
465
- const fullVarId = `${baseVarId}[${subs}]`;
466
- this.varSpecs.set(fullVarId, {
467
- varIndex: v.index,
468
- subscriptIndices: subIndices
469
- });
470
- }
471
- } else {
472
- this.varSpecs.set(baseVarId, {
473
- varIndex: v.index
474
- });
475
- }
476
- baseVarIds.add(baseVarId);
477
- }
478
- }
479
- }
480
- /**
481
- * Return the `VarSpec` for the given variable ID, or undefined if there is no spec defined
482
- * in the listing for that variable.
483
- */
484
- getSpecForVarId(varId) {
485
- return this.varSpecs.get(varId);
486
- }
487
- /**
488
- * Return the `VarSpec` for the given variable name, or undefined if there is no spec defined
489
- * in the listing for that variable.
490
- */
491
- getSpecForVarName(varName) {
492
- const varId = sdeVarIdForVensimVarName(varName);
493
- return this.varSpecs.get(varId);
494
- }
495
- /**
496
- * Create a new `Outputs` instance that uses the same start/end years as the given "normal"
497
- * `Outputs` instance but is prepared for reading the specified internal variables from the model.
498
- *
499
- * @param normalOutputs The `Outputs` that is used to access normal output variables from the model.
500
- * @param varIds The variable IDs to include with the new `Outputs` instance.
501
- */
502
- deriveOutputs(normalOutputs, varIds) {
503
- const varSpecs = [];
504
- for (const varId of varIds) {
505
- const varSpec = this.varSpecs.get(varId);
506
- if (varSpec !== void 0) {
507
- varSpecs.push(varSpec);
508
- } else {
509
- console.warn(`WARNING: No output var spec found for id=${varId}`);
510
- }
511
- }
512
- const newOutputs = new Outputs(varIds, normalOutputs.startTime, normalOutputs.endTime, normalOutputs.saveFreq);
513
- newOutputs.varSpecs = varSpecs;
514
- return newOutputs;
515
- }
516
- };
517
- function varIdWithoutSubscripts(fullVarId) {
518
- const bracketIndex = fullVarId.indexOf("[");
519
- if (bracketIndex >= 0) {
520
- return fullVarId.substring(0, bracketIndex);
521
- } else {
522
- return fullVarId;
523
- }
524
- }
525
- function cartesianProductOf(arr) {
526
- return arr.reduce(
527
- (a, b) => {
528
- return a.map((x) => b.map((y) => x.concat([y]))).reduce((v, w) => v.concat(w), []);
529
- },
530
- [[]]
531
- );
532
- }
533
- function sdeVarIdForVensimName(name) {
534
- return "_" + name.trim().replace(/"/g, "_").replace(/\s+!$/g, "!").replace(/\s/g, "_").replace(/,/g, "_").replace(/-/g, "_").replace(/\./g, "_").replace(/\$/g, "_").replace(/'/g, "_").replace(/&/g, "_").replace(/%/g, "_").replace(/\//g, "_").replace(/\|/g, "_").toLowerCase();
535
- }
536
- function sdeVarIdForVensimVarName(varName) {
537
- const m = varName.match(/([^[]+)(?:\[([^\]]+)\])?/);
538
- if (!m) {
539
- throw new Error(`Invalid Vensim name: ${varName}`);
540
- }
541
- let id = sdeVarIdForVensimName(m[1]);
542
- if (m[2]) {
543
- const subscripts = m[2].split(",").map((x) => sdeVarIdForVensimName(x));
544
- id += `[${subscripts.join(",")}]`;
545
- }
546
- return id;
547
- }
548
-
549
- // src/runnable-model/resolve-var-ref.ts
550
- function resolveVarRef(listing, varRef, varKind) {
551
- if (varRef.varSpec) {
552
- return;
553
- }
554
- if (listing === void 0) {
555
- throw new Error(
556
- `Unable to resolve ${varKind} variable references by name or identifier when model listing is unavailable`
557
- );
558
- }
559
- if (varRef.varId) {
560
- const varSpec = listing == null ? void 0 : listing.getSpecForVarId(varRef.varId);
561
- if (varSpec) {
562
- varRef.varSpec = varSpec;
563
- } else {
564
- throw new Error(`Failed to resolve ${varKind} variable reference for varId=${varRef.varId}`);
565
- }
566
- } else {
567
- const varSpec = listing == null ? void 0 : listing.getSpecForVarName(varRef.varName);
568
- if (varSpec) {
569
- varRef.varSpec = varSpec;
570
- } else {
571
- throw new Error(`Failed to resolve ${varKind} variable reference for varName='${varRef.varId}'`);
572
- }
573
- }
574
- }
575
-
576
- // src/runnable-model/buffered-run-model-params.ts
577
- var headerLengthInElements = 20;
578
- var extrasLengthInElements = 1;
579
- var Int32Section = class {
580
- constructor() {
581
- this.offsetInBytes = 0;
582
- this.lengthInElements = 0;
583
- }
584
- update(encoded, offsetInBytes, lengthInElements) {
585
- this.view = lengthInElements > 0 ? new Int32Array(encoded, offsetInBytes, lengthInElements) : void 0;
586
- this.offsetInBytes = offsetInBytes;
587
- this.lengthInElements = lengthInElements;
588
- }
589
- };
590
- var Float64Section = class {
591
- constructor() {
592
- this.offsetInBytes = 0;
593
- this.lengthInElements = 0;
594
- }
595
- update(encoded, offsetInBytes, lengthInElements) {
596
- this.view = lengthInElements > 0 ? new Float64Array(encoded, offsetInBytes, lengthInElements) : void 0;
597
- this.offsetInBytes = offsetInBytes;
598
- this.lengthInElements = lengthInElements;
599
- }
600
- };
601
- var BufferedRunModelParams = class {
602
- /**
603
- * @param listing The model listing that is used to locate a variable that is referenced by
604
- * name or identifier. If undefined, variables cannot be referenced by name or identifier,
605
- * and can only be referenced using a valid `VarSpec`.
606
- */
607
- constructor(listing) {
608
- this.listing = listing;
609
- /**
610
- * The header section of the `encoded` buffer. The header declares the byte offset and length
611
- * (in elements) of each section of the buffer.
612
- */
613
- this.header = new Int32Section();
614
- /** The extras section of the `encoded` buffer (holds elapsed time, etc). */
615
- this.extras = new Float64Section();
616
- /** The inputs section of the `encoded` buffer. */
617
- this.inputs = new Float64Section();
618
- /** The outputs section of the `encoded` buffer. */
619
- this.outputs = new Float64Section();
620
- /** The output indices section of the `encoded` buffer. */
621
- this.outputIndices = new Int32Section();
622
- /** The constant values section of the `encoded` buffer. */
623
- this.constants = new Float64Section();
624
- /** The constant indices section of the `encoded` buffer. */
625
- this.constantIndices = new Int32Section();
626
- /** The lookup data section of the `encoded` buffer. */
627
- this.lookups = new Float64Section();
628
- /** The lookup indices section of the `encoded` buffer. */
629
- this.lookupIndices = new Int32Section();
630
- }
631
- /**
632
- * Return the encoded buffer from this instance, which can be passed to `updateFromEncodedBuffer`.
633
- */
634
- getEncodedBuffer() {
635
- return this.encoded;
636
- }
637
- // from RunModelParams interface
638
- getInputs() {
639
- return this.inputs.view;
640
- }
641
- // from RunModelParams interface
642
- copyInputs(array, create) {
643
- if (this.inputs.lengthInElements === 0) {
644
- return;
645
- }
646
- if (array === void 0 || array.length < this.inputs.lengthInElements) {
647
- array = create(this.inputs.lengthInElements);
648
- }
649
- array.set(this.inputs.view);
650
- }
651
- // from RunModelParams interface
652
- getOutputIndicesLength() {
653
- return this.outputIndices.lengthInElements;
654
- }
655
- // from RunModelParams interface
656
- getOutputIndices() {
657
- return this.outputIndices.view;
658
- }
659
- // from RunModelParams interface
660
- copyOutputIndices(array, create) {
661
- if (this.outputIndices.lengthInElements === 0) {
662
- return;
663
- }
664
- if (array === void 0 || array.length < this.outputIndices.lengthInElements) {
665
- array = create(this.outputIndices.lengthInElements);
666
- }
667
- array.set(this.outputIndices.view);
668
- }
669
- // from RunModelParams interface
670
- getOutputsLength() {
671
- return this.outputs.lengthInElements;
672
- }
673
- // from RunModelParams interface
674
- getOutputs() {
675
- return this.outputs.view;
676
- }
677
- // from RunModelParams interface
678
- getOutputsObject() {
679
- return void 0;
680
- }
681
- // from RunModelParams interface
682
- storeOutputs(array) {
683
- if (this.outputs.view === void 0) {
684
- return;
685
- }
686
- if (array.length > this.outputs.view.length) {
687
- this.outputs.view.set(array.subarray(0, this.outputs.view.length));
688
- } else {
689
- this.outputs.view.set(array);
690
- }
691
- }
692
- // from RunModelParams interface
693
- getConstants() {
694
- if (this.constantIndices.lengthInElements === 0) {
695
- return void 0;
696
- }
697
- return decodeConstants(this.constantIndices.view, this.constants.view);
698
- }
699
- // from RunModelParams interface
700
- getLookups() {
701
- if (this.lookupIndices.lengthInElements === 0) {
702
- return void 0;
703
- }
704
- return decodeLookups(this.lookupIndices.view, this.lookups.view);
705
- }
706
- // from RunModelParams interface
707
- getElapsedTime() {
708
- return this.extras.view[0];
709
- }
710
- // from RunModelParams interface
711
- storeElapsedTime(elapsed) {
712
- this.extras.view[0] = elapsed;
713
- }
714
- /**
715
- * Copy the outputs buffer to the given `Outputs` instance. This should be called
716
- * after the `runModel` call has completed so that the output values are copied from
717
- * the internal buffer to the `Outputs` instance that was passed to `runModel`.
718
- *
719
- * @param outputs The `Outputs` instance into which the output values will be copied.
720
- */
721
- finalizeOutputs(outputs) {
722
- if (this.outputs.view) {
723
- outputs.updateFromBuffer(this.outputs.view, outputs.seriesLength);
724
- }
725
- outputs.runTimeInMillis = this.getElapsedTime();
726
- }
727
- /**
728
- * Update this instance using the parameters that are passed to a `runModel` call.
729
- *
730
- * @param inputs The model input values (must be in the same order as in the spec file).
731
- * @param outputs The structure into which the model outputs will be stored.
732
- * @param options Additional options that influence the model run.
733
- */
734
- updateFromParams(inputs, outputs, options) {
735
- const inputsLengthInElements = inputs.length;
736
- const outputsLengthInElements = outputs.varIds.length * outputs.seriesLength;
737
- let outputIndicesLengthInElements;
738
- const outputVarSpecs = outputs.varSpecs;
739
- if (outputVarSpecs !== void 0 && outputVarSpecs.length > 0) {
740
- outputIndicesLengthInElements = getEncodedVarIndicesLength(outputVarSpecs);
741
- } else {
742
- outputIndicesLengthInElements = 0;
743
- }
744
- let constantsLengthInElements;
745
- let constantIndicesLengthInElements;
746
- if ((options == null ? void 0 : options.constants) !== void 0 && options.constants.length > 0) {
747
- for (const constantDef of options.constants) {
748
- resolveVarRef(this.listing, constantDef.varRef, "constant");
749
- }
750
- const encodedLengths = getEncodedConstantBufferLengths(options.constants);
751
- constantsLengthInElements = encodedLengths.constantsLength;
752
- constantIndicesLengthInElements = encodedLengths.constantIndicesLength;
753
- } else {
754
- constantsLengthInElements = 0;
755
- constantIndicesLengthInElements = 0;
756
- }
757
- let lookupsLengthInElements;
758
- let lookupIndicesLengthInElements;
759
- if ((options == null ? void 0 : options.lookups) !== void 0 && options.lookups.length > 0) {
760
- for (const lookupDef of options.lookups) {
761
- resolveVarRef(this.listing, lookupDef.varRef, "lookup");
762
- }
763
- const encodedLengths = getEncodedLookupBufferLengths(options.lookups);
764
- lookupsLengthInElements = encodedLengths.lookupsLength;
765
- lookupIndicesLengthInElements = encodedLengths.lookupIndicesLength;
766
- } else {
767
- lookupsLengthInElements = 0;
768
- lookupIndicesLengthInElements = 0;
769
- }
770
- let byteOffset = 0;
771
- function section(kind, lengthInElements) {
772
- const sectionOffsetInBytes = byteOffset;
773
- const bytesPerElement = kind === "float64" ? Float64Array.BYTES_PER_ELEMENT : Int32Array.BYTES_PER_ELEMENT;
774
- const requiredSectionLengthInBytes = Math.round(lengthInElements * bytesPerElement);
775
- const alignedSectionLengthInBytes = Math.ceil(requiredSectionLengthInBytes / 8) * 8;
776
- byteOffset += alignedSectionLengthInBytes;
777
- return sectionOffsetInBytes;
778
- }
779
- const headerOffsetInBytes = section("int32", headerLengthInElements);
780
- const extrasOffsetInBytes = section("float64", extrasLengthInElements);
781
- const inputsOffsetInBytes = section("float64", inputsLengthInElements);
782
- const outputsOffsetInBytes = section("float64", outputsLengthInElements);
783
- const outputIndicesOffsetInBytes = section("int32", outputIndicesLengthInElements);
784
- const constantsOffsetInBytes = section("float64", constantsLengthInElements);
785
- const constantIndicesOffsetInBytes = section("int32", constantIndicesLengthInElements);
786
- const lookupsOffsetInBytes = section("float64", lookupsLengthInElements);
787
- const lookupIndicesOffsetInBytes = section("int32", lookupIndicesLengthInElements);
788
- const requiredLengthInBytes = byteOffset;
789
- if (this.encoded === void 0 || this.encoded.byteLength < requiredLengthInBytes) {
790
- const totalLengthInBytes = Math.ceil(requiredLengthInBytes * 1.2);
791
- this.encoded = new ArrayBuffer(totalLengthInBytes);
792
- this.header.update(this.encoded, headerOffsetInBytes, headerLengthInElements);
793
- }
794
- const headerView = this.header.view;
795
- let headerIndex = 0;
796
- headerView[headerIndex++] = extrasOffsetInBytes;
797
- headerView[headerIndex++] = extrasLengthInElements;
798
- headerView[headerIndex++] = inputsOffsetInBytes;
799
- headerView[headerIndex++] = inputsLengthInElements;
800
- headerView[headerIndex++] = outputsOffsetInBytes;
801
- headerView[headerIndex++] = outputsLengthInElements;
802
- headerView[headerIndex++] = outputIndicesOffsetInBytes;
803
- headerView[headerIndex++] = outputIndicesLengthInElements;
804
- headerView[headerIndex++] = constantsOffsetInBytes;
805
- headerView[headerIndex++] = constantsLengthInElements;
806
- headerView[headerIndex++] = constantIndicesOffsetInBytes;
807
- headerView[headerIndex++] = constantIndicesLengthInElements;
808
- headerView[headerIndex++] = lookupsOffsetInBytes;
809
- headerView[headerIndex++] = lookupsLengthInElements;
810
- headerView[headerIndex++] = lookupIndicesOffsetInBytes;
811
- headerView[headerIndex++] = lookupIndicesLengthInElements;
812
- this.inputs.update(this.encoded, inputsOffsetInBytes, inputsLengthInElements);
813
- this.extras.update(this.encoded, extrasOffsetInBytes, extrasLengthInElements);
814
- this.outputs.update(this.encoded, outputsOffsetInBytes, outputsLengthInElements);
815
- this.outputIndices.update(this.encoded, outputIndicesOffsetInBytes, outputIndicesLengthInElements);
816
- this.constants.update(this.encoded, constantsOffsetInBytes, constantsLengthInElements);
817
- this.constantIndices.update(this.encoded, constantIndicesOffsetInBytes, constantIndicesLengthInElements);
818
- this.lookups.update(this.encoded, lookupsOffsetInBytes, lookupsLengthInElements);
819
- this.lookupIndices.update(this.encoded, lookupIndicesOffsetInBytes, lookupIndicesLengthInElements);
820
- const inputsView = this.inputs.view;
821
- for (let i = 0; i < inputs.length; i++) {
822
- const input = inputs[i];
823
- if (typeof input === "number") {
824
- inputsView[i] = input;
825
- } else {
826
- inputsView[i] = input.get();
827
- }
828
- }
829
- if (this.outputIndices.view) {
830
- encodeVarIndices(outputVarSpecs, this.outputIndices.view);
831
- }
832
- if (constantIndicesLengthInElements > 0) {
833
- encodeConstants(options.constants, this.constantIndices.view, this.constants.view);
834
- }
835
- if (lookupIndicesLengthInElements > 0) {
836
- encodeLookups(options.lookups, this.lookupIndices.view, this.lookups.view);
837
- }
838
- }
839
- /**
840
- * Update this instance using the values contained in the encoded buffer from another
841
- * `BufferedRunModelParams` instance.
842
- *
843
- * @param buffer An encoded buffer returned by `getEncodedBuffer`.
844
- */
845
- updateFromEncodedBuffer(buffer) {
846
- const headerLengthInBytes = headerLengthInElements * Int32Array.BYTES_PER_ELEMENT;
847
- if (buffer.byteLength < headerLengthInBytes) {
848
- throw new Error("Buffer must be long enough to contain header section");
849
- }
850
- this.encoded = buffer;
851
- const headerOffsetInBytes = 0;
852
- this.header.update(this.encoded, headerOffsetInBytes, headerLengthInElements);
853
- const headerView = this.header.view;
854
- let headerIndex = 0;
855
- const extrasOffsetInBytes = headerView[headerIndex++];
856
- const extrasLengthInElements2 = headerView[headerIndex++];
857
- const inputsOffsetInBytes = headerView[headerIndex++];
858
- const inputsLengthInElements = headerView[headerIndex++];
859
- const outputsOffsetInBytes = headerView[headerIndex++];
860
- const outputsLengthInElements = headerView[headerIndex++];
861
- const outputIndicesOffsetInBytes = headerView[headerIndex++];
862
- const outputIndicesLengthInElements = headerView[headerIndex++];
863
- const constantsOffsetInBytes = headerView[headerIndex++];
864
- const constantsLengthInElements = headerView[headerIndex++];
865
- const constantIndicesOffsetInBytes = headerView[headerIndex++];
866
- const constantIndicesLengthInElements = headerView[headerIndex++];
867
- const lookupsOffsetInBytes = headerView[headerIndex++];
868
- const lookupsLengthInElements = headerView[headerIndex++];
869
- const lookupIndicesOffsetInBytes = headerView[headerIndex++];
870
- const lookupIndicesLengthInElements = headerView[headerIndex++];
871
- const extrasLengthInBytes = extrasLengthInElements2 * Float64Array.BYTES_PER_ELEMENT;
872
- const inputsLengthInBytes = inputsLengthInElements * Float64Array.BYTES_PER_ELEMENT;
873
- const outputsLengthInBytes = outputsLengthInElements * Float64Array.BYTES_PER_ELEMENT;
874
- const outputIndicesLengthInBytes = outputIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT;
875
- const constantsLengthInBytes = constantsLengthInElements * Float64Array.BYTES_PER_ELEMENT;
876
- const constantIndicesLengthInBytes = constantIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT;
877
- const lookupsLengthInBytes = lookupsLengthInElements * Float64Array.BYTES_PER_ELEMENT;
878
- const lookupIndicesLengthInBytes = lookupIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT;
879
- const requiredLengthInBytes = headerLengthInBytes + extrasLengthInBytes + inputsLengthInBytes + outputsLengthInBytes + outputIndicesLengthInBytes + constantsLengthInBytes + constantIndicesLengthInBytes + lookupsLengthInBytes + lookupIndicesLengthInBytes;
880
- if (buffer.byteLength < requiredLengthInBytes) {
881
- throw new Error("Buffer must be long enough to contain sections declared in header");
882
- }
883
- this.extras.update(this.encoded, extrasOffsetInBytes, extrasLengthInElements2);
884
- this.inputs.update(this.encoded, inputsOffsetInBytes, inputsLengthInElements);
885
- this.outputs.update(this.encoded, outputsOffsetInBytes, outputsLengthInElements);
886
- this.outputIndices.update(this.encoded, outputIndicesOffsetInBytes, outputIndicesLengthInElements);
887
- this.constants.update(this.encoded, constantsOffsetInBytes, constantsLengthInElements);
888
- this.constantIndices.update(this.encoded, constantIndicesOffsetInBytes, constantIndicesLengthInElements);
889
- this.lookups.update(this.encoded, lookupsOffsetInBytes, lookupsLengthInElements);
890
- this.lookupIndices.update(this.encoded, lookupIndicesOffsetInBytes, lookupIndicesLengthInElements);
891
- }
892
- };
893
-
894
- // src/runnable-model/referenced-run-model-params.ts
895
- var ReferencedRunModelParams = class {
896
- /**
897
- * @param listing The model listing that is used to locate a variable that is referenced by
898
- * name or identifier. If undefined, variables cannot be referenced by name or identifier,
899
- * and can only be referenced using a valid `VarSpec`.
900
- */
901
- constructor(listing) {
902
- this.listing = listing;
903
- this.outputsLengthInElements = 0;
904
- this.outputIndicesLengthInElements = 0;
905
- }
906
- // from RunModelParams interface
907
- getInputs() {
908
- return void 0;
909
- }
910
- // from RunModelParams interface
911
- copyInputs(array, create) {
912
- const inputsLengthInElements = this.inputs.length;
913
- if (array === void 0 || array.length < inputsLengthInElements) {
914
- array = create(inputsLengthInElements);
915
- }
916
- for (let i = 0; i < this.inputs.length; i++) {
917
- const input = this.inputs[i];
918
- if (typeof input === "number") {
919
- array[i] = input;
920
- } else {
921
- array[i] = input.get();
922
- }
923
- }
924
- }
925
- // from RunModelParams interface
926
- getOutputIndicesLength() {
927
- return this.outputIndicesLengthInElements;
928
- }
929
- // from RunModelParams interface
930
- getOutputIndices() {
931
- return void 0;
932
- }
933
- // from RunModelParams interface
934
- copyOutputIndices(array, create) {
935
- if (this.outputIndicesLengthInElements === 0) {
936
- return;
937
- }
938
- if (array === void 0 || array.length < this.outputIndicesLengthInElements) {
939
- array = create(this.outputIndicesLengthInElements);
940
- }
941
- encodeVarIndices(this.outputs.varSpecs, array);
942
- }
943
- // from RunModelParams interface
944
- getOutputsLength() {
945
- return this.outputsLengthInElements;
946
- }
947
- // from RunModelParams interface
948
- getOutputs() {
949
- return void 0;
950
- }
951
- // from RunModelParams interface
952
- getOutputsObject() {
953
- return this.outputs;
954
- }
955
- // from RunModelParams interface
956
- storeOutputs(array) {
957
- if (this.outputs) {
958
- const result = this.outputs.updateFromBuffer(array, this.outputs.seriesLength);
959
- if (result.isErr()) {
960
- throw new Error(`Failed to store outputs: ${result.error}`);
961
- }
962
- }
963
- }
964
- // from RunModelParams interface
965
- getConstants() {
966
- if (this.constants !== void 0 && this.constants.length > 0) {
967
- return this.constants;
968
- } else {
969
- return void 0;
970
- }
971
- }
972
- // from RunModelParams interface
973
- getLookups() {
974
- if (this.lookups !== void 0 && this.lookups.length > 0) {
975
- return this.lookups;
976
- } else {
977
- return void 0;
978
- }
979
- }
980
- // from RunModelParams interface
981
- getElapsedTime() {
982
- var _a;
983
- return (_a = this.outputs) == null ? void 0 : _a.runTimeInMillis;
984
- }
985
- // from RunModelParams interface
986
- storeElapsedTime(elapsed) {
987
- if (this.outputs) {
988
- this.outputs.runTimeInMillis = elapsed;
989
- }
990
- }
991
- /**
992
- * Update this instance using the parameters that are passed to a `runModel` call.
993
- *
994
- * @param inputs The model input values (must be in the same order as in the spec file).
995
- * @param outputs The structure into which the model outputs will be stored.
996
- * @param options Additional options that influence the model run.
997
- */
998
- updateFromParams(inputs, outputs, options) {
999
- this.inputs = inputs;
1000
- this.outputs = outputs;
1001
- this.outputsLengthInElements = outputs.varIds.length * outputs.seriesLength;
1002
- this.constants = options == null ? void 0 : options.constants;
1003
- this.lookups = options == null ? void 0 : options.lookups;
1004
- if (this.constants) {
1005
- for (const constantDef of this.constants) {
1006
- resolveVarRef(this.listing, constantDef.varRef, "constant");
1007
- }
1008
- }
1009
- if (this.lookups) {
1010
- for (const lookupDef of this.lookups) {
1011
- resolveVarRef(this.listing, lookupDef.varRef, "lookup");
1012
- }
1013
- }
1014
- const outputVarSpecs = outputs.varSpecs;
1015
- if (outputVarSpecs !== void 0 && outputVarSpecs.length > 0) {
1016
- this.outputIndicesLengthInElements = getEncodedVarIndicesLength(outputVarSpecs);
1017
- } else {
1018
- this.outputIndicesLengthInElements = 0;
1019
- }
1020
- }
1021
- };
1022
-
1023
- // src/js-model/js-model-constants.ts
1024
- var _NA_ = -Number.MAX_VALUE;
1025
-
1026
- // src/js-model/js-model-lookup.ts
1027
- var JsModelLookup = class {
1028
- /**
1029
- * @param size The number of (x,y) pairs in the lookup.
1030
- * @param data The lookup data, as (x,y) pairs. The length of the array must be
1031
- * >= 2*n. Note that the data will be stored by reference, so if there is a chance
1032
- * that the array will be reused or modified by other code, be sure to pass in a
1033
- * copy of the array.
1034
- */
1035
- constructor(size, data) {
1036
- if (data && data.length < size * 2) {
1037
- throw new Error(`Lookup data array length must be >= 2*size (length=${data.length} size=${size}`);
1038
- }
1039
- this.originalData = data;
1040
- this.originalSize = size;
1041
- this.dynamicData = void 0;
1042
- this.dynamicSize = 0;
1043
- this.activeData = this.originalData;
1044
- this.activeSize = this.originalSize;
1045
- this.lastInput = Number.MAX_VALUE;
1046
- this.lastHitIndex = 0;
1047
- }
1048
- /**
1049
- * Set new data for this lookup instance, or restore the original data.
1050
- *
1051
- * If `data` is undefined, the original data that was supplied to the constructor will
1052
- * be restored as the "active" data. Otherwise, `data` will be copied to an internal
1053
- * data buffer, which will be the "active" data. If `size` is greater than the size
1054
- * passed to previous calls, the internal data buffer will be grown as needed.
1055
- *
1056
- * @param size The number of (x,y) pairs in the lookup.
1057
- * @param data The lookup data, as (x,y) pairs. The length of the array must be
1058
- * >= 2*n. Note that the data will be copied into an internal data buffer, so it
1059
- * is not necessary to defensively copy data before calling this method.
1060
- */
1061
- setData(size, data) {
1062
- if (data) {
1063
- if (data.length < size * 2) {
1064
- throw new Error(`Lookup data array length must be >= 2*size (length=${data.length} size=${size}`);
1065
- }
1066
- const dataLengthInElems = size * 2;
1067
- if (this.dynamicData === void 0 || dataLengthInElems > this.dynamicData.length) {
1068
- this.dynamicData = new Float64Array(dataLengthInElems);
1069
- }
1070
- this.dynamicSize = size;
1071
- if (size > 0) {
1072
- const subarray = data.subarray(0, dataLengthInElems);
1073
- this.dynamicData.set(subarray);
1074
- }
1075
- this.activeData = this.dynamicData;
1076
- this.activeSize = this.dynamicSize;
1077
- } else {
1078
- this.activeData = this.originalData;
1079
- this.activeSize = this.originalSize;
1080
- }
1081
- this.invertedData = void 0;
1082
- this.lastInput = Number.MAX_VALUE;
1083
- this.lastHitIndex = 0;
1084
- }
1085
- getValueForX(x, mode) {
1086
- return this.getValue(x, false, mode);
1087
- }
1088
- getValueForY(y) {
1089
- if (this.invertedData === void 0) {
1090
- const numValues = this.activeSize * 2;
1091
- const normalData = this.activeData;
1092
- const invertedData = Array(numValues);
1093
- for (let i = 0; i < numValues; i += 2) {
1094
- invertedData[i] = normalData[i + 1];
1095
- invertedData[i + 1] = normalData[i];
1096
- }
1097
- this.invertedData = invertedData;
1098
- }
1099
- return this.getValue(y, true, "interpolate");
1100
- }
1101
- /**
1102
- * Interpolate the y value from the array of (x,y) pairs.
1103
- * NOTE: The x values are assumed to be monotonically increasing.
1104
- */
1105
- getValue(input, useInvertedData, mode) {
1106
- if (this.activeSize === 0) {
1107
- return _NA_;
1108
- }
1109
- const data = useInvertedData ? this.invertedData : this.activeData;
1110
- const max = this.activeSize * 2;
1111
- const useCachedValues = !useInvertedData;
1112
- let startIndex;
1113
- if (useCachedValues && input >= this.lastInput) {
1114
- startIndex = this.lastHitIndex;
1115
- } else {
1116
- startIndex = 0;
1117
- }
1118
- for (let xi = startIndex; xi < max; xi += 2) {
1119
- const x = data[xi];
1120
- if (x >= input) {
1121
- if (useCachedValues) {
1122
- this.lastInput = input;
1123
- this.lastHitIndex = xi;
1124
- }
1125
- if (xi === 0 || x === input) {
1126
- return data[xi + 1];
1127
- }
1128
- switch (mode) {
1129
- default:
1130
- case "interpolate": {
1131
- const last_x = data[xi - 2];
1132
- const last_y = data[xi - 1];
1133
- const y = data[xi + 1];
1134
- const dx = x - last_x;
1135
- const dy = y - last_y;
1136
- return last_y + dy / dx * (input - last_x);
1137
- }
1138
- case "forward":
1139
- return data[xi + 1];
1140
- case "backward":
1141
- return data[xi - 1];
1142
- }
1143
- }
1144
- }
1145
- if (useCachedValues) {
1146
- this.lastInput = input;
1147
- this.lastHitIndex = max;
1148
- }
1149
- return data[max - 1];
1150
- }
1151
- /**
1152
- * Return the most appropriate y value from the array of (x,y) pairs when
1153
- * this instance is used to provide inputs for the `GAME` function.
1154
- *
1155
- * NOTE: The x values are assumed to be monotonically increasing.
1156
- *
1157
- * This method is similar to `getValueForX` in concept, except that this one
1158
- * returns the provided `defaultValue` if the `time` parameter is earlier than
1159
- * the first data point in the lookup. Also, this method always uses the
1160
- * `backward` interpolation mode, meaning that it holds the "current" value
1161
- * constant instead of interpolating.
1162
- *
1163
- * @param time The time that is used to select the data point that has an
1164
- * `x` value less than or equal to the provided time.
1165
- * @param defaultValue The value that is returned if this lookup is empty (has
1166
- * no points) or if the provided time is earlier than the first data point.
1167
- */
1168
- getValueForGameTime(time, defaultValue) {
1169
- if (this.activeSize <= 0) {
1170
- return defaultValue;
1171
- }
1172
- const x0 = this.activeData[0];
1173
- if (time < x0) {
1174
- return defaultValue;
1175
- }
1176
- return this.getValue(time, false, "backward");
1177
- }
1178
- /**
1179
- * Interpolate the y value from the array of (x,y) pairs.
1180
- * NOTE: The x values are assumed to be monotonically increasing.
1181
- *
1182
- * This method is similar to `getValue` in concept, but Vensim produces results for
1183
- * the `GET DATA BETWEEN TIMES` function that differ in unexpected ways from normal
1184
- * lookup behavior, so we implement it as a separate method here.
1185
- */
1186
- getValueBetweenTimes(input, mode) {
1187
- if (this.activeSize === 0) {
1188
- return _NA_;
1189
- }
1190
- const data = this.activeData;
1191
- const max = this.activeSize * 2;
1192
- switch (mode) {
1193
- case "forward": {
1194
- input = Math.floor(input);
1195
- for (let xi = 0; xi < max; xi += 2) {
1196
- const x = data[xi];
1197
- if (x >= input) {
1198
- return data[xi + 1];
1199
- }
1200
- }
1201
- return data[max - 1];
1202
- }
1203
- case "backward": {
1204
- input = Math.floor(input);
1205
- for (let xi = 2; xi < max; xi += 2) {
1206
- const x = data[xi];
1207
- if (x >= input) {
1208
- return data[xi - 1];
1209
- }
1210
- }
1211
- if (max >= 4) {
1212
- return data[max - 3];
1213
- } else {
1214
- return data[1];
1215
- }
1216
- }
1217
- case "interpolate":
1218
- default: {
1219
- if (input - Math.floor(input) > 0) {
1220
- let msg = `GET DATA BETWEEN TIMES was called with an input value (${input}) that has a fractional part. `;
1221
- msg += "When mode is 0 (interpolate) and the input value is not a whole number, Vensim produces unexpected ";
1222
- msg += "results that may differ from those produced by SDEverywhere.";
1223
- throw new Error(msg);
1224
- }
1225
- for (let xi = 2; xi < max; xi += 2) {
1226
- const x = data[xi];
1227
- if (x >= input) {
1228
- const last_x = data[xi - 2];
1229
- const last_y = data[xi - 1];
1230
- const y = data[xi + 1];
1231
- const dx = x - last_x;
1232
- const dy = y - last_y;
1233
- return last_y + dy / dx * (input - last_x);
1234
- }
1235
- }
1236
- return data[max - 1];
1237
- }
1238
- }
1239
- }
1240
- };
1241
-
1242
- // src/js-model/js-model-functions.ts
1243
- var EPSILON = 1e-6;
1244
- function getJsModelFunctions() {
1245
- let ctx;
1246
- const cachedVectors = /* @__PURE__ */ new Map();
1247
- const cachedSortVectors = /* @__PURE__ */ new Map();
1248
- const cachedInvertWorkMatrices = /* @__PURE__ */ new Map();
1249
- const cachedInvertResultMatrices = /* @__PURE__ */ new Map();
1250
- return {
1251
- setContext(context) {
1252
- ctx = context;
1253
- },
1254
- ABS(x) {
1255
- return Math.abs(x);
1256
- },
1257
- ARCCOS(x) {
1258
- return Math.acos(x);
1259
- },
1260
- ARCSIN(x) {
1261
- return Math.asin(x);
1262
- },
1263
- ARCTAN(x) {
1264
- return Math.atan(x);
1265
- },
1266
- COS(x) {
1267
- return Math.cos(x);
1268
- },
1269
- EXP(x) {
1270
- return Math.exp(x);
1271
- },
1272
- GAME(inputs, x) {
1273
- return inputs ? inputs.getValueForGameTime(ctx.currentTime, x) : x;
1274
- },
1275
- // GAMMA_LN(): number {
1276
- // throw new Error('GAMMA_LN function not yet implemented for JS target')
1277
- // },
1278
- INTEG(value, rate) {
1279
- return value + rate * ctx.timeStep;
1280
- },
1281
- INTEGER(x) {
1282
- return Math.trunc(x);
1283
- },
1284
- INVERT_MATRIX(matrix, n) {
1285
- let work = cachedInvertWorkMatrices.get(n);
1286
- if (work === void 0) {
1287
- work = Array(n);
1288
- for (let i = 0; i < n; i++) {
1289
- work[i] = Array(2 * n);
1290
- }
1291
- cachedInvertWorkMatrices.set(n, work);
1292
- }
1293
- let result = cachedInvertResultMatrices.get(n);
1294
- if (result === void 0) {
1295
- result = Array(n);
1296
- for (let i = 0; i < n; i++) {
1297
- result[i] = Array(n);
1298
- }
1299
- cachedInvertResultMatrices.set(n, result);
1300
- }
1301
- for (let i = 0; i < n; i++) {
1302
- for (let j = 0; j < n; j++) {
1303
- work[i][j] = matrix[i][j];
1304
- work[i][n + j] = i === j ? 1 : 0;
1305
- }
1306
- }
1307
- for (let k = 0; k < n; k++) {
1308
- let pivot = k;
1309
- let max = Math.abs(work[k][k]);
1310
- for (let i = k + 1; i < n; i++) {
1311
- const v = Math.abs(work[i][k]);
1312
- if (v > max) {
1313
- max = v;
1314
- pivot = i;
1315
- }
1316
- }
1317
- if (max === 0) {
1318
- for (let i = 0; i < n; i++) {
1319
- for (let j = 0; j < n; j++) {
1320
- result[i][j] = _NA_;
1321
- }
1322
- }
1323
- return result;
1324
- }
1325
- if (pivot !== k) {
1326
- const tmpRow = work[k];
1327
- work[k] = work[pivot];
1328
- work[pivot] = tmpRow;
1329
- }
1330
- const p = work[k][k];
1331
- for (let j = 0; j < 2 * n; j++) {
1332
- work[k][j] /= p;
1333
- }
1334
- for (let i = 0; i < n; i++) {
1335
- if (i !== k) {
1336
- const f = work[i][k];
1337
- if (f !== 0) {
1338
- for (let j = 0; j < 2 * n; j++) {
1339
- work[i][j] -= f * work[k][j];
1340
- }
1341
- }
1342
- }
1343
- }
1344
- }
1345
- for (let i = 0; i < n; i++) {
1346
- for (let j = 0; j < n; j++) {
1347
- result[i][j] = work[i][n + j];
1348
- }
1349
- }
1350
- return result;
1351
- },
1352
- LN(x) {
1353
- return Math.log(x);
1354
- },
1355
- MAX(x, y) {
1356
- return Math.max(x, y);
1357
- },
1358
- MIN(x, y) {
1359
- return Math.min(x, y);
1360
- },
1361
- MODULO(x, y) {
1362
- return x % y;
1363
- },
1364
- POW(x, y) {
1365
- return Math.pow(x, y);
1366
- },
1367
- POWER(x, y) {
1368
- return Math.pow(x, y);
1369
- },
1370
- PULSE(start, width) {
1371
- return pulse(ctx, start, width);
1372
- },
1373
- PULSE_TRAIN(start, width, interval, end) {
1374
- const n = Math.floor((end - start) / interval);
1375
- for (let k = 0; k <= n; k++) {
1376
- if (ctx.currentTime <= end && pulse(ctx, start + k * interval, width)) {
1377
- return 1;
1378
- }
1379
- }
1380
- return 0;
1381
- },
1382
- QUANTUM(x, y) {
1383
- return y <= 0 ? x : y * Math.trunc(x / y);
1384
- },
1385
- RAMP(slope, startTime, endTime) {
1386
- if (ctx.currentTime > startTime) {
1387
- if (ctx.currentTime < endTime || startTime > endTime) {
1388
- return slope * (ctx.currentTime - startTime);
1389
- } else {
1390
- return slope * (endTime - startTime);
1391
- }
1392
- } else {
1393
- return 0;
1394
- }
1395
- },
1396
- SIN(x) {
1397
- return Math.sin(x);
1398
- },
1399
- SQRT(x) {
1400
- return Math.sqrt(x);
1401
- },
1402
- STEP(height, stepTime) {
1403
- return ctx.currentTime + ctx.timeStep / 2 > stepTime ? height : 0;
1404
- },
1405
- TAN(x) {
1406
- return Math.tan(x);
1407
- },
1408
- VECTOR_SORT_ORDER(vector, size, direction) {
1409
- if (size > vector.length) {
1410
- throw new Error(`VECTOR SORT ORDER input vector length (${vector.length}) must be >= size (${size})`);
1411
- }
1412
- let sortVector = cachedSortVectors.get(size);
1413
- if (sortVector === void 0) {
1414
- sortVector = Array(size);
1415
- for (let i = 0; i < size; i++) {
1416
- sortVector[i] = { x: 0, ind: 0 };
1417
- }
1418
- cachedSortVectors.set(size, sortVector);
1419
- }
1420
- let outArray = cachedVectors.get(size);
1421
- if (outArray === void 0) {
1422
- outArray = Array(size);
1423
- cachedVectors.set(size, outArray);
1424
- }
1425
- for (let i = 0; i < size; i++) {
1426
- sortVector[i].x = vector[i];
1427
- sortVector[i].ind = i;
1428
- }
1429
- const sortOrder = direction > 0 ? 1 : -1;
1430
- sortVector.sort((a, b) => {
1431
- let result;
1432
- if (a.x < b.x) {
1433
- result = -1;
1434
- } else if (a.x > b.x) {
1435
- result = 1;
1436
- } else {
1437
- result = 0;
1438
- }
1439
- return result * sortOrder;
1440
- });
1441
- for (let i = 0; i < size; i++) {
1442
- outArray[i] = sortVector[i].ind;
1443
- }
1444
- return outArray;
1445
- },
1446
- XIDZ(a, b, x) {
1447
- return Math.abs(b) < EPSILON ? x : a / b;
1448
- },
1449
- ZIDZ(a, b) {
1450
- if (Math.abs(b) < EPSILON) {
1451
- return 0;
1452
- } else {
1453
- return a / b;
1454
- }
1455
- },
1456
- //
1457
- // Lookup functions
1458
- //
1459
- createLookup(size, data) {
1460
- return new JsModelLookup(size, data);
1461
- },
1462
- LOOKUP(lookup, x) {
1463
- return lookup ? lookup.getValueForX(x, "interpolate") : _NA_;
1464
- },
1465
- LOOKUP_FORWARD(lookup, x) {
1466
- return lookup ? lookup.getValueForX(x, "forward") : _NA_;
1467
- },
1468
- LOOKUP_BACKWARD(lookup, x) {
1469
- return lookup ? lookup.getValueForX(x, "backward") : _NA_;
1470
- },
1471
- LOOKUP_INVERT(lookup, y) {
1472
- return lookup ? lookup.getValueForY(y) : _NA_;
1473
- },
1474
- WITH_LOOKUP(x, lookup) {
1475
- return lookup ? lookup.getValueForX(x, "interpolate") : _NA_;
1476
- },
1477
- GET_DATA_BETWEEN_TIMES(lookup, x, mode) {
1478
- let lookupMode;
1479
- if (mode >= 1) {
1480
- lookupMode = "forward";
1481
- } else if (mode <= -1) {
1482
- lookupMode = "backward";
1483
- } else {
1484
- lookupMode = "interpolate";
1485
- }
1486
- return lookup ? lookup.getValueBetweenTimes(x, lookupMode) : _NA_;
1487
- }
1488
- };
1489
- }
1490
- function pulse(ctx, start, width) {
1491
- const timePlus = ctx.currentTime + ctx.timeStep / 2;
1492
- if (width === 0) {
1493
- width = ctx.timeStep;
1494
- }
1495
- return timePlus > start && timePlus < start + width ? 1 : 0;
1496
- }
1497
-
1498
- // src/perf/perf.ts
1499
- var isWeb;
1500
- function perfNow() {
1501
- if (isWeb === void 0) {
1502
- isWeb = typeof self !== "undefined" && (self == null ? void 0 : self.performance) !== void 0;
1503
- }
1504
- if (isWeb) {
1505
- return self.performance.now();
1506
- } else {
1507
- return process == null ? void 0 : process.hrtime();
1508
- }
1509
- }
1510
- function perfElapsed(t0) {
1511
- if (isWeb) {
1512
- const t1 = self.performance.now();
1513
- return t1 - t0;
1514
- } else {
1515
- const elapsed = process.hrtime(t0);
1516
- return (elapsed[0] * 1e9 + elapsed[1]) / 1e6;
1517
- }
1518
- }
1519
-
1520
- // src/runnable-model/base-runnable-model.ts
1521
- var BaseRunnableModel = class {
1522
- constructor(options) {
1523
- this.startTime = options.startTime;
1524
- this.endTime = options.endTime;
1525
- this.saveFreq = options.saveFreq;
1526
- this.numSavePoints = options.numSavePoints;
1527
- this.outputVarIds = options.outputVarIds;
1528
- this.modelListing = options.modelListing;
1529
- this.onRunModel = options.onRunModel;
1530
- }
1531
- // from RunnableModel interface
1532
- runModel(params) {
1533
- var _a;
1534
- let inputsArray = params.getInputs();
1535
- if (inputsArray === void 0) {
1536
- params.copyInputs(this.inputs, (numElements) => {
1537
- this.inputs = new Float64Array(numElements);
1538
- return this.inputs;
1539
- });
1540
- inputsArray = this.inputs;
1541
- }
1542
- let outputIndicesArray = params.getOutputIndices();
1543
- if (outputIndicesArray === void 0 && params.getOutputIndicesLength() > 0) {
1544
- params.copyOutputIndices(this.outputIndices, (numElements) => {
1545
- this.outputIndices = new Int32Array(numElements);
1546
- return this.outputIndices;
1547
- });
1548
- outputIndicesArray = this.outputIndices;
1549
- }
1550
- const outputsLengthInElements = params.getOutputsLength();
1551
- if (this.outputs === void 0 || this.outputs.length < outputsLengthInElements) {
1552
- this.outputs = new Float64Array(outputsLengthInElements);
1553
- }
1554
- const outputsArray = this.outputs;
1555
- const t0 = perfNow();
1556
- (_a = this.onRunModel) == null ? void 0 : _a.call(this, inputsArray, outputsArray, {
1557
- outputIndices: outputIndicesArray,
1558
- constants: params.getConstants(),
1559
- lookups: params.getLookups()
1560
- });
1561
- const elapsed = perfElapsed(t0);
1562
- params.storeOutputs(outputsArray);
1563
- params.storeElapsedTime(elapsed);
1564
- }
1565
- // from RunnableModel interface
1566
- terminate() {
1567
- }
1568
- };
1569
-
1570
- // src/js-model/js-model.ts
1571
- function initJsModel(model) {
1572
- let fns = model.getModelFunctions();
1573
- if (fns === void 0) {
1574
- fns = getJsModelFunctions();
1575
- model.setModelFunctions(fns);
1576
- }
1577
- const initialTime = model.getInitialTime();
1578
- const finalTime = model.getFinalTime();
1579
- const timeStep = model.getTimeStep();
1580
- const saveFreq = model.getSaveFreq();
1581
- const numSavePoints = Math.round((finalTime - initialTime) / saveFreq) + 1;
1582
- return new BaseRunnableModel({
1583
- startTime: initialTime,
1584
- endTime: finalTime,
1585
- saveFreq,
1586
- numSavePoints,
1587
- outputVarIds: model.outputVarIds,
1588
- modelListing: model.modelListing,
1589
- onRunModel: (inputs, outputs, options) => {
1590
- runJsModel(
1591
- model,
1592
- initialTime,
1593
- finalTime,
1594
- timeStep,
1595
- saveFreq,
1596
- numSavePoints,
1597
- inputs,
1598
- outputs,
1599
- options == null ? void 0 : options.outputIndices,
1600
- options == null ? void 0 : options.constants,
1601
- options == null ? void 0 : options.lookups,
1602
- void 0
1603
- );
1604
- }
1605
- });
1606
- }
1607
- function runJsModel(model, initialTime, finalTime, timeStep, saveFreq, numSavePoints, inputs, outputs, outputIndices, constants, lookups, stopAfterTime) {
1608
- let time = initialTime;
1609
- model.setTime(time);
1610
- const fnContext = {
1611
- timeStep,
1612
- currentTime: time
1613
- };
1614
- model.getModelFunctions().setContext(fnContext);
1615
- model.initConstants();
1616
- if (constants !== void 0) {
1617
- for (const constantDef of constants) {
1618
- model.setConstant(constantDef.varRef.varSpec, constantDef.value);
1619
- }
1620
- }
1621
- if (lookups !== void 0) {
1622
- for (const lookupDef of lookups) {
1623
- model.setLookup(lookupDef.varRef.varSpec, lookupDef.points);
1624
- }
1625
- }
1626
- if ((inputs == null ? void 0 : inputs.length) > 0) {
1627
- model.setInputs((index) => inputs[index]);
1628
- }
1629
- model.initLevels();
1630
- const lastStep = Math.round((finalTime - initialTime) / timeStep);
1631
- const stopTime = stopAfterTime !== void 0 ? stopAfterTime : finalTime;
1632
- let step = 0;
1633
- let savePointIndex = 0;
1634
- let outputVarIndex = 0;
1635
- while (step <= lastStep) {
1636
- model.evalAux();
1637
- if (time % saveFreq < 1e-6) {
1638
- outputVarIndex = 0;
1639
- const storeValue = (value) => {
1640
- const outputBufferIndex = outputVarIndex * numSavePoints + savePointIndex;
1641
- outputs[outputBufferIndex] = time <= stopTime ? value : void 0;
1642
- outputVarIndex++;
1643
- };
1644
- if (outputIndices !== void 0) {
1645
- let indexBufferOffset = 0;
1646
- const outputCount = outputIndices[indexBufferOffset++];
1647
- for (let i = 0; i < outputCount; i++) {
1648
- const varIndex = outputIndices[indexBufferOffset++];
1649
- const subCount = outputIndices[indexBufferOffset++];
1650
- let subscriptIndices;
1651
- if (subCount > 0) {
1652
- subscriptIndices = outputIndices.subarray(indexBufferOffset, indexBufferOffset + subCount);
1653
- indexBufferOffset += subCount;
1654
- }
1655
- const varSpec = {
1656
- varIndex,
1657
- subscriptIndices
1658
- };
1659
- model.storeOutput(varSpec, storeValue);
1660
- }
1661
- } else {
1662
- model.storeOutputs(storeValue);
1663
- }
1664
- savePointIndex++;
1665
- }
1666
- if (step === lastStep) {
1667
- break;
1668
- }
1669
- model.evalLevels();
1670
- time += timeStep;
1671
- model.setTime(time);
1672
- fnContext.currentTime = time;
1673
- step++;
1674
- }
1675
- }
1676
-
1677
- // src/js-model/exec-js-model.ts
1678
- function execJsModel(jsModel) {
1679
- const runnableModel = initJsModel(jsModel);
1680
- const inputs = [];
1681
- const outputVarIds = jsModel.outputVarIds;
1682
- const startTime = jsModel.getInitialTime();
1683
- const endTime = jsModel.getFinalTime();
1684
- const saveFreq = jsModel.getSaveFreq();
1685
- const outputs = new Outputs(outputVarIds, startTime, endTime, saveFreq);
1686
- const params = new ReferencedRunModelParams();
1687
- params.updateFromParams(inputs, outputs);
1688
- runnableModel.runModel(params);
1689
- const outputVarNames = jsModel.outputVarNames.map((name) => name.replace(/"/g, '\\"'));
1690
- const header = outputVarNames.join(" ");
1691
- console.log(header);
1692
- for (let i = 0; i < outputs.seriesLength; i++) {
1693
- const rowValues = [];
1694
- for (const series of outputs.varSeries) {
1695
- rowValues.push(series.points[i].y);
1696
- }
1697
- console.log(rowValues.join(" "));
1698
- }
1699
- }
1700
-
1701
- // src/js-model/_mocks/mock-js-model.ts
1702
- var MockJsModel = class {
1703
- constructor(options) {
1704
- // from JsModel interface
1705
- this.kind = "js";
1706
- this.vars = /* @__PURE__ */ new Map();
1707
- this.constants = /* @__PURE__ */ new Map();
1708
- this.lookups = /* @__PURE__ */ new Map();
1709
- this.outputVarIds = options.outputVarIds;
1710
- this.outputVarNames = options.outputVarIds;
1711
- this.initialTime = options.initialTime;
1712
- this.finalTime = options.finalTime;
1713
- this.outputVarIds = options.outputVarIds;
1714
- if (options.listingJson) {
1715
- this.modelListing = JSON.parse(options.listingJson);
1716
- this.internalListing = new ModelListing(this.modelListing);
1717
- }
1718
- this.onEvalAux = options.onEvalAux;
1719
- }
1720
- varIdForSpec(varSpec) {
1721
- for (const [listingVarId, listingSpec] of this.internalListing.varSpecs) {
1722
- if (listingSpec.varIndex === varSpec.varIndex) {
1723
- return listingVarId;
1724
- }
1725
- }
1726
- return void 0;
1727
- }
1728
- // from JsModel interface
1729
- getInitialTime() {
1730
- return this.initialTime;
1731
- }
1732
- // from JsModel interface
1733
- getFinalTime() {
1734
- return this.finalTime;
1735
- }
1736
- // from JsModel interface
1737
- getTimeStep() {
1738
- return 1;
1739
- }
1740
- // from JsModel interface
1741
- getSaveFreq() {
1742
- return 1;
1743
- }
1744
- // from JsModel interface
1745
- getModelFunctions() {
1746
- return this.fns;
1747
- }
1748
- // from JsModel interface
1749
- setModelFunctions(fns) {
1750
- this.fns = fns;
1751
- }
1752
- // from JsModel interface
1753
- setTime(time) {
1754
- this.vars.set("_time", time);
1755
- }
1756
- // from JsModel interface
1757
- setInputs() {
1758
- }
1759
- // from JsModel interface
1760
- setConstant(varSpec, value) {
1761
- const varId = this.varIdForSpec(varSpec);
1762
- if (varId === void 0) {
1763
- throw new Error(`No constant variable found for spec ${varSpec}`);
1764
- }
1765
- this.constants.set(varId, value);
1766
- }
1767
- // from JsModel interface
1768
- setLookup(varSpec, points) {
1769
- const varId = this.varIdForSpec(varSpec);
1770
- if (varId === void 0) {
1771
- throw new Error(`No lookup variable found for spec ${varSpec}`);
1772
- }
1773
- const numPoints = points ? points.length / 2 : 0;
1774
- this.lookups.set(varId, new JsModelLookup(numPoints, points));
1775
- }
1776
- // from JsModel interface
1777
- storeOutputs(storeValue) {
1778
- for (const varId of this.outputVarIds) {
1779
- storeValue(this.vars.get(varId));
1780
- }
1781
- }
1782
- // from JsModel interface
1783
- storeOutput(varSpec, storeValue) {
1784
- const varId = this.varIdForSpec(varSpec);
1785
- if (varId === void 0) {
1786
- throw new Error(`No output variable found for spec ${varSpec}`);
1787
- }
1788
- storeValue(this.vars.get(varId));
1789
- }
1790
- // from JsModel interface
1791
- initConstants() {
1792
- this.constants.clear();
1793
- }
1794
- // from JsModel interface
1795
- initLevels() {
1796
- }
1797
- // from JsModel interface
1798
- evalAux() {
1799
- var _a;
1800
- (_a = this.onEvalAux) == null ? void 0 : _a.call(this, this.vars, this.constants.size > 0 ? this.constants : void 0, this.lookups);
1801
- }
1802
- // from JsModel interface
1803
- evalLevels() {
1804
- }
1805
- };
1806
-
1807
- // src/wasm-model/wasm-buffer.ts
1808
- var WasmBuffer = class {
1809
- /**
1810
- * @param wasmModule The `WasmModule` used to initialize the memory.
1811
- * @param numElements The number of elements in the buffer.
1812
- * @param byteOffset The byte offset within the wasm heap.
1813
- * @param heapArray The array view on the underlying heap buffer.
1814
- */
1815
- constructor(wasmModule, numElements, byteOffset, heapArray) {
1816
- this.wasmModule = wasmModule;
1817
- this.numElements = numElements;
1818
- this.byteOffset = byteOffset;
1819
- this.heapArray = heapArray;
1820
- }
1821
- /**
1822
- * @return An `ArrType` view on the underlying heap buffer.
1823
- */
1824
- getArrayView() {
1825
- return this.heapArray;
1826
- }
1827
- /**
1828
- * @return The raw address of the underlying heap buffer.
1829
- * @hidden This is intended for use by `WasmModel` only.
1830
- */
1831
- getAddress() {
1832
- return this.byteOffset;
1833
- }
1834
- /**
1835
- * Dispose the buffer by freeing the allocated heap memory.
1836
- */
1837
- dispose() {
1838
- var _a, _b;
1839
- if (this.heapArray) {
1840
- (_b = (_a = this.wasmModule)._free) == null ? void 0 : _b.call(_a, this.byteOffset);
1841
- this.numElements = void 0;
1842
- this.heapArray = void 0;
1843
- this.byteOffset = void 0;
1844
- }
1845
- }
1846
- };
1847
- function createInt32WasmBuffer(wasmModule, numElements) {
1848
- const elemSizeInBytes = 4;
1849
- const lengthInBytes = numElements * elemSizeInBytes;
1850
- const byteOffset = wasmModule._malloc(lengthInBytes);
1851
- const elemOffset = byteOffset / elemSizeInBytes;
1852
- const heapArray = wasmModule.HEAP32.subarray(elemOffset, elemOffset + numElements);
1853
- return new WasmBuffer(wasmModule, numElements, byteOffset, heapArray);
1854
- }
1855
- function createFloat64WasmBuffer(wasmModule, numElements) {
1856
- const elemSizeInBytes = 8;
1857
- const lengthInBytes = numElements * elemSizeInBytes;
1858
- const byteOffset = wasmModule._malloc(lengthInBytes);
1859
- const elemOffset = byteOffset / elemSizeInBytes;
1860
- const heapArray = wasmModule.HEAPF64.subarray(elemOffset, elemOffset + numElements);
1861
- return new WasmBuffer(wasmModule, numElements, byteOffset, heapArray);
1862
- }
1863
-
1864
- // src/wasm-model/wasm-model.ts
1865
- var WasmModel = class {
1866
- /**
1867
- * @param wasmModule The `WasmModule` that provides access to the native functions.
1868
- * @param outputVarIds The output variable IDs for this model.
1869
- */
1870
- constructor(wasmModule) {
1871
- this.wasmModule = wasmModule;
1872
- function getNumberValue(funcName) {
1873
- const wasmGetValue = wasmModule.cwrap(funcName, "number", []);
1874
- return wasmGetValue();
1875
- }
1876
- this.startTime = getNumberValue("getInitialTime");
1877
- this.endTime = getNumberValue("getFinalTime");
1878
- this.saveFreq = getNumberValue("getSaveper");
1879
- this.numSavePoints = Math.round((this.endTime - this.startTime) / this.saveFreq) + 1;
1880
- this.outputVarIds = wasmModule.outputVarIds;
1881
- this.modelListing = wasmModule.modelListing;
1882
- this.wasmSetLookup = wasmModule.cwrap("setLookup", null, ["number", "number", "number", "number"]);
1883
- this.wasmRunModel = wasmModule.cwrap("runModelWithBuffers", null, [
1884
- "number",
1885
- "number",
1886
- "number",
1887
- "number",
1888
- "number",
1889
- "number"
1890
- ]);
1891
- }
1892
- // from RunnableModel interface
1893
- runModel(params) {
1894
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1895
- const lookups = params.getLookups();
1896
- if (lookups !== void 0) {
1897
- for (const lookupDef of lookups) {
1898
- const varSpec = lookupDef.varRef.varSpec;
1899
- const numSubElements = ((_a = varSpec.subscriptIndices) == null ? void 0 : _a.length) || 0;
1900
- let subIndicesAddress;
1901
- if (numSubElements > 0) {
1902
- if (this.lookupSubIndicesBuffer === void 0 || this.lookupSubIndicesBuffer.numElements < numSubElements) {
1903
- (_b = this.lookupSubIndicesBuffer) == null ? void 0 : _b.dispose();
1904
- this.lookupSubIndicesBuffer = createInt32WasmBuffer(this.wasmModule, numSubElements);
1905
- }
1906
- this.lookupSubIndicesBuffer.getArrayView().set(varSpec.subscriptIndices);
1907
- subIndicesAddress = this.lookupSubIndicesBuffer.getAddress();
1908
- } else {
1909
- subIndicesAddress = 0;
1910
- }
1911
- let pointsAddress;
1912
- let numPoints;
1913
- if (lookupDef.points) {
1914
- const numLookupElements = lookupDef.points.length;
1915
- if (this.lookupDataBuffer === void 0 || this.lookupDataBuffer.numElements < numLookupElements) {
1916
- (_c = this.lookupDataBuffer) == null ? void 0 : _c.dispose();
1917
- this.lookupDataBuffer = createFloat64WasmBuffer(this.wasmModule, numLookupElements);
1918
- }
1919
- this.lookupDataBuffer.getArrayView().set(lookupDef.points);
1920
- pointsAddress = this.lookupDataBuffer.getAddress();
1921
- numPoints = numLookupElements / 2;
1922
- } else {
1923
- pointsAddress = 0;
1924
- numPoints = 0;
1925
- }
1926
- const varIndex = varSpec.varIndex;
1927
- this.wasmSetLookup(varIndex, subIndicesAddress, pointsAddress, numPoints);
1928
- }
1929
- }
1930
- let constantIndicesBuffer;
1931
- let constantValuesBuffer;
1932
- const constants = params.getConstants();
1933
- if (constants !== void 0 && constants.length > 0) {
1934
- let totalIndicesSize = 1;
1935
- for (const constantDef of constants) {
1936
- const numSubElements = ((_d = constantDef.varRef.varSpec.subscriptIndices) == null ? void 0 : _d.length) || 0;
1937
- totalIndicesSize += 2 + numSubElements;
1938
- }
1939
- if (this.constantIndicesBuffer === void 0 || this.constantIndicesBuffer.numElements < totalIndicesSize) {
1940
- (_e = this.constantIndicesBuffer) == null ? void 0 : _e.dispose();
1941
- this.constantIndicesBuffer = createInt32WasmBuffer(this.wasmModule, totalIndicesSize);
1942
- }
1943
- const numConstants = constants.length;
1944
- if (this.constantValuesBuffer === void 0 || this.constantValuesBuffer.numElements < numConstants) {
1945
- (_f = this.constantValuesBuffer) == null ? void 0 : _f.dispose();
1946
- this.constantValuesBuffer = createFloat64WasmBuffer(this.wasmModule, numConstants);
1947
- }
1948
- const indicesView = this.constantIndicesBuffer.getArrayView();
1949
- const valuesView = this.constantValuesBuffer.getArrayView();
1950
- let indicesOffset = 0;
1951
- let valuesOffset = 0;
1952
- indicesView[indicesOffset++] = numConstants;
1953
- for (const constantDef of constants) {
1954
- const varSpec = constantDef.varRef.varSpec;
1955
- const numSubElements = ((_g = varSpec.subscriptIndices) == null ? void 0 : _g.length) || 0;
1956
- indicesView[indicesOffset++] = varSpec.varIndex;
1957
- indicesView[indicesOffset++] = numSubElements;
1958
- if (numSubElements > 0) {
1959
- for (let i = 0; i < numSubElements; i++) {
1960
- indicesView[indicesOffset++] = varSpec.subscriptIndices[i];
1961
- }
1962
- }
1963
- valuesView[valuesOffset++] = constantDef.value;
1964
- }
1965
- constantIndicesBuffer = this.constantIndicesBuffer;
1966
- constantValuesBuffer = this.constantValuesBuffer;
1967
- } else {
1968
- constantIndicesBuffer = void 0;
1969
- constantValuesBuffer = void 0;
1970
- }
1971
- params.copyInputs((_h = this.inputsBuffer) == null ? void 0 : _h.getArrayView(), (numElements) => {
1972
- var _a2;
1973
- (_a2 = this.inputsBuffer) == null ? void 0 : _a2.dispose();
1974
- this.inputsBuffer = createFloat64WasmBuffer(this.wasmModule, numElements);
1975
- return this.inputsBuffer.getArrayView();
1976
- });
1977
- let outputIndicesBuffer;
1978
- if (params.getOutputIndicesLength() > 0) {
1979
- params.copyOutputIndices((_i = this.outputIndicesBuffer) == null ? void 0 : _i.getArrayView(), (numElements) => {
1980
- var _a2;
1981
- (_a2 = this.outputIndicesBuffer) == null ? void 0 : _a2.dispose();
1982
- this.outputIndicesBuffer = createInt32WasmBuffer(this.wasmModule, numElements);
1983
- return this.outputIndicesBuffer.getArrayView();
1984
- });
1985
- outputIndicesBuffer = this.outputIndicesBuffer;
1986
- } else {
1987
- outputIndicesBuffer = void 0;
1988
- }
1989
- const outputsLengthInElements = params.getOutputsLength();
1990
- if (this.outputsBuffer === void 0 || this.outputsBuffer.numElements < outputsLengthInElements) {
1991
- (_j = this.outputsBuffer) == null ? void 0 : _j.dispose();
1992
- this.outputsBuffer = createFloat64WasmBuffer(this.wasmModule, outputsLengthInElements);
1993
- }
1994
- const t0 = perfNow();
1995
- this.wasmRunModel(
1996
- ((_k = this.inputsBuffer) == null ? void 0 : _k.getAddress()) || 0,
1997
- // Always pass 0 (NULL) for input indices, since we assume that all input values are
1998
- // provided and are in the same order as the input variables defined in the model spec
1999
- 0,
2000
- this.outputsBuffer.getAddress(),
2001
- (outputIndicesBuffer == null ? void 0 : outputIndicesBuffer.getAddress()) || 0,
2002
- (constantValuesBuffer == null ? void 0 : constantValuesBuffer.getAddress()) || 0,
2003
- (constantIndicesBuffer == null ? void 0 : constantIndicesBuffer.getAddress()) || 0
2004
- );
2005
- const elapsed = perfElapsed(t0);
2006
- params.storeOutputs(this.outputsBuffer.getArrayView());
2007
- params.storeElapsedTime(elapsed);
2008
- }
2009
- // from RunnableModel interface
2010
- terminate() {
2011
- var _a, _b, _c, _d, _e;
2012
- (_a = this.inputsBuffer) == null ? void 0 : _a.dispose();
2013
- this.inputsBuffer = void 0;
2014
- (_b = this.outputsBuffer) == null ? void 0 : _b.dispose();
2015
- this.outputsBuffer = void 0;
2016
- (_c = this.outputIndicesBuffer) == null ? void 0 : _c.dispose();
2017
- this.outputIndicesBuffer = void 0;
2018
- (_d = this.constantValuesBuffer) == null ? void 0 : _d.dispose();
2019
- this.constantValuesBuffer = void 0;
2020
- (_e = this.constantIndicesBuffer) == null ? void 0 : _e.dispose();
2021
- this.constantIndicesBuffer = void 0;
2022
- }
2023
- };
2024
- function initWasmModel(wasmModule) {
2025
- return new WasmModel(wasmModule);
2026
- }
2027
-
2028
- // src/wasm-model/_mocks/mock-wasm-module.ts
2029
- var MockWasmModule = class {
2030
- constructor(options) {
2031
- // from WasmModule interface
2032
- this.kind = "wasm";
2033
- // Start at 8 so that we can treat 0 as NULL
2034
- this.mallocOffset = 8;
2035
- this.allocs = /* @__PURE__ */ new Map();
2036
- this.lookups = /* @__PURE__ */ new Map();
2037
- this.constants = /* @__PURE__ */ new Map();
2038
- this.initialTime = options.initialTime;
2039
- this.finalTime = options.finalTime;
2040
- this.outputVarIds = options.outputVarIds;
2041
- if (options.listingJson) {
2042
- this.modelListing = JSON.parse(options.listingJson);
2043
- this.internalListing = new ModelListing(this.modelListing);
2044
- }
2045
- this.onRunModel = options.onRunModel;
2046
- this.heap = new ArrayBuffer(8192);
2047
- this.HEAP32 = new Int32Array(this.heap);
2048
- this.HEAPF64 = new Float64Array(this.heap);
2049
- }
2050
- varIdForSpec(varSpec) {
2051
- for (const [listingVarId, listingSpec] of this.internalListing.varSpecs) {
2052
- if (listingSpec.varIndex === varSpec.varIndex) {
2053
- return listingVarId;
2054
- }
2055
- }
2056
- return void 0;
2057
- }
2058
- // from WasmModule interface
2059
- cwrap(fname) {
2060
- switch (fname) {
2061
- case "getInitialTime":
2062
- return () => this.initialTime;
2063
- case "getFinalTime":
2064
- return () => this.finalTime;
2065
- case "getSaveper":
2066
- return () => 1;
2067
- case "setLookup":
2068
- return (varIndex, _subIndicesAddress, pointsAddress, numPoints) => {
2069
- const varId = this.varIdForSpec({ varIndex });
2070
- if (varId === void 0) {
2071
- throw new Error(`No lookup variable found for var index ${varIndex}`);
2072
- }
2073
- const points = new Float64Array(this.getHeapView("float64", pointsAddress));
2074
- this.lookups.set(varId, new JsModelLookup(numPoints, points));
2075
- };
2076
- case "runModelWithBuffers":
2077
- return (inputsAddress, _inputIndicesAddress, outputsAddress, outputIndicesAddress, constantValuesAddress, constantIndicesAddress) => {
2078
- const inputs = this.getHeapView("float64", inputsAddress);
2079
- const outputs = this.getHeapView("float64", outputsAddress);
2080
- const outputIndices = this.getHeapView("int32", outputIndicesAddress);
2081
- this.constants.clear();
2082
- if (constantValuesAddress !== 0 && constantIndicesAddress !== 0) {
2083
- const constantValues = this.getHeapView("float64", constantValuesAddress);
2084
- const constantIndices = this.getHeapView("int32", constantIndicesAddress);
2085
- const numConstants = constantIndices[0];
2086
- let indicesOffset = 1;
2087
- let valuesOffset = 0;
2088
- for (let i = 0; i < numConstants; i++) {
2089
- const varIndex = constantIndices[indicesOffset++];
2090
- const subCount = constantIndices[indicesOffset++];
2091
- indicesOffset += subCount;
2092
- const varId = this.varIdForSpec({ varIndex });
2093
- if (varId) {
2094
- this.constants.set(varId, constantValues[valuesOffset++]);
2095
- }
2096
- }
2097
- }
2098
- this.onRunModel(
2099
- inputs,
2100
- outputs,
2101
- this.constants.size > 0 ? this.constants : void 0,
2102
- this.lookups,
2103
- outputIndices
2104
- );
2105
- this.constants.clear();
2106
- };
2107
- default:
2108
- throw new Error(`Unhandled call to cwrap with function name '${fname}'`);
2109
- }
2110
- }
2111
- // from WasmModule interface
2112
- _malloc(lengthInBytes) {
2113
- const currentOffset = this.mallocOffset;
2114
- this.allocs.set(currentOffset, lengthInBytes);
2115
- if (lengthInBytes > 0) {
2116
- this.mallocOffset += lengthInBytes;
2117
- } else {
2118
- this.mallocOffset += 8;
2119
- }
2120
- return currentOffset;
2121
- }
2122
- // from WasmModule interface
2123
- _free() {
2124
- }
2125
- getHeapView(kind, address) {
2126
- if (address === 0) {
2127
- return void 0;
2128
- }
2129
- const lengthInBytes = this.allocs.get(address);
2130
- if (lengthInBytes === void 0) {
2131
- throw new Error("Failed to locate heap allocation");
2132
- }
2133
- if (kind === "float64") {
2134
- const offset = address / 8;
2135
- return this.HEAPF64.subarray(offset, offset + lengthInBytes / 8);
2136
- } else {
2137
- const offset = address / 4;
2138
- return this.HEAP32.subarray(offset, offset + lengthInBytes / 4);
2139
- }
2140
- }
2141
- };
2142
-
2143
- // src/model-runner/synchronous-model-runner.ts
2144
- function createRunnableModel(generatedModel) {
2145
- switch (generatedModel.kind) {
2146
- case "js":
2147
- return initJsModel(generatedModel);
2148
- case "wasm":
2149
- return initWasmModel(generatedModel);
2150
- default:
2151
- throw new Error(`Unable to identify generated model kind`);
2152
- }
2153
- }
2154
- function createSynchronousModelRunner(generatedModel) {
2155
- const runnableModel = createRunnableModel(generatedModel);
2156
- return createRunnerFromRunnableModel(runnableModel);
2157
- }
2158
- function createRunnerFromRunnableModel(model) {
2159
- const listing = model.modelListing ? new ModelListing(model.modelListing) : void 0;
2160
- const params = new ReferencedRunModelParams(listing);
2161
- let terminated = false;
2162
- const runModelSync = (inputs, outputs, options) => {
2163
- params.updateFromParams(inputs, outputs, options);
2164
- model.runModel(params);
2165
- return outputs;
2166
- };
2167
- return {
2168
- createOutputs: () => {
2169
- return new Outputs(model.outputVarIds, model.startTime, model.endTime, model.saveFreq);
2170
- },
2171
- runModel: (inputs, outputs, options) => {
2172
- if (terminated) {
2173
- return Promise.reject(new Error("Model runner has already been terminated"));
2174
- }
2175
- return Promise.resolve(runModelSync(inputs, outputs, options));
2176
- },
2177
- runModelSync: (inputs, outputs, options) => {
2178
- if (terminated) {
2179
- throw new Error("Model runner has already been terminated");
2180
- }
2181
- return runModelSync(inputs, outputs, options);
2182
- },
2183
- terminate: () => __async(null, null, function* () {
2184
- if (!terminated) {
2185
- model.terminate();
2186
- terminated = true;
2187
- }
2188
- })
2189
- };
2190
- }
2191
-
2192
- // src/model-scheduler/model-scheduler.ts
2193
- var ModelScheduler = class {
2194
- /**
2195
- * @param runner The model runner.
2196
- * @param userInputs The input values, in the same order as in the spec file passed to `sde`.
2197
- * @param outputs The structure into which the model outputs will be stored.
2198
- */
2199
- constructor(runner, userInputs, outputs) {
2200
- this.runner = runner;
2201
- this.userInputs = userInputs;
2202
- this.outputs = outputs;
2203
- /** Whether a model run has been scheduled. */
2204
- this.runNeeded = false;
2205
- /** Whether a model run is in progress. */
2206
- this.runInProgress = false;
2207
- const afterSet = () => {
2208
- this.runModelIfNeeded();
2209
- };
2210
- for (const userInput of userInputs) {
2211
- userInput.callbacks.onSet = afterSet;
2212
- }
2213
- this.currentInputs = [];
2214
- for (const userInput of userInputs) {
2215
- this.currentInputs.push(createSimpleInputValue(userInput.varId));
2216
- }
2217
- }
2218
- /**
2219
- * Schedule a model run (if not already pending). When the run is
2220
- * complete, save the outputs and call the `onOutputsChanged` callback.
2221
- */
2222
- runModelIfNeeded() {
2223
- this.runNeeded = true;
2224
- if (this.runInProgress) {
2225
- return;
2226
- } else {
2227
- this.runInProgress = true;
2228
- setTimeout(() => {
2229
- this.runModelNow();
2230
- }, 0);
2231
- }
2232
- }
2233
- /**
2234
- * Run the model asynchronously using the current set of input values.
2235
- */
2236
- runModelNow() {
2237
- return __async(this, null, function* () {
2238
- var _a;
2239
- for (let i = 0; i < this.userInputs.length; i++) {
2240
- this.currentInputs[i].set(this.userInputs[i].get());
2241
- }
2242
- try {
2243
- this.outputs = yield this.runner.runModel(this.currentInputs, this.outputs);
2244
- (_a = this.onOutputsChanged) == null ? void 0 : _a.call(this, this.outputs);
2245
- } catch (e) {
2246
- console.error(`ERROR: Failed to run model: ${e.message}`);
2247
- }
2248
- if (this.runNeeded) {
2249
- this.runNeeded = false;
2250
- setTimeout(() => {
2251
- this.runModelNow();
2252
- }, 0);
2253
- } else {
2254
- this.runNeeded = false;
2255
- this.runInProgress = false;
2256
- }
2257
- });
2258
- }
2259
- };
2260
- function createSimpleInputValue(varId) {
2261
- let currentValue = 0;
2262
- const get = () => {
2263
- return currentValue;
2264
- };
2265
- const set = (newValue) => {
2266
- currentValue = newValue;
2267
- };
2268
- const reset = () => {
2269
- set(0);
2270
- };
2271
- return { varId, get, set, reset, callbacks: {} };
2272
- }
2273
-
2274
- // src/model-scheduler/multi-context-model-scheduler.ts
2275
- var MultiContextModelScheduler = class {
2276
- /**
2277
- * @param runner The model runner.
2278
- * @param options Additional options for the scheduler.
2279
- * @param options.initialOutputs An optional `Outputs` instance that will be reused
2280
- * for the initial context. This is useful for saving memory when an `Outputs`
2281
- * instance was already created for, e.g., a initial baseline/reference run.
2282
- */
2283
- constructor(runner, options) {
2284
- this.runner = runner;
2285
- /** The contexts that hold distinct sets of inputs and outputs. */
2286
- this.contexts = [];
2287
- /** Whether a model run has been scheduled. */
2288
- this.runNeeded = false;
2289
- /** Whether a model run is in progress. */
2290
- this.runInProgress = false;
2291
- this.initialOutputs = options == null ? void 0 : options.initialOutputs;
2292
- }
2293
- /**
2294
- * Return true if the scheduler has started any model runs.
2295
- */
2296
- isStarted() {
2297
- return this.initialOutputs === void 0;
2298
- }
2299
- /**
2300
- * Add a new context that holds a distinct set of model inputs and outputs.
2301
- * These inputs and outputs are kept separate from those in other contexts,
2302
- * which allows an application to use the same underlying model to run with
2303
- * multiple I/O contexts.
2304
- *
2305
- * Note that the contexts created before the first scheduled model run
2306
- * will inherit the data from `initialOutputs` passed to the constructor,
2307
- * but contexts created after that will initially have output values set
2308
- * to zero.
2309
- *
2310
- * @param inputs The input values, in the same order as in the spec file passed to `sde`.
2311
- * @param options Additional options for the context.
2312
- * @param options.externalData Additional data that is external to the model outputs.
2313
- * For example, this can contain data that was captured from an initial reference
2314
- * run, or other static data that is displayed in graphs alongside the model
2315
- * output data in graphs.
2316
- */
2317
- addContext(inputs, options) {
2318
- let outputs;
2319
- if (this.initialOutputs !== void 0) {
2320
- if (this.contexts.length === 0) {
2321
- outputs = this.initialOutputs;
2322
- } else {
2323
- outputs = this.runner.createOutputs();
2324
- for (const varId of outputs.varIds) {
2325
- const series0 = this.initialOutputs.getSeriesForVar(varId);
2326
- const series1 = outputs.getSeriesForVar(varId);
2327
- for (let i = 0; i < series0.points.length; i++) {
2328
- series1.points[i].y = series0.points[i].y;
2329
- }
2330
- }
2331
- }
2332
- } else {
2333
- outputs = this.runner.createOutputs();
2334
- }
2335
- const context = new ModelContextImpl(inputs, outputs, options == null ? void 0 : options.externalData);
2336
- const afterSet = () => {
2337
- context.runNeeded = true;
2338
- this.runModelIfNeeded();
2339
- };
2340
- for (const input of inputs) {
2341
- input.callbacks.onSet = afterSet;
2342
- }
2343
- this.contexts.push(context);
2344
- return context;
2345
- }
2346
- /**
2347
- * Remove the given context from the set of contexts managed by the scheduler.
2348
- *
2349
- * @param context The context to remove.
2350
- */
2351
- removeContext(context) {
2352
- const index = this.contexts.findIndex((c) => c === context);
2353
- if (index >= 0) {
2354
- this.contexts.splice(index, 1);
2355
- }
2356
- }
2357
- /**
2358
- * Schedule a model run (if not already pending). When the run is
2359
- * complete, save the outputs and call the `onOutputsChanged` callback.
2360
- */
2361
- runModelIfNeeded() {
2362
- this.runNeeded = true;
2363
- if (this.runInProgress) {
2364
- return;
2365
- } else {
2366
- this.runInProgress = true;
2367
- setTimeout(() => {
2368
- this.runModelNow();
2369
- }, 0);
2370
- }
2371
- }
2372
- /**
2373
- * Run the model asynchronously for all relevant contexts.
2374
- */
2375
- runModelNow() {
2376
- return __async(this, null, function* () {
2377
- this.initialOutputs = void 0;
2378
- for (const context of this.contexts) {
2379
- if (context.runNeeded) {
2380
- context.runNeeded = false;
2381
- yield this.runModelNowForContext(context);
2382
- }
2383
- }
2384
- if (this.runNeeded) {
2385
- this.runNeeded = false;
2386
- setTimeout(() => {
2387
- this.runModelNow();
2388
- }, 0);
2389
- } else {
2390
- this.runNeeded = false;
2391
- this.runInProgress = false;
2392
- }
2393
- });
2394
- }
2395
- /**
2396
- * Run the model asynchronously using the current set of input values in the given context.
2397
- *
2398
- * @param context The context to use for the model run.
2399
- */
2400
- runModelNowForContext(context) {
2401
- return __async(this, null, function* () {
2402
- var _a;
2403
- if (this.currentInputs === void 0) {
2404
- this.currentInputs = Array(context.inputsArray.length);
2405
- }
2406
- for (let i = 0; i < context.inputsArray.length; i++) {
2407
- this.currentInputs[i] = context.inputsArray[i].get();
2408
- }
2409
- try {
2410
- yield this.runner.runModel(this.currentInputs, context.outputs);
2411
- (_a = context.onOutputsChanged) == null ? void 0 : _a.call(context);
2412
- } catch (e) {
2413
- console.error("ERROR: The scheduler encountered an error when running the model:", e);
2414
- }
2415
- });
2416
- }
2417
- };
2418
- var ModelContextImpl = class {
2419
- /**
2420
- * @hidden This is intended for use by `MultiContextModelScheduler` only.
2421
- *
2422
- * @param inputs The input values, in the same order as in the spec file passed to `sde`.
2423
- * @param outputs The structure into which the model outputs will be stored.
2424
- * @param externalData Additional data that is external to the model outputs. For example, this can contain
2425
- * data that was captured from an initial reference run, or other static data that is displayed in graphs
2426
- * alongside the model output data in graphs.
2427
- */
2428
- constructor(inputs, outputs, externalData) {
2429
- this.externalData = externalData;
2430
- /**
2431
- * Whether a model run is needed for this context.
2432
- * @hidden This is intended for use by `MultiContextModelScheduler` only.
2433
- */
2434
- this.runNeeded = false;
2435
- this.inputsArray = Array.from(inputs);
2436
- this.outputs = outputs;
2437
- }
2438
- /**
2439
- * Return the series data for the given model output variable or external
2440
- * dataset.
2441
- *
2442
- * @param varId The ID of the output variable associated with the data.
2443
- * @param sourceName The external data source name (e.g. "Ref"), or
2444
- * undefined to use the latest model output data from this context.
2445
- */
2446
- getSeriesForVar(varId, sourceName) {
2447
- if (sourceName === void 0) {
2448
- return this.outputs.getSeriesForVar(varId);
2449
- } else {
2450
- const dataForSource = this.externalData.get(sourceName);
2451
- if (dataForSource !== void 0) {
2452
- return dataForSource.get(varId);
2453
- } else {
2454
- return void 0;
2455
- }
2456
- }
2457
- }
2458
- };
2459
- // Annotate the CommonJS export names for ESM import in node:
2460
- 0 && (module.exports = {
2461
- BufferedRunModelParams,
2462
- MockJsModel,
2463
- MockWasmModule,
2464
- ModelListing,
2465
- ModelScheduler,
2466
- MultiContextModelScheduler,
2467
- Outputs,
2468
- ReferencedRunModelParams,
2469
- Series,
2470
- createConstantDef,
2471
- createInputValue,
2472
- createLookupDef,
2473
- createRunnableModel,
2474
- createSynchronousModelRunner,
2475
- decodeConstants,
2476
- decodeLookups,
2477
- encodeConstants,
2478
- encodeLookups,
2479
- encodeVarIndices,
2480
- execJsModel,
2481
- getEncodedConstantBufferLengths,
2482
- getEncodedLookupBufferLengths,
2483
- getEncodedVarIndicesLength,
2484
- getJsModelFunctions,
2485
- initJsModel,
2486
- initWasmModel,
2487
- perfElapsed,
2488
- perfNow
2489
- });
2490
- //# sourceMappingURL=index.cjs.map