@sdeverywhere/runtime 0.2.6 → 0.2.8

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 CHANGED
@@ -51,24 +51,29 @@ var __async = (__this, __arguments, generator) => {
51
51
  };
52
52
 
53
53
  // src/index.ts
54
- var src_exports = {};
55
- __export(src_exports, {
54
+ var index_exports = {};
55
+ __export(index_exports, {
56
56
  BufferedRunModelParams: () => BufferedRunModelParams,
57
57
  MockJsModel: () => MockJsModel,
58
58
  MockWasmModule: () => MockWasmModule,
59
59
  ModelListing: () => ModelListing,
60
60
  ModelScheduler: () => ModelScheduler,
61
+ MultiContextModelScheduler: () => MultiContextModelScheduler,
61
62
  Outputs: () => Outputs,
62
63
  ReferencedRunModelParams: () => ReferencedRunModelParams,
63
64
  Series: () => Series,
65
+ createConstantDef: () => createConstantDef,
64
66
  createInputValue: () => createInputValue,
65
67
  createLookupDef: () => createLookupDef,
66
68
  createRunnableModel: () => createRunnableModel,
67
69
  createSynchronousModelRunner: () => createSynchronousModelRunner,
70
+ decodeConstants: () => decodeConstants,
68
71
  decodeLookups: () => decodeLookups,
72
+ encodeConstants: () => encodeConstants,
69
73
  encodeLookups: () => encodeLookups,
70
74
  encodeVarIndices: () => encodeVarIndices,
71
75
  execJsModel: () => execJsModel,
76
+ getEncodedConstantBufferLengths: () => getEncodedConstantBufferLengths,
72
77
  getEncodedLookupBufferLengths: () => getEncodedLookupBufferLengths,
73
78
  getEncodedVarIndicesLength: () => getEncodedVarIndicesLength,
74
79
  getJsModelFunctions: () => getJsModelFunctions,
@@ -77,7 +82,7 @@ __export(src_exports, {
77
82
  perfElapsed: () => perfElapsed,
78
83
  perfNow: () => perfNow
79
84
  });
80
- module.exports = __toCommonJS(src_exports);
85
+ module.exports = __toCommonJS(index_exports);
81
86
 
82
87
  // src/_shared/inputs.ts
83
88
  function createInputValue(varId, defaultValue, initialValue) {
@@ -250,6 +255,66 @@ function encodeVarIndices(varSpecs, indicesArray) {
250
255
  }
251
256
  }
252
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
+ }
253
318
  function getEncodedLookupBufferLengths(lookupDefs) {
254
319
  var _a, _b;
255
320
  let lookupIndicesLength = 1;
@@ -331,6 +396,14 @@ function decodeLookups(lookupIndicesArray, lookupsArray) {
331
396
  return lookupDefs;
332
397
  }
333
398
 
399
+ // src/_shared/constant-def.ts
400
+ function createConstantDef(varRef, value) {
401
+ return {
402
+ varRef,
403
+ value
404
+ };
405
+ }
406
+
334
407
  // src/_shared/lookup-def.ts
335
408
  function createLookupDef(varRef, points) {
336
409
  let flatPoints;
@@ -501,7 +574,7 @@ function resolveVarRef(listing, varRef, varKind) {
501
574
  }
502
575
 
503
576
  // src/runnable-model/buffered-run-model-params.ts
504
- var headerLengthInElements = 16;
577
+ var headerLengthInElements = 20;
505
578
  var extrasLengthInElements = 1;
506
579
  var Int32Section = class {
507
580
  constructor() {
@@ -546,6 +619,10 @@ var BufferedRunModelParams = class {
546
619
  this.outputs = new Float64Section();
547
620
  /** The output indices section of the `encoded` buffer. */
548
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();
549
626
  /** The lookup data section of the `encoded` buffer. */
550
627
  this.lookups = new Float64Section();
551
628
  /** The lookup indices section of the `encoded` buffer. */
@@ -613,6 +690,13 @@ var BufferedRunModelParams = class {
613
690
  }
614
691
  }
615
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
616
700
  getLookups() {
617
701
  if (this.lookupIndices.lengthInElements === 0) {
618
702
  return void 0;
@@ -657,6 +741,19 @@ var BufferedRunModelParams = class {
657
741
  } else {
658
742
  outputIndicesLengthInElements = 0;
659
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
+ }
660
757
  let lookupsLengthInElements;
661
758
  let lookupIndicesLengthInElements;
662
759
  if ((options == null ? void 0 : options.lookups) !== void 0 && options.lookups.length > 0) {
@@ -684,6 +781,8 @@ var BufferedRunModelParams = class {
684
781
  const inputsOffsetInBytes = section("float64", inputsLengthInElements);
685
782
  const outputsOffsetInBytes = section("float64", outputsLengthInElements);
686
783
  const outputIndicesOffsetInBytes = section("int32", outputIndicesLengthInElements);
784
+ const constantsOffsetInBytes = section("float64", constantsLengthInElements);
785
+ const constantIndicesOffsetInBytes = section("int32", constantIndicesLengthInElements);
687
786
  const lookupsOffsetInBytes = section("float64", lookupsLengthInElements);
688
787
  const lookupIndicesOffsetInBytes = section("int32", lookupIndicesLengthInElements);
689
788
  const requiredLengthInBytes = byteOffset;
@@ -702,6 +801,10 @@ var BufferedRunModelParams = class {
702
801
  headerView[headerIndex++] = outputsLengthInElements;
703
802
  headerView[headerIndex++] = outputIndicesOffsetInBytes;
704
803
  headerView[headerIndex++] = outputIndicesLengthInElements;
804
+ headerView[headerIndex++] = constantsOffsetInBytes;
805
+ headerView[headerIndex++] = constantsLengthInElements;
806
+ headerView[headerIndex++] = constantIndicesOffsetInBytes;
807
+ headerView[headerIndex++] = constantIndicesLengthInElements;
705
808
  headerView[headerIndex++] = lookupsOffsetInBytes;
706
809
  headerView[headerIndex++] = lookupsLengthInElements;
707
810
  headerView[headerIndex++] = lookupIndicesOffsetInBytes;
@@ -710,6 +813,8 @@ var BufferedRunModelParams = class {
710
813
  this.extras.update(this.encoded, extrasOffsetInBytes, extrasLengthInElements);
711
814
  this.outputs.update(this.encoded, outputsOffsetInBytes, outputsLengthInElements);
712
815
  this.outputIndices.update(this.encoded, outputIndicesOffsetInBytes, outputIndicesLengthInElements);
816
+ this.constants.update(this.encoded, constantsOffsetInBytes, constantsLengthInElements);
817
+ this.constantIndices.update(this.encoded, constantIndicesOffsetInBytes, constantIndicesLengthInElements);
713
818
  this.lookups.update(this.encoded, lookupsOffsetInBytes, lookupsLengthInElements);
714
819
  this.lookupIndices.update(this.encoded, lookupIndicesOffsetInBytes, lookupIndicesLengthInElements);
715
820
  const inputsView = this.inputs.view;
@@ -724,6 +829,9 @@ var BufferedRunModelParams = class {
724
829
  if (this.outputIndices.view) {
725
830
  encodeVarIndices(outputVarSpecs, this.outputIndices.view);
726
831
  }
832
+ if (constantIndicesLengthInElements > 0) {
833
+ encodeConstants(options.constants, this.constantIndices.view, this.constants.view);
834
+ }
727
835
  if (lookupIndicesLengthInElements > 0) {
728
836
  encodeLookups(options.lookups, this.lookupIndices.view, this.lookups.view);
729
837
  }
@@ -752,6 +860,10 @@ var BufferedRunModelParams = class {
752
860
  const outputsLengthInElements = headerView[headerIndex++];
753
861
  const outputIndicesOffsetInBytes = headerView[headerIndex++];
754
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++];
755
867
  const lookupsOffsetInBytes = headerView[headerIndex++];
756
868
  const lookupsLengthInElements = headerView[headerIndex++];
757
869
  const lookupIndicesOffsetInBytes = headerView[headerIndex++];
@@ -760,9 +872,11 @@ var BufferedRunModelParams = class {
760
872
  const inputsLengthInBytes = inputsLengthInElements * Float64Array.BYTES_PER_ELEMENT;
761
873
  const outputsLengthInBytes = outputsLengthInElements * Float64Array.BYTES_PER_ELEMENT;
762
874
  const outputIndicesLengthInBytes = outputIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT;
875
+ const constantsLengthInBytes = constantsLengthInElements * Float64Array.BYTES_PER_ELEMENT;
876
+ const constantIndicesLengthInBytes = constantIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT;
763
877
  const lookupsLengthInBytes = lookupsLengthInElements * Float64Array.BYTES_PER_ELEMENT;
764
878
  const lookupIndicesLengthInBytes = lookupIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT;
765
- const requiredLengthInBytes = headerLengthInBytes + extrasLengthInBytes + inputsLengthInBytes + outputsLengthInBytes + outputIndicesLengthInBytes + lookupsLengthInBytes + lookupIndicesLengthInBytes;
879
+ const requiredLengthInBytes = headerLengthInBytes + extrasLengthInBytes + inputsLengthInBytes + outputsLengthInBytes + outputIndicesLengthInBytes + constantsLengthInBytes + constantIndicesLengthInBytes + lookupsLengthInBytes + lookupIndicesLengthInBytes;
766
880
  if (buffer.byteLength < requiredLengthInBytes) {
767
881
  throw new Error("Buffer must be long enough to contain sections declared in header");
768
882
  }
@@ -770,6 +884,8 @@ var BufferedRunModelParams = class {
770
884
  this.inputs.update(this.encoded, inputsOffsetInBytes, inputsLengthInElements);
771
885
  this.outputs.update(this.encoded, outputsOffsetInBytes, outputsLengthInElements);
772
886
  this.outputIndices.update(this.encoded, outputIndicesOffsetInBytes, outputIndicesLengthInElements);
887
+ this.constants.update(this.encoded, constantsOffsetInBytes, constantsLengthInElements);
888
+ this.constantIndices.update(this.encoded, constantIndicesOffsetInBytes, constantIndicesLengthInElements);
773
889
  this.lookups.update(this.encoded, lookupsOffsetInBytes, lookupsLengthInElements);
774
890
  this.lookupIndices.update(this.encoded, lookupIndicesOffsetInBytes, lookupIndicesLengthInElements);
775
891
  }
@@ -846,6 +962,14 @@ var ReferencedRunModelParams = class {
846
962
  }
847
963
  }
848
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
849
973
  getLookups() {
850
974
  if (this.lookups !== void 0 && this.lookups.length > 0) {
851
975
  return this.lookups;
@@ -875,7 +999,13 @@ var ReferencedRunModelParams = class {
875
999
  this.inputs = inputs;
876
1000
  this.outputs = outputs;
877
1001
  this.outputsLengthInElements = outputs.varIds.length * outputs.seriesLength;
1002
+ this.constants = options == null ? void 0 : options.constants;
878
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
+ }
879
1009
  if (this.lookups) {
880
1010
  for (const lookupDef of this.lookups) {
881
1011
  resolveVarRef(this.listing, lookupDef.varRef, "lookup");
@@ -1355,6 +1485,7 @@ var BaseRunnableModel = class {
1355
1485
  const t0 = perfNow();
1356
1486
  (_a = this.onRunModel) == null ? void 0 : _a.call(this, inputsArray, outputsArray, {
1357
1487
  outputIndices: outputIndicesArray,
1488
+ constants: params.getConstants(),
1358
1489
  lookups: params.getLookups()
1359
1490
  });
1360
1491
  const elapsed = perfElapsed(t0);
@@ -1396,13 +1527,14 @@ function initJsModel(model) {
1396
1527
  inputs,
1397
1528
  outputs,
1398
1529
  options == null ? void 0 : options.outputIndices,
1530
+ options == null ? void 0 : options.constants,
1399
1531
  options == null ? void 0 : options.lookups,
1400
1532
  void 0
1401
1533
  );
1402
1534
  }
1403
1535
  });
1404
1536
  }
1405
- function runJsModel(model, initialTime, finalTime, timeStep, saveFreq, numSavePoints, inputs, outputs, outputIndices, lookups, stopAfterTime) {
1537
+ function runJsModel(model, initialTime, finalTime, timeStep, saveFreq, numSavePoints, inputs, outputs, outputIndices, constants, lookups, stopAfterTime) {
1406
1538
  let time = initialTime;
1407
1539
  model.setTime(time);
1408
1540
  const fnContext = {
@@ -1411,6 +1543,11 @@ function runJsModel(model, initialTime, finalTime, timeStep, saveFreq, numSavePo
1411
1543
  };
1412
1544
  model.getModelFunctions().setContext(fnContext);
1413
1545
  model.initConstants();
1546
+ if (constants !== void 0) {
1547
+ for (const constantDef of constants) {
1548
+ model.setConstant(constantDef.varRef.varSpec, constantDef.value);
1549
+ }
1550
+ }
1414
1551
  if (lookups !== void 0) {
1415
1552
  for (const lookupDef of lookups) {
1416
1553
  model.setLookup(lookupDef.varRef.varSpec, lookupDef.points);
@@ -1497,6 +1634,7 @@ var MockJsModel = class {
1497
1634
  // from JsModel interface
1498
1635
  this.kind = "js";
1499
1636
  this.vars = /* @__PURE__ */ new Map();
1637
+ this.constants = /* @__PURE__ */ new Map();
1500
1638
  this.lookups = /* @__PURE__ */ new Map();
1501
1639
  this.outputVarIds = options.outputVarIds;
1502
1640
  this.outputVarNames = options.outputVarIds;
@@ -1549,6 +1687,14 @@ var MockJsModel = class {
1549
1687
  setInputs() {
1550
1688
  }
1551
1689
  // from JsModel interface
1690
+ setConstant(varSpec, value) {
1691
+ const varId = this.varIdForSpec(varSpec);
1692
+ if (varId === void 0) {
1693
+ throw new Error(`No constant variable found for spec ${varSpec}`);
1694
+ }
1695
+ this.constants.set(varId, value);
1696
+ }
1697
+ // from JsModel interface
1552
1698
  setLookup(varSpec, points) {
1553
1699
  const varId = this.varIdForSpec(varSpec);
1554
1700
  if (varId === void 0) {
@@ -1573,6 +1719,7 @@ var MockJsModel = class {
1573
1719
  }
1574
1720
  // from JsModel interface
1575
1721
  initConstants() {
1722
+ this.constants.clear();
1576
1723
  }
1577
1724
  // from JsModel interface
1578
1725
  initLevels() {
@@ -1580,7 +1727,7 @@ var MockJsModel = class {
1580
1727
  // from JsModel interface
1581
1728
  evalAux() {
1582
1729
  var _a;
1583
- (_a = this.onEvalAux) == null ? void 0 : _a.call(this, this.vars, this.lookups);
1730
+ (_a = this.onEvalAux) == null ? void 0 : _a.call(this, this.vars, this.constants.size > 0 ? this.constants : void 0, this.lookups);
1584
1731
  }
1585
1732
  // from JsModel interface
1586
1733
  evalLevels() {
@@ -1663,11 +1810,18 @@ var WasmModel = class {
1663
1810
  this.outputVarIds = wasmModule.outputVarIds;
1664
1811
  this.modelListing = wasmModule.modelListing;
1665
1812
  this.wasmSetLookup = wasmModule.cwrap("setLookup", null, ["number", "number", "number", "number"]);
1666
- this.wasmRunModel = wasmModule.cwrap("runModelWithBuffers", null, ["number", "number", "number"]);
1813
+ this.wasmRunModel = wasmModule.cwrap("runModelWithBuffers", null, [
1814
+ "number",
1815
+ "number",
1816
+ "number",
1817
+ "number",
1818
+ "number",
1819
+ "number"
1820
+ ]);
1667
1821
  }
1668
1822
  // from RunnableModel interface
1669
1823
  runModel(params) {
1670
- var _a, _b, _c, _d, _e, _f, _g;
1824
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1671
1825
  const lookups = params.getLookups();
1672
1826
  if (lookups !== void 0) {
1673
1827
  for (const lookupDef of lookups) {
@@ -1703,7 +1857,48 @@ var WasmModel = class {
1703
1857
  this.wasmSetLookup(varIndex, subIndicesAddress, pointsAddress, numPoints);
1704
1858
  }
1705
1859
  }
1706
- params.copyInputs((_d = this.inputsBuffer) == null ? void 0 : _d.getArrayView(), (numElements) => {
1860
+ let constantIndicesBuffer;
1861
+ let constantValuesBuffer;
1862
+ const constants = params.getConstants();
1863
+ if (constants !== void 0 && constants.length > 0) {
1864
+ let totalIndicesSize = 1;
1865
+ for (const constantDef of constants) {
1866
+ const numSubElements = ((_d = constantDef.varRef.varSpec.subscriptIndices) == null ? void 0 : _d.length) || 0;
1867
+ totalIndicesSize += 2 + numSubElements;
1868
+ }
1869
+ if (this.constantIndicesBuffer === void 0 || this.constantIndicesBuffer.numElements < totalIndicesSize) {
1870
+ (_e = this.constantIndicesBuffer) == null ? void 0 : _e.dispose();
1871
+ this.constantIndicesBuffer = createInt32WasmBuffer(this.wasmModule, totalIndicesSize);
1872
+ }
1873
+ const numConstants = constants.length;
1874
+ if (this.constantValuesBuffer === void 0 || this.constantValuesBuffer.numElements < numConstants) {
1875
+ (_f = this.constantValuesBuffer) == null ? void 0 : _f.dispose();
1876
+ this.constantValuesBuffer = createFloat64WasmBuffer(this.wasmModule, numConstants);
1877
+ }
1878
+ const indicesView = this.constantIndicesBuffer.getArrayView();
1879
+ const valuesView = this.constantValuesBuffer.getArrayView();
1880
+ let indicesOffset = 0;
1881
+ let valuesOffset = 0;
1882
+ indicesView[indicesOffset++] = numConstants;
1883
+ for (const constantDef of constants) {
1884
+ const varSpec = constantDef.varRef.varSpec;
1885
+ const numSubElements = ((_g = varSpec.subscriptIndices) == null ? void 0 : _g.length) || 0;
1886
+ indicesView[indicesOffset++] = varSpec.varIndex;
1887
+ indicesView[indicesOffset++] = numSubElements;
1888
+ if (numSubElements > 0) {
1889
+ for (let i = 0; i < numSubElements; i++) {
1890
+ indicesView[indicesOffset++] = varSpec.subscriptIndices[i];
1891
+ }
1892
+ }
1893
+ valuesView[valuesOffset++] = constantDef.value;
1894
+ }
1895
+ constantIndicesBuffer = this.constantIndicesBuffer;
1896
+ constantValuesBuffer = this.constantValuesBuffer;
1897
+ } else {
1898
+ constantIndicesBuffer = void 0;
1899
+ constantValuesBuffer = void 0;
1900
+ }
1901
+ params.copyInputs((_h = this.inputsBuffer) == null ? void 0 : _h.getArrayView(), (numElements) => {
1707
1902
  var _a2;
1708
1903
  (_a2 = this.inputsBuffer) == null ? void 0 : _a2.dispose();
1709
1904
  this.inputsBuffer = createFloat64WasmBuffer(this.wasmModule, numElements);
@@ -1711,7 +1906,7 @@ var WasmModel = class {
1711
1906
  });
1712
1907
  let outputIndicesBuffer;
1713
1908
  if (params.getOutputIndicesLength() > 0) {
1714
- params.copyOutputIndices((_e = this.outputIndicesBuffer) == null ? void 0 : _e.getArrayView(), (numElements) => {
1909
+ params.copyOutputIndices((_i = this.outputIndicesBuffer) == null ? void 0 : _i.getArrayView(), (numElements) => {
1715
1910
  var _a2;
1716
1911
  (_a2 = this.outputIndicesBuffer) == null ? void 0 : _a2.dispose();
1717
1912
  this.outputIndicesBuffer = createInt32WasmBuffer(this.wasmModule, numElements);
@@ -1723,14 +1918,19 @@ var WasmModel = class {
1723
1918
  }
1724
1919
  const outputsLengthInElements = params.getOutputsLength();
1725
1920
  if (this.outputsBuffer === void 0 || this.outputsBuffer.numElements < outputsLengthInElements) {
1726
- (_f = this.outputsBuffer) == null ? void 0 : _f.dispose();
1921
+ (_j = this.outputsBuffer) == null ? void 0 : _j.dispose();
1727
1922
  this.outputsBuffer = createFloat64WasmBuffer(this.wasmModule, outputsLengthInElements);
1728
1923
  }
1729
1924
  const t0 = perfNow();
1730
1925
  this.wasmRunModel(
1731
- ((_g = this.inputsBuffer) == null ? void 0 : _g.getAddress()) || 0,
1926
+ ((_k = this.inputsBuffer) == null ? void 0 : _k.getAddress()) || 0,
1927
+ // Always pass 0 (NULL) for input indices, since we assume that all input values are
1928
+ // provided and are in the same order as the input variables defined in the model spec
1929
+ 0,
1732
1930
  this.outputsBuffer.getAddress(),
1733
- (outputIndicesBuffer == null ? void 0 : outputIndicesBuffer.getAddress()) || 0
1931
+ (outputIndicesBuffer == null ? void 0 : outputIndicesBuffer.getAddress()) || 0,
1932
+ (constantValuesBuffer == null ? void 0 : constantValuesBuffer.getAddress()) || 0,
1933
+ (constantIndicesBuffer == null ? void 0 : constantIndicesBuffer.getAddress()) || 0
1734
1934
  );
1735
1935
  const elapsed = perfElapsed(t0);
1736
1936
  params.storeOutputs(this.outputsBuffer.getArrayView());
@@ -1738,13 +1938,17 @@ var WasmModel = class {
1738
1938
  }
1739
1939
  // from RunnableModel interface
1740
1940
  terminate() {
1741
- var _a, _b, _c;
1941
+ var _a, _b, _c, _d, _e;
1742
1942
  (_a = this.inputsBuffer) == null ? void 0 : _a.dispose();
1743
1943
  this.inputsBuffer = void 0;
1744
1944
  (_b = this.outputsBuffer) == null ? void 0 : _b.dispose();
1745
1945
  this.outputsBuffer = void 0;
1746
1946
  (_c = this.outputIndicesBuffer) == null ? void 0 : _c.dispose();
1747
1947
  this.outputIndicesBuffer = void 0;
1948
+ (_d = this.constantValuesBuffer) == null ? void 0 : _d.dispose();
1949
+ this.constantValuesBuffer = void 0;
1950
+ (_e = this.constantIndicesBuffer) == null ? void 0 : _e.dispose();
1951
+ this.constantIndicesBuffer = void 0;
1748
1952
  }
1749
1953
  };
1750
1954
  function initWasmModel(wasmModule) {
@@ -1760,6 +1964,7 @@ var MockWasmModule = class {
1760
1964
  this.mallocOffset = 8;
1761
1965
  this.allocs = /* @__PURE__ */ new Map();
1762
1966
  this.lookups = /* @__PURE__ */ new Map();
1967
+ this.constants = /* @__PURE__ */ new Map();
1763
1968
  this.initialTime = options.initialTime;
1764
1969
  this.finalTime = options.finalTime;
1765
1970
  this.outputVarIds = options.outputVarIds;
@@ -1799,11 +2004,35 @@ var MockWasmModule = class {
1799
2004
  this.lookups.set(varId, new JsModelLookup(numPoints, points));
1800
2005
  };
1801
2006
  case "runModelWithBuffers":
1802
- return (inputsAddress, outputsAddress, outputIndicesAddress) => {
2007
+ return (inputsAddress, _inputIndicesAddress, outputsAddress, outputIndicesAddress, constantValuesAddress, constantIndicesAddress) => {
1803
2008
  const inputs = this.getHeapView("float64", inputsAddress);
1804
2009
  const outputs = this.getHeapView("float64", outputsAddress);
1805
2010
  const outputIndices = this.getHeapView("int32", outputIndicesAddress);
1806
- this.onRunModel(inputs, outputs, this.lookups, outputIndices);
2011
+ this.constants.clear();
2012
+ if (constantValuesAddress !== 0 && constantIndicesAddress !== 0) {
2013
+ const constantValues = this.getHeapView("float64", constantValuesAddress);
2014
+ const constantIndices = this.getHeapView("int32", constantIndicesAddress);
2015
+ const numConstants = constantIndices[0];
2016
+ let indicesOffset = 1;
2017
+ let valuesOffset = 0;
2018
+ for (let i = 0; i < numConstants; i++) {
2019
+ const varIndex = constantIndices[indicesOffset++];
2020
+ const subCount = constantIndices[indicesOffset++];
2021
+ indicesOffset += subCount;
2022
+ const varId = this.varIdForSpec({ varIndex });
2023
+ if (varId) {
2024
+ this.constants.set(varId, constantValues[valuesOffset++]);
2025
+ }
2026
+ }
2027
+ }
2028
+ this.onRunModel(
2029
+ inputs,
2030
+ outputs,
2031
+ this.constants.size > 0 ? this.constants : void 0,
2032
+ this.lookups,
2033
+ outputIndices
2034
+ );
2035
+ this.constants.clear();
1807
2036
  };
1808
2037
  default:
1809
2038
  throw new Error(`Unhandled call to cwrap with function name '${fname}'`);
@@ -1881,7 +2110,7 @@ function createRunnerFromRunnableModel(model) {
1881
2110
  }
1882
2111
  return runModelSync(inputs, outputs, options);
1883
2112
  },
1884
- terminate: () => __async(this, null, function* () {
2113
+ terminate: () => __async(null, null, function* () {
1885
2114
  if (!terminated) {
1886
2115
  model.terminate();
1887
2116
  terminated = true;
@@ -1906,7 +2135,7 @@ var ModelScheduler = class {
1906
2135
  /** Whether a model run is in progress. */
1907
2136
  this.runInProgress = false;
1908
2137
  const afterSet = () => {
1909
- this.runWasmModelIfNeeded();
2138
+ this.runModelIfNeeded();
1910
2139
  };
1911
2140
  for (const userInput of userInputs) {
1912
2141
  userInput.callbacks.onSet = afterSet;
@@ -1917,24 +2146,24 @@ var ModelScheduler = class {
1917
2146
  }
1918
2147
  }
1919
2148
  /**
1920
- * Schedule a wasm model run (if not already pending). When the run is
2149
+ * Schedule a model run (if not already pending). When the run is
1921
2150
  * complete, save the outputs and call the `onOutputsChanged` callback.
1922
2151
  */
1923
- runWasmModelIfNeeded() {
2152
+ runModelIfNeeded() {
1924
2153
  this.runNeeded = true;
1925
2154
  if (this.runInProgress) {
1926
2155
  return;
1927
2156
  } else {
1928
2157
  this.runInProgress = true;
1929
2158
  setTimeout(() => {
1930
- this.runWasmModelNow();
2159
+ this.runModelNow();
1931
2160
  }, 0);
1932
2161
  }
1933
2162
  }
1934
2163
  /**
1935
- * Run the wasm model asynchronously using the current set of input values.
2164
+ * Run the model asynchronously using the current set of input values.
1936
2165
  */
1937
- runWasmModelNow() {
2166
+ runModelNow() {
1938
2167
  return __async(this, null, function* () {
1939
2168
  var _a;
1940
2169
  for (let i = 0; i < this.userInputs.length; i++) {
@@ -1949,7 +2178,7 @@ var ModelScheduler = class {
1949
2178
  if (this.runNeeded) {
1950
2179
  this.runNeeded = false;
1951
2180
  setTimeout(() => {
1952
- this.runWasmModelNow();
2181
+ this.runModelNow();
1953
2182
  }, 0);
1954
2183
  } else {
1955
2184
  this.runNeeded = false;
@@ -1971,6 +2200,192 @@ function createSimpleInputValue(varId) {
1971
2200
  };
1972
2201
  return { varId, get, set, reset, callbacks: {} };
1973
2202
  }
2203
+
2204
+ // src/model-scheduler/multi-context-model-scheduler.ts
2205
+ var MultiContextModelScheduler = class {
2206
+ /**
2207
+ * @param runner The model runner.
2208
+ * @param options Additional options for the scheduler.
2209
+ * @param options.initialOutputs An optional `Outputs` instance that will be reused
2210
+ * for the initial context. This is useful for saving memory when an `Outputs`
2211
+ * instance was already created for, e.g., a initial baseline/reference run.
2212
+ */
2213
+ constructor(runner, options) {
2214
+ this.runner = runner;
2215
+ /** The contexts that hold distinct sets of inputs and outputs. */
2216
+ this.contexts = [];
2217
+ /** Whether a model run has been scheduled. */
2218
+ this.runNeeded = false;
2219
+ /** Whether a model run is in progress. */
2220
+ this.runInProgress = false;
2221
+ this.initialOutputs = options == null ? void 0 : options.initialOutputs;
2222
+ }
2223
+ /**
2224
+ * Return true if the scheduler has started any model runs.
2225
+ */
2226
+ isStarted() {
2227
+ return this.initialOutputs === void 0;
2228
+ }
2229
+ /**
2230
+ * Add a new context that holds a distinct set of model inputs and outputs.
2231
+ * These inputs and outputs are kept separate from those in other contexts,
2232
+ * which allows an application to use the same underlying model to run with
2233
+ * multiple I/O contexts.
2234
+ *
2235
+ * Note that the contexts created before the first scheduled model run
2236
+ * will inherit the data from `initialOutputs` passed to the constructor,
2237
+ * but contexts created after that will initially have output values set
2238
+ * to zero.
2239
+ *
2240
+ * @param inputs The input values, in the same order as in the spec file passed to `sde`.
2241
+ * @param options Additional options for the context.
2242
+ * @param options.externalData Additional data that is external to the model outputs.
2243
+ * For example, this can contain data that was captured from an initial reference
2244
+ * run, or other static data that is displayed in graphs alongside the model
2245
+ * output data in graphs.
2246
+ */
2247
+ addContext(inputs, options) {
2248
+ let outputs;
2249
+ if (this.initialOutputs !== void 0) {
2250
+ if (this.contexts.length === 0) {
2251
+ outputs = this.initialOutputs;
2252
+ } else {
2253
+ outputs = this.runner.createOutputs();
2254
+ for (const varId of outputs.varIds) {
2255
+ const series0 = this.initialOutputs.getSeriesForVar(varId);
2256
+ const series1 = outputs.getSeriesForVar(varId);
2257
+ for (let i = 0; i < series0.points.length; i++) {
2258
+ series1.points[i].y = series0.points[i].y;
2259
+ }
2260
+ }
2261
+ }
2262
+ } else {
2263
+ outputs = this.runner.createOutputs();
2264
+ }
2265
+ const context = new ModelContextImpl(inputs, outputs, options == null ? void 0 : options.externalData);
2266
+ const afterSet = () => {
2267
+ context.runNeeded = true;
2268
+ this.runModelIfNeeded();
2269
+ };
2270
+ for (const input of inputs) {
2271
+ input.callbacks.onSet = afterSet;
2272
+ }
2273
+ this.contexts.push(context);
2274
+ return context;
2275
+ }
2276
+ /**
2277
+ * Remove the given context from the set of contexts managed by the scheduler.
2278
+ *
2279
+ * @param context The context to remove.
2280
+ */
2281
+ removeContext(context) {
2282
+ const index = this.contexts.findIndex((c) => c === context);
2283
+ if (index >= 0) {
2284
+ this.contexts.splice(index, 1);
2285
+ }
2286
+ }
2287
+ /**
2288
+ * Schedule a model run (if not already pending). When the run is
2289
+ * complete, save the outputs and call the `onOutputsChanged` callback.
2290
+ */
2291
+ runModelIfNeeded() {
2292
+ this.runNeeded = true;
2293
+ if (this.runInProgress) {
2294
+ return;
2295
+ } else {
2296
+ this.runInProgress = true;
2297
+ setTimeout(() => {
2298
+ this.runModelNow();
2299
+ }, 0);
2300
+ }
2301
+ }
2302
+ /**
2303
+ * Run the model asynchronously for all relevant contexts.
2304
+ */
2305
+ runModelNow() {
2306
+ return __async(this, null, function* () {
2307
+ this.initialOutputs = void 0;
2308
+ for (const context of this.contexts) {
2309
+ if (context.runNeeded) {
2310
+ context.runNeeded = false;
2311
+ yield this.runModelNowForContext(context);
2312
+ }
2313
+ }
2314
+ if (this.runNeeded) {
2315
+ this.runNeeded = false;
2316
+ setTimeout(() => {
2317
+ this.runModelNow();
2318
+ }, 0);
2319
+ } else {
2320
+ this.runNeeded = false;
2321
+ this.runInProgress = false;
2322
+ }
2323
+ });
2324
+ }
2325
+ /**
2326
+ * Run the model asynchronously using the current set of input values in the given context.
2327
+ *
2328
+ * @param context The context to use for the model run.
2329
+ */
2330
+ runModelNowForContext(context) {
2331
+ return __async(this, null, function* () {
2332
+ var _a;
2333
+ if (this.currentInputs === void 0) {
2334
+ this.currentInputs = Array(context.inputsArray.length);
2335
+ }
2336
+ for (let i = 0; i < context.inputsArray.length; i++) {
2337
+ this.currentInputs[i] = context.inputsArray[i].get();
2338
+ }
2339
+ try {
2340
+ yield this.runner.runModel(this.currentInputs, context.outputs);
2341
+ (_a = context.onOutputsChanged) == null ? void 0 : _a.call(context);
2342
+ } catch (e) {
2343
+ console.error("ERROR: The scheduler encountered an error when running the model:", e);
2344
+ }
2345
+ });
2346
+ }
2347
+ };
2348
+ var ModelContextImpl = class {
2349
+ /**
2350
+ * @hidden This is intended for use by `MultiContextModelScheduler` only.
2351
+ *
2352
+ * @param inputs The input values, in the same order as in the spec file passed to `sde`.
2353
+ * @param outputs The structure into which the model outputs will be stored.
2354
+ * @param externalData Additional data that is external to the model outputs. For example, this can contain
2355
+ * data that was captured from an initial reference run, or other static data that is displayed in graphs
2356
+ * alongside the model output data in graphs.
2357
+ */
2358
+ constructor(inputs, outputs, externalData) {
2359
+ this.externalData = externalData;
2360
+ /**
2361
+ * Whether a model run is needed for this context.
2362
+ * @hidden This is intended for use by `MultiContextModelScheduler` only.
2363
+ */
2364
+ this.runNeeded = false;
2365
+ this.inputsArray = Array.from(inputs);
2366
+ this.outputs = outputs;
2367
+ }
2368
+ /**
2369
+ * Return the series data for the given model output variable or external
2370
+ * dataset.
2371
+ *
2372
+ * @param varId The ID of the output variable associated with the data.
2373
+ * @param sourceName The external data source name (e.g. "Ref"), or
2374
+ * undefined to use the latest model output data from this context.
2375
+ */
2376
+ getSeriesForVar(varId, sourceName) {
2377
+ if (sourceName === void 0) {
2378
+ return this.outputs.getSeriesForVar(varId);
2379
+ } else {
2380
+ const dataForSource = this.externalData.get(sourceName);
2381
+ if (dataForSource !== void 0) {
2382
+ return dataForSource.get(varId);
2383
+ } else {
2384
+ return void 0;
2385
+ }
2386
+ }
2387
+ }
2388
+ };
1974
2389
  // Annotate the CommonJS export names for ESM import in node:
1975
2390
  0 && (module.exports = {
1976
2391
  BufferedRunModelParams,
@@ -1978,17 +2393,22 @@ function createSimpleInputValue(varId) {
1978
2393
  MockWasmModule,
1979
2394
  ModelListing,
1980
2395
  ModelScheduler,
2396
+ MultiContextModelScheduler,
1981
2397
  Outputs,
1982
2398
  ReferencedRunModelParams,
1983
2399
  Series,
2400
+ createConstantDef,
1984
2401
  createInputValue,
1985
2402
  createLookupDef,
1986
2403
  createRunnableModel,
1987
2404
  createSynchronousModelRunner,
2405
+ decodeConstants,
1988
2406
  decodeLookups,
2407
+ encodeConstants,
1989
2408
  encodeLookups,
1990
2409
  encodeVarIndices,
1991
2410
  execJsModel,
2411
+ getEncodedConstantBufferLengths,
1992
2412
  getEncodedLookupBufferLengths,
1993
2413
  getEncodedVarIndicesLength,
1994
2414
  getJsModelFunctions,