@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.js CHANGED
@@ -206,6 +206,66 @@ function encodeVarIndices(varSpecs, indicesArray) {
206
206
  }
207
207
  }
208
208
  }
209
+ function getEncodedConstantBufferLengths(constantDefs) {
210
+ var _a;
211
+ let constantIndicesLength = 1;
212
+ let constantsLength = 0;
213
+ for (const constantDef of constantDefs) {
214
+ const varSpec = constantDef.varRef.varSpec;
215
+ if (varSpec === void 0) {
216
+ throw new Error("Cannot compute constant buffer lengths until all constant var specs are defined");
217
+ }
218
+ constantIndicesLength += 2;
219
+ const subCount = ((_a = varSpec.subscriptIndices) == null ? void 0 : _a.length) || 0;
220
+ constantIndicesLength += subCount;
221
+ constantsLength += 1;
222
+ }
223
+ return {
224
+ constantIndicesLength,
225
+ constantsLength
226
+ };
227
+ }
228
+ function encodeConstants(constantDefs, constantIndicesArray, constantsArray) {
229
+ let ci = 0;
230
+ constantIndicesArray[ci++] = constantDefs.length;
231
+ let constantDataOffset = 0;
232
+ for (const constantDef of constantDefs) {
233
+ const varSpec = constantDef.varRef.varSpec;
234
+ constantIndicesArray[ci++] = varSpec.varIndex;
235
+ const subs = varSpec.subscriptIndices;
236
+ const subCount = (subs == null ? void 0 : subs.length) || 0;
237
+ constantIndicesArray[ci++] = subCount;
238
+ for (let i = 0; i < subCount; i++) {
239
+ constantIndicesArray[ci++] = subs[i];
240
+ }
241
+ constantsArray[constantDataOffset++] = constantDef.value;
242
+ }
243
+ }
244
+ function decodeConstants(constantIndicesArray, constantsArray) {
245
+ const constantDefs = [];
246
+ let ci = 0;
247
+ const constantCount = constantIndicesArray[ci++];
248
+ for (let i = 0; i < constantCount; i++) {
249
+ const varIndex = constantIndicesArray[ci++];
250
+ const subCount = constantIndicesArray[ci++];
251
+ const subscriptIndices = subCount > 0 ? Array(subCount) : void 0;
252
+ for (let subIndex = 0; subIndex < subCount; subIndex++) {
253
+ subscriptIndices[subIndex] = constantIndicesArray[ci++];
254
+ }
255
+ const varSpec = {
256
+ varIndex,
257
+ subscriptIndices
258
+ };
259
+ const value = constantsArray[i];
260
+ constantDefs.push({
261
+ varRef: {
262
+ varSpec
263
+ },
264
+ value
265
+ });
266
+ }
267
+ return constantDefs;
268
+ }
209
269
  function getEncodedLookupBufferLengths(lookupDefs) {
210
270
  var _a, _b;
211
271
  let lookupIndicesLength = 1;
@@ -287,6 +347,14 @@ function decodeLookups(lookupIndicesArray, lookupsArray) {
287
347
  return lookupDefs;
288
348
  }
289
349
 
350
+ // src/_shared/constant-def.ts
351
+ function createConstantDef(varRef, value) {
352
+ return {
353
+ varRef,
354
+ value
355
+ };
356
+ }
357
+
290
358
  // src/_shared/lookup-def.ts
291
359
  function createLookupDef(varRef, points) {
292
360
  let flatPoints;
@@ -457,7 +525,7 @@ function resolveVarRef(listing, varRef, varKind) {
457
525
  }
458
526
 
459
527
  // src/runnable-model/buffered-run-model-params.ts
460
- var headerLengthInElements = 16;
528
+ var headerLengthInElements = 20;
461
529
  var extrasLengthInElements = 1;
462
530
  var Int32Section = class {
463
531
  constructor() {
@@ -502,6 +570,10 @@ var BufferedRunModelParams = class {
502
570
  this.outputs = new Float64Section();
503
571
  /** The output indices section of the `encoded` buffer. */
504
572
  this.outputIndices = new Int32Section();
573
+ /** The constant values section of the `encoded` buffer. */
574
+ this.constants = new Float64Section();
575
+ /** The constant indices section of the `encoded` buffer. */
576
+ this.constantIndices = new Int32Section();
505
577
  /** The lookup data section of the `encoded` buffer. */
506
578
  this.lookups = new Float64Section();
507
579
  /** The lookup indices section of the `encoded` buffer. */
@@ -569,6 +641,13 @@ var BufferedRunModelParams = class {
569
641
  }
570
642
  }
571
643
  // from RunModelParams interface
644
+ getConstants() {
645
+ if (this.constantIndices.lengthInElements === 0) {
646
+ return void 0;
647
+ }
648
+ return decodeConstants(this.constantIndices.view, this.constants.view);
649
+ }
650
+ // from RunModelParams interface
572
651
  getLookups() {
573
652
  if (this.lookupIndices.lengthInElements === 0) {
574
653
  return void 0;
@@ -613,6 +692,19 @@ var BufferedRunModelParams = class {
613
692
  } else {
614
693
  outputIndicesLengthInElements = 0;
615
694
  }
695
+ let constantsLengthInElements;
696
+ let constantIndicesLengthInElements;
697
+ if ((options == null ? void 0 : options.constants) !== void 0 && options.constants.length > 0) {
698
+ for (const constantDef of options.constants) {
699
+ resolveVarRef(this.listing, constantDef.varRef, "constant");
700
+ }
701
+ const encodedLengths = getEncodedConstantBufferLengths(options.constants);
702
+ constantsLengthInElements = encodedLengths.constantsLength;
703
+ constantIndicesLengthInElements = encodedLengths.constantIndicesLength;
704
+ } else {
705
+ constantsLengthInElements = 0;
706
+ constantIndicesLengthInElements = 0;
707
+ }
616
708
  let lookupsLengthInElements;
617
709
  let lookupIndicesLengthInElements;
618
710
  if ((options == null ? void 0 : options.lookups) !== void 0 && options.lookups.length > 0) {
@@ -640,6 +732,8 @@ var BufferedRunModelParams = class {
640
732
  const inputsOffsetInBytes = section("float64", inputsLengthInElements);
641
733
  const outputsOffsetInBytes = section("float64", outputsLengthInElements);
642
734
  const outputIndicesOffsetInBytes = section("int32", outputIndicesLengthInElements);
735
+ const constantsOffsetInBytes = section("float64", constantsLengthInElements);
736
+ const constantIndicesOffsetInBytes = section("int32", constantIndicesLengthInElements);
643
737
  const lookupsOffsetInBytes = section("float64", lookupsLengthInElements);
644
738
  const lookupIndicesOffsetInBytes = section("int32", lookupIndicesLengthInElements);
645
739
  const requiredLengthInBytes = byteOffset;
@@ -658,6 +752,10 @@ var BufferedRunModelParams = class {
658
752
  headerView[headerIndex++] = outputsLengthInElements;
659
753
  headerView[headerIndex++] = outputIndicesOffsetInBytes;
660
754
  headerView[headerIndex++] = outputIndicesLengthInElements;
755
+ headerView[headerIndex++] = constantsOffsetInBytes;
756
+ headerView[headerIndex++] = constantsLengthInElements;
757
+ headerView[headerIndex++] = constantIndicesOffsetInBytes;
758
+ headerView[headerIndex++] = constantIndicesLengthInElements;
661
759
  headerView[headerIndex++] = lookupsOffsetInBytes;
662
760
  headerView[headerIndex++] = lookupsLengthInElements;
663
761
  headerView[headerIndex++] = lookupIndicesOffsetInBytes;
@@ -666,6 +764,8 @@ var BufferedRunModelParams = class {
666
764
  this.extras.update(this.encoded, extrasOffsetInBytes, extrasLengthInElements);
667
765
  this.outputs.update(this.encoded, outputsOffsetInBytes, outputsLengthInElements);
668
766
  this.outputIndices.update(this.encoded, outputIndicesOffsetInBytes, outputIndicesLengthInElements);
767
+ this.constants.update(this.encoded, constantsOffsetInBytes, constantsLengthInElements);
768
+ this.constantIndices.update(this.encoded, constantIndicesOffsetInBytes, constantIndicesLengthInElements);
669
769
  this.lookups.update(this.encoded, lookupsOffsetInBytes, lookupsLengthInElements);
670
770
  this.lookupIndices.update(this.encoded, lookupIndicesOffsetInBytes, lookupIndicesLengthInElements);
671
771
  const inputsView = this.inputs.view;
@@ -680,6 +780,9 @@ var BufferedRunModelParams = class {
680
780
  if (this.outputIndices.view) {
681
781
  encodeVarIndices(outputVarSpecs, this.outputIndices.view);
682
782
  }
783
+ if (constantIndicesLengthInElements > 0) {
784
+ encodeConstants(options.constants, this.constantIndices.view, this.constants.view);
785
+ }
683
786
  if (lookupIndicesLengthInElements > 0) {
684
787
  encodeLookups(options.lookups, this.lookupIndices.view, this.lookups.view);
685
788
  }
@@ -708,6 +811,10 @@ var BufferedRunModelParams = class {
708
811
  const outputsLengthInElements = headerView[headerIndex++];
709
812
  const outputIndicesOffsetInBytes = headerView[headerIndex++];
710
813
  const outputIndicesLengthInElements = headerView[headerIndex++];
814
+ const constantsOffsetInBytes = headerView[headerIndex++];
815
+ const constantsLengthInElements = headerView[headerIndex++];
816
+ const constantIndicesOffsetInBytes = headerView[headerIndex++];
817
+ const constantIndicesLengthInElements = headerView[headerIndex++];
711
818
  const lookupsOffsetInBytes = headerView[headerIndex++];
712
819
  const lookupsLengthInElements = headerView[headerIndex++];
713
820
  const lookupIndicesOffsetInBytes = headerView[headerIndex++];
@@ -716,9 +823,11 @@ var BufferedRunModelParams = class {
716
823
  const inputsLengthInBytes = inputsLengthInElements * Float64Array.BYTES_PER_ELEMENT;
717
824
  const outputsLengthInBytes = outputsLengthInElements * Float64Array.BYTES_PER_ELEMENT;
718
825
  const outputIndicesLengthInBytes = outputIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT;
826
+ const constantsLengthInBytes = constantsLengthInElements * Float64Array.BYTES_PER_ELEMENT;
827
+ const constantIndicesLengthInBytes = constantIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT;
719
828
  const lookupsLengthInBytes = lookupsLengthInElements * Float64Array.BYTES_PER_ELEMENT;
720
829
  const lookupIndicesLengthInBytes = lookupIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT;
721
- const requiredLengthInBytes = headerLengthInBytes + extrasLengthInBytes + inputsLengthInBytes + outputsLengthInBytes + outputIndicesLengthInBytes + lookupsLengthInBytes + lookupIndicesLengthInBytes;
830
+ const requiredLengthInBytes = headerLengthInBytes + extrasLengthInBytes + inputsLengthInBytes + outputsLengthInBytes + outputIndicesLengthInBytes + constantsLengthInBytes + constantIndicesLengthInBytes + lookupsLengthInBytes + lookupIndicesLengthInBytes;
722
831
  if (buffer.byteLength < requiredLengthInBytes) {
723
832
  throw new Error("Buffer must be long enough to contain sections declared in header");
724
833
  }
@@ -726,6 +835,8 @@ var BufferedRunModelParams = class {
726
835
  this.inputs.update(this.encoded, inputsOffsetInBytes, inputsLengthInElements);
727
836
  this.outputs.update(this.encoded, outputsOffsetInBytes, outputsLengthInElements);
728
837
  this.outputIndices.update(this.encoded, outputIndicesOffsetInBytes, outputIndicesLengthInElements);
838
+ this.constants.update(this.encoded, constantsOffsetInBytes, constantsLengthInElements);
839
+ this.constantIndices.update(this.encoded, constantIndicesOffsetInBytes, constantIndicesLengthInElements);
729
840
  this.lookups.update(this.encoded, lookupsOffsetInBytes, lookupsLengthInElements);
730
841
  this.lookupIndices.update(this.encoded, lookupIndicesOffsetInBytes, lookupIndicesLengthInElements);
731
842
  }
@@ -802,6 +913,14 @@ var ReferencedRunModelParams = class {
802
913
  }
803
914
  }
804
915
  // from RunModelParams interface
916
+ getConstants() {
917
+ if (this.constants !== void 0 && this.constants.length > 0) {
918
+ return this.constants;
919
+ } else {
920
+ return void 0;
921
+ }
922
+ }
923
+ // from RunModelParams interface
805
924
  getLookups() {
806
925
  if (this.lookups !== void 0 && this.lookups.length > 0) {
807
926
  return this.lookups;
@@ -831,7 +950,13 @@ var ReferencedRunModelParams = class {
831
950
  this.inputs = inputs;
832
951
  this.outputs = outputs;
833
952
  this.outputsLengthInElements = outputs.varIds.length * outputs.seriesLength;
953
+ this.constants = options == null ? void 0 : options.constants;
834
954
  this.lookups = options == null ? void 0 : options.lookups;
955
+ if (this.constants) {
956
+ for (const constantDef of this.constants) {
957
+ resolveVarRef(this.listing, constantDef.varRef, "constant");
958
+ }
959
+ }
835
960
  if (this.lookups) {
836
961
  for (const lookupDef of this.lookups) {
837
962
  resolveVarRef(this.listing, lookupDef.varRef, "lookup");
@@ -1311,6 +1436,7 @@ var BaseRunnableModel = class {
1311
1436
  const t0 = perfNow();
1312
1437
  (_a = this.onRunModel) == null ? void 0 : _a.call(this, inputsArray, outputsArray, {
1313
1438
  outputIndices: outputIndicesArray,
1439
+ constants: params.getConstants(),
1314
1440
  lookups: params.getLookups()
1315
1441
  });
1316
1442
  const elapsed = perfElapsed(t0);
@@ -1352,13 +1478,14 @@ function initJsModel(model) {
1352
1478
  inputs,
1353
1479
  outputs,
1354
1480
  options == null ? void 0 : options.outputIndices,
1481
+ options == null ? void 0 : options.constants,
1355
1482
  options == null ? void 0 : options.lookups,
1356
1483
  void 0
1357
1484
  );
1358
1485
  }
1359
1486
  });
1360
1487
  }
1361
- function runJsModel(model, initialTime, finalTime, timeStep, saveFreq, numSavePoints, inputs, outputs, outputIndices, lookups, stopAfterTime) {
1488
+ function runJsModel(model, initialTime, finalTime, timeStep, saveFreq, numSavePoints, inputs, outputs, outputIndices, constants, lookups, stopAfterTime) {
1362
1489
  let time = initialTime;
1363
1490
  model.setTime(time);
1364
1491
  const fnContext = {
@@ -1367,6 +1494,11 @@ function runJsModel(model, initialTime, finalTime, timeStep, saveFreq, numSavePo
1367
1494
  };
1368
1495
  model.getModelFunctions().setContext(fnContext);
1369
1496
  model.initConstants();
1497
+ if (constants !== void 0) {
1498
+ for (const constantDef of constants) {
1499
+ model.setConstant(constantDef.varRef.varSpec, constantDef.value);
1500
+ }
1501
+ }
1370
1502
  if (lookups !== void 0) {
1371
1503
  for (const lookupDef of lookups) {
1372
1504
  model.setLookup(lookupDef.varRef.varSpec, lookupDef.points);
@@ -1453,6 +1585,7 @@ var MockJsModel = class {
1453
1585
  // from JsModel interface
1454
1586
  this.kind = "js";
1455
1587
  this.vars = /* @__PURE__ */ new Map();
1588
+ this.constants = /* @__PURE__ */ new Map();
1456
1589
  this.lookups = /* @__PURE__ */ new Map();
1457
1590
  this.outputVarIds = options.outputVarIds;
1458
1591
  this.outputVarNames = options.outputVarIds;
@@ -1505,6 +1638,14 @@ var MockJsModel = class {
1505
1638
  setInputs() {
1506
1639
  }
1507
1640
  // from JsModel interface
1641
+ setConstant(varSpec, value) {
1642
+ const varId = this.varIdForSpec(varSpec);
1643
+ if (varId === void 0) {
1644
+ throw new Error(`No constant variable found for spec ${varSpec}`);
1645
+ }
1646
+ this.constants.set(varId, value);
1647
+ }
1648
+ // from JsModel interface
1508
1649
  setLookup(varSpec, points) {
1509
1650
  const varId = this.varIdForSpec(varSpec);
1510
1651
  if (varId === void 0) {
@@ -1529,6 +1670,7 @@ var MockJsModel = class {
1529
1670
  }
1530
1671
  // from JsModel interface
1531
1672
  initConstants() {
1673
+ this.constants.clear();
1532
1674
  }
1533
1675
  // from JsModel interface
1534
1676
  initLevels() {
@@ -1536,7 +1678,7 @@ var MockJsModel = class {
1536
1678
  // from JsModel interface
1537
1679
  evalAux() {
1538
1680
  var _a;
1539
- (_a = this.onEvalAux) == null ? void 0 : _a.call(this, this.vars, this.lookups);
1681
+ (_a = this.onEvalAux) == null ? void 0 : _a.call(this, this.vars, this.constants.size > 0 ? this.constants : void 0, this.lookups);
1540
1682
  }
1541
1683
  // from JsModel interface
1542
1684
  evalLevels() {
@@ -1619,11 +1761,18 @@ var WasmModel = class {
1619
1761
  this.outputVarIds = wasmModule.outputVarIds;
1620
1762
  this.modelListing = wasmModule.modelListing;
1621
1763
  this.wasmSetLookup = wasmModule.cwrap("setLookup", null, ["number", "number", "number", "number"]);
1622
- this.wasmRunModel = wasmModule.cwrap("runModelWithBuffers", null, ["number", "number", "number"]);
1764
+ this.wasmRunModel = wasmModule.cwrap("runModelWithBuffers", null, [
1765
+ "number",
1766
+ "number",
1767
+ "number",
1768
+ "number",
1769
+ "number",
1770
+ "number"
1771
+ ]);
1623
1772
  }
1624
1773
  // from RunnableModel interface
1625
1774
  runModel(params) {
1626
- var _a, _b, _c, _d, _e, _f, _g;
1775
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
1627
1776
  const lookups = params.getLookups();
1628
1777
  if (lookups !== void 0) {
1629
1778
  for (const lookupDef of lookups) {
@@ -1659,7 +1808,48 @@ var WasmModel = class {
1659
1808
  this.wasmSetLookup(varIndex, subIndicesAddress, pointsAddress, numPoints);
1660
1809
  }
1661
1810
  }
1662
- params.copyInputs((_d = this.inputsBuffer) == null ? void 0 : _d.getArrayView(), (numElements) => {
1811
+ let constantIndicesBuffer;
1812
+ let constantValuesBuffer;
1813
+ const constants = params.getConstants();
1814
+ if (constants !== void 0 && constants.length > 0) {
1815
+ let totalIndicesSize = 1;
1816
+ for (const constantDef of constants) {
1817
+ const numSubElements = ((_d = constantDef.varRef.varSpec.subscriptIndices) == null ? void 0 : _d.length) || 0;
1818
+ totalIndicesSize += 2 + numSubElements;
1819
+ }
1820
+ if (this.constantIndicesBuffer === void 0 || this.constantIndicesBuffer.numElements < totalIndicesSize) {
1821
+ (_e = this.constantIndicesBuffer) == null ? void 0 : _e.dispose();
1822
+ this.constantIndicesBuffer = createInt32WasmBuffer(this.wasmModule, totalIndicesSize);
1823
+ }
1824
+ const numConstants = constants.length;
1825
+ if (this.constantValuesBuffer === void 0 || this.constantValuesBuffer.numElements < numConstants) {
1826
+ (_f = this.constantValuesBuffer) == null ? void 0 : _f.dispose();
1827
+ this.constantValuesBuffer = createFloat64WasmBuffer(this.wasmModule, numConstants);
1828
+ }
1829
+ const indicesView = this.constantIndicesBuffer.getArrayView();
1830
+ const valuesView = this.constantValuesBuffer.getArrayView();
1831
+ let indicesOffset = 0;
1832
+ let valuesOffset = 0;
1833
+ indicesView[indicesOffset++] = numConstants;
1834
+ for (const constantDef of constants) {
1835
+ const varSpec = constantDef.varRef.varSpec;
1836
+ const numSubElements = ((_g = varSpec.subscriptIndices) == null ? void 0 : _g.length) || 0;
1837
+ indicesView[indicesOffset++] = varSpec.varIndex;
1838
+ indicesView[indicesOffset++] = numSubElements;
1839
+ if (numSubElements > 0) {
1840
+ for (let i = 0; i < numSubElements; i++) {
1841
+ indicesView[indicesOffset++] = varSpec.subscriptIndices[i];
1842
+ }
1843
+ }
1844
+ valuesView[valuesOffset++] = constantDef.value;
1845
+ }
1846
+ constantIndicesBuffer = this.constantIndicesBuffer;
1847
+ constantValuesBuffer = this.constantValuesBuffer;
1848
+ } else {
1849
+ constantIndicesBuffer = void 0;
1850
+ constantValuesBuffer = void 0;
1851
+ }
1852
+ params.copyInputs((_h = this.inputsBuffer) == null ? void 0 : _h.getArrayView(), (numElements) => {
1663
1853
  var _a2;
1664
1854
  (_a2 = this.inputsBuffer) == null ? void 0 : _a2.dispose();
1665
1855
  this.inputsBuffer = createFloat64WasmBuffer(this.wasmModule, numElements);
@@ -1667,7 +1857,7 @@ var WasmModel = class {
1667
1857
  });
1668
1858
  let outputIndicesBuffer;
1669
1859
  if (params.getOutputIndicesLength() > 0) {
1670
- params.copyOutputIndices((_e = this.outputIndicesBuffer) == null ? void 0 : _e.getArrayView(), (numElements) => {
1860
+ params.copyOutputIndices((_i = this.outputIndicesBuffer) == null ? void 0 : _i.getArrayView(), (numElements) => {
1671
1861
  var _a2;
1672
1862
  (_a2 = this.outputIndicesBuffer) == null ? void 0 : _a2.dispose();
1673
1863
  this.outputIndicesBuffer = createInt32WasmBuffer(this.wasmModule, numElements);
@@ -1679,14 +1869,19 @@ var WasmModel = class {
1679
1869
  }
1680
1870
  const outputsLengthInElements = params.getOutputsLength();
1681
1871
  if (this.outputsBuffer === void 0 || this.outputsBuffer.numElements < outputsLengthInElements) {
1682
- (_f = this.outputsBuffer) == null ? void 0 : _f.dispose();
1872
+ (_j = this.outputsBuffer) == null ? void 0 : _j.dispose();
1683
1873
  this.outputsBuffer = createFloat64WasmBuffer(this.wasmModule, outputsLengthInElements);
1684
1874
  }
1685
1875
  const t0 = perfNow();
1686
1876
  this.wasmRunModel(
1687
- ((_g = this.inputsBuffer) == null ? void 0 : _g.getAddress()) || 0,
1877
+ ((_k = this.inputsBuffer) == null ? void 0 : _k.getAddress()) || 0,
1878
+ // Always pass 0 (NULL) for input indices, since we assume that all input values are
1879
+ // provided and are in the same order as the input variables defined in the model spec
1880
+ 0,
1688
1881
  this.outputsBuffer.getAddress(),
1689
- (outputIndicesBuffer == null ? void 0 : outputIndicesBuffer.getAddress()) || 0
1882
+ (outputIndicesBuffer == null ? void 0 : outputIndicesBuffer.getAddress()) || 0,
1883
+ (constantValuesBuffer == null ? void 0 : constantValuesBuffer.getAddress()) || 0,
1884
+ (constantIndicesBuffer == null ? void 0 : constantIndicesBuffer.getAddress()) || 0
1690
1885
  );
1691
1886
  const elapsed = perfElapsed(t0);
1692
1887
  params.storeOutputs(this.outputsBuffer.getArrayView());
@@ -1694,13 +1889,17 @@ var WasmModel = class {
1694
1889
  }
1695
1890
  // from RunnableModel interface
1696
1891
  terminate() {
1697
- var _a, _b, _c;
1892
+ var _a, _b, _c, _d, _e;
1698
1893
  (_a = this.inputsBuffer) == null ? void 0 : _a.dispose();
1699
1894
  this.inputsBuffer = void 0;
1700
1895
  (_b = this.outputsBuffer) == null ? void 0 : _b.dispose();
1701
1896
  this.outputsBuffer = void 0;
1702
1897
  (_c = this.outputIndicesBuffer) == null ? void 0 : _c.dispose();
1703
1898
  this.outputIndicesBuffer = void 0;
1899
+ (_d = this.constantValuesBuffer) == null ? void 0 : _d.dispose();
1900
+ this.constantValuesBuffer = void 0;
1901
+ (_e = this.constantIndicesBuffer) == null ? void 0 : _e.dispose();
1902
+ this.constantIndicesBuffer = void 0;
1704
1903
  }
1705
1904
  };
1706
1905
  function initWasmModel(wasmModule) {
@@ -1716,6 +1915,7 @@ var MockWasmModule = class {
1716
1915
  this.mallocOffset = 8;
1717
1916
  this.allocs = /* @__PURE__ */ new Map();
1718
1917
  this.lookups = /* @__PURE__ */ new Map();
1918
+ this.constants = /* @__PURE__ */ new Map();
1719
1919
  this.initialTime = options.initialTime;
1720
1920
  this.finalTime = options.finalTime;
1721
1921
  this.outputVarIds = options.outputVarIds;
@@ -1755,11 +1955,35 @@ var MockWasmModule = class {
1755
1955
  this.lookups.set(varId, new JsModelLookup(numPoints, points));
1756
1956
  };
1757
1957
  case "runModelWithBuffers":
1758
- return (inputsAddress, outputsAddress, outputIndicesAddress) => {
1958
+ return (inputsAddress, _inputIndicesAddress, outputsAddress, outputIndicesAddress, constantValuesAddress, constantIndicesAddress) => {
1759
1959
  const inputs = this.getHeapView("float64", inputsAddress);
1760
1960
  const outputs = this.getHeapView("float64", outputsAddress);
1761
1961
  const outputIndices = this.getHeapView("int32", outputIndicesAddress);
1762
- this.onRunModel(inputs, outputs, this.lookups, outputIndices);
1962
+ this.constants.clear();
1963
+ if (constantValuesAddress !== 0 && constantIndicesAddress !== 0) {
1964
+ const constantValues = this.getHeapView("float64", constantValuesAddress);
1965
+ const constantIndices = this.getHeapView("int32", constantIndicesAddress);
1966
+ const numConstants = constantIndices[0];
1967
+ let indicesOffset = 1;
1968
+ let valuesOffset = 0;
1969
+ for (let i = 0; i < numConstants; i++) {
1970
+ const varIndex = constantIndices[indicesOffset++];
1971
+ const subCount = constantIndices[indicesOffset++];
1972
+ indicesOffset += subCount;
1973
+ const varId = this.varIdForSpec({ varIndex });
1974
+ if (varId) {
1975
+ this.constants.set(varId, constantValues[valuesOffset++]);
1976
+ }
1977
+ }
1978
+ }
1979
+ this.onRunModel(
1980
+ inputs,
1981
+ outputs,
1982
+ this.constants.size > 0 ? this.constants : void 0,
1983
+ this.lookups,
1984
+ outputIndices
1985
+ );
1986
+ this.constants.clear();
1763
1987
  };
1764
1988
  default:
1765
1989
  throw new Error(`Unhandled call to cwrap with function name '${fname}'`);
@@ -1837,7 +2061,7 @@ function createRunnerFromRunnableModel(model) {
1837
2061
  }
1838
2062
  return runModelSync(inputs, outputs, options);
1839
2063
  },
1840
- terminate: () => __async(this, null, function* () {
2064
+ terminate: () => __async(null, null, function* () {
1841
2065
  if (!terminated) {
1842
2066
  model.terminate();
1843
2067
  terminated = true;
@@ -1862,7 +2086,7 @@ var ModelScheduler = class {
1862
2086
  /** Whether a model run is in progress. */
1863
2087
  this.runInProgress = false;
1864
2088
  const afterSet = () => {
1865
- this.runWasmModelIfNeeded();
2089
+ this.runModelIfNeeded();
1866
2090
  };
1867
2091
  for (const userInput of userInputs) {
1868
2092
  userInput.callbacks.onSet = afterSet;
@@ -1873,24 +2097,24 @@ var ModelScheduler = class {
1873
2097
  }
1874
2098
  }
1875
2099
  /**
1876
- * Schedule a wasm model run (if not already pending). When the run is
2100
+ * Schedule a model run (if not already pending). When the run is
1877
2101
  * complete, save the outputs and call the `onOutputsChanged` callback.
1878
2102
  */
1879
- runWasmModelIfNeeded() {
2103
+ runModelIfNeeded() {
1880
2104
  this.runNeeded = true;
1881
2105
  if (this.runInProgress) {
1882
2106
  return;
1883
2107
  } else {
1884
2108
  this.runInProgress = true;
1885
2109
  setTimeout(() => {
1886
- this.runWasmModelNow();
2110
+ this.runModelNow();
1887
2111
  }, 0);
1888
2112
  }
1889
2113
  }
1890
2114
  /**
1891
- * Run the wasm model asynchronously using the current set of input values.
2115
+ * Run the model asynchronously using the current set of input values.
1892
2116
  */
1893
- runWasmModelNow() {
2117
+ runModelNow() {
1894
2118
  return __async(this, null, function* () {
1895
2119
  var _a;
1896
2120
  for (let i = 0; i < this.userInputs.length; i++) {
@@ -1905,7 +2129,7 @@ var ModelScheduler = class {
1905
2129
  if (this.runNeeded) {
1906
2130
  this.runNeeded = false;
1907
2131
  setTimeout(() => {
1908
- this.runWasmModelNow();
2132
+ this.runModelNow();
1909
2133
  }, 0);
1910
2134
  } else {
1911
2135
  this.runNeeded = false;
@@ -1927,23 +2151,214 @@ function createSimpleInputValue(varId) {
1927
2151
  };
1928
2152
  return { varId, get, set, reset, callbacks: {} };
1929
2153
  }
2154
+
2155
+ // src/model-scheduler/multi-context-model-scheduler.ts
2156
+ var MultiContextModelScheduler = class {
2157
+ /**
2158
+ * @param runner The model runner.
2159
+ * @param options Additional options for the scheduler.
2160
+ * @param options.initialOutputs An optional `Outputs` instance that will be reused
2161
+ * for the initial context. This is useful for saving memory when an `Outputs`
2162
+ * instance was already created for, e.g., a initial baseline/reference run.
2163
+ */
2164
+ constructor(runner, options) {
2165
+ this.runner = runner;
2166
+ /** The contexts that hold distinct sets of inputs and outputs. */
2167
+ this.contexts = [];
2168
+ /** Whether a model run has been scheduled. */
2169
+ this.runNeeded = false;
2170
+ /** Whether a model run is in progress. */
2171
+ this.runInProgress = false;
2172
+ this.initialOutputs = options == null ? void 0 : options.initialOutputs;
2173
+ }
2174
+ /**
2175
+ * Return true if the scheduler has started any model runs.
2176
+ */
2177
+ isStarted() {
2178
+ return this.initialOutputs === void 0;
2179
+ }
2180
+ /**
2181
+ * Add a new context that holds a distinct set of model inputs and outputs.
2182
+ * These inputs and outputs are kept separate from those in other contexts,
2183
+ * which allows an application to use the same underlying model to run with
2184
+ * multiple I/O contexts.
2185
+ *
2186
+ * Note that the contexts created before the first scheduled model run
2187
+ * will inherit the data from `initialOutputs` passed to the constructor,
2188
+ * but contexts created after that will initially have output values set
2189
+ * to zero.
2190
+ *
2191
+ * @param inputs The input values, in the same order as in the spec file passed to `sde`.
2192
+ * @param options Additional options for the context.
2193
+ * @param options.externalData Additional data that is external to the model outputs.
2194
+ * For example, this can contain data that was captured from an initial reference
2195
+ * run, or other static data that is displayed in graphs alongside the model
2196
+ * output data in graphs.
2197
+ */
2198
+ addContext(inputs, options) {
2199
+ let outputs;
2200
+ if (this.initialOutputs !== void 0) {
2201
+ if (this.contexts.length === 0) {
2202
+ outputs = this.initialOutputs;
2203
+ } else {
2204
+ outputs = this.runner.createOutputs();
2205
+ for (const varId of outputs.varIds) {
2206
+ const series0 = this.initialOutputs.getSeriesForVar(varId);
2207
+ const series1 = outputs.getSeriesForVar(varId);
2208
+ for (let i = 0; i < series0.points.length; i++) {
2209
+ series1.points[i].y = series0.points[i].y;
2210
+ }
2211
+ }
2212
+ }
2213
+ } else {
2214
+ outputs = this.runner.createOutputs();
2215
+ }
2216
+ const context = new ModelContextImpl(inputs, outputs, options == null ? void 0 : options.externalData);
2217
+ const afterSet = () => {
2218
+ context.runNeeded = true;
2219
+ this.runModelIfNeeded();
2220
+ };
2221
+ for (const input of inputs) {
2222
+ input.callbacks.onSet = afterSet;
2223
+ }
2224
+ this.contexts.push(context);
2225
+ return context;
2226
+ }
2227
+ /**
2228
+ * Remove the given context from the set of contexts managed by the scheduler.
2229
+ *
2230
+ * @param context The context to remove.
2231
+ */
2232
+ removeContext(context) {
2233
+ const index = this.contexts.findIndex((c) => c === context);
2234
+ if (index >= 0) {
2235
+ this.contexts.splice(index, 1);
2236
+ }
2237
+ }
2238
+ /**
2239
+ * Schedule a model run (if not already pending). When the run is
2240
+ * complete, save the outputs and call the `onOutputsChanged` callback.
2241
+ */
2242
+ runModelIfNeeded() {
2243
+ this.runNeeded = true;
2244
+ if (this.runInProgress) {
2245
+ return;
2246
+ } else {
2247
+ this.runInProgress = true;
2248
+ setTimeout(() => {
2249
+ this.runModelNow();
2250
+ }, 0);
2251
+ }
2252
+ }
2253
+ /**
2254
+ * Run the model asynchronously for all relevant contexts.
2255
+ */
2256
+ runModelNow() {
2257
+ return __async(this, null, function* () {
2258
+ this.initialOutputs = void 0;
2259
+ for (const context of this.contexts) {
2260
+ if (context.runNeeded) {
2261
+ context.runNeeded = false;
2262
+ yield this.runModelNowForContext(context);
2263
+ }
2264
+ }
2265
+ if (this.runNeeded) {
2266
+ this.runNeeded = false;
2267
+ setTimeout(() => {
2268
+ this.runModelNow();
2269
+ }, 0);
2270
+ } else {
2271
+ this.runNeeded = false;
2272
+ this.runInProgress = false;
2273
+ }
2274
+ });
2275
+ }
2276
+ /**
2277
+ * Run the model asynchronously using the current set of input values in the given context.
2278
+ *
2279
+ * @param context The context to use for the model run.
2280
+ */
2281
+ runModelNowForContext(context) {
2282
+ return __async(this, null, function* () {
2283
+ var _a;
2284
+ if (this.currentInputs === void 0) {
2285
+ this.currentInputs = Array(context.inputsArray.length);
2286
+ }
2287
+ for (let i = 0; i < context.inputsArray.length; i++) {
2288
+ this.currentInputs[i] = context.inputsArray[i].get();
2289
+ }
2290
+ try {
2291
+ yield this.runner.runModel(this.currentInputs, context.outputs);
2292
+ (_a = context.onOutputsChanged) == null ? void 0 : _a.call(context);
2293
+ } catch (e) {
2294
+ console.error("ERROR: The scheduler encountered an error when running the model:", e);
2295
+ }
2296
+ });
2297
+ }
2298
+ };
2299
+ var ModelContextImpl = class {
2300
+ /**
2301
+ * @hidden This is intended for use by `MultiContextModelScheduler` only.
2302
+ *
2303
+ * @param inputs The input values, in the same order as in the spec file passed to `sde`.
2304
+ * @param outputs The structure into which the model outputs will be stored.
2305
+ * @param externalData Additional data that is external to the model outputs. For example, this can contain
2306
+ * data that was captured from an initial reference run, or other static data that is displayed in graphs
2307
+ * alongside the model output data in graphs.
2308
+ */
2309
+ constructor(inputs, outputs, externalData) {
2310
+ this.externalData = externalData;
2311
+ /**
2312
+ * Whether a model run is needed for this context.
2313
+ * @hidden This is intended for use by `MultiContextModelScheduler` only.
2314
+ */
2315
+ this.runNeeded = false;
2316
+ this.inputsArray = Array.from(inputs);
2317
+ this.outputs = outputs;
2318
+ }
2319
+ /**
2320
+ * Return the series data for the given model output variable or external
2321
+ * dataset.
2322
+ *
2323
+ * @param varId The ID of the output variable associated with the data.
2324
+ * @param sourceName The external data source name (e.g. "Ref"), or
2325
+ * undefined to use the latest model output data from this context.
2326
+ */
2327
+ getSeriesForVar(varId, sourceName) {
2328
+ if (sourceName === void 0) {
2329
+ return this.outputs.getSeriesForVar(varId);
2330
+ } else {
2331
+ const dataForSource = this.externalData.get(sourceName);
2332
+ if (dataForSource !== void 0) {
2333
+ return dataForSource.get(varId);
2334
+ } else {
2335
+ return void 0;
2336
+ }
2337
+ }
2338
+ }
2339
+ };
1930
2340
  export {
1931
2341
  BufferedRunModelParams,
1932
2342
  MockJsModel,
1933
2343
  MockWasmModule,
1934
2344
  ModelListing,
1935
2345
  ModelScheduler,
2346
+ MultiContextModelScheduler,
1936
2347
  Outputs,
1937
2348
  ReferencedRunModelParams,
1938
2349
  Series,
2350
+ createConstantDef,
1939
2351
  createInputValue,
1940
2352
  createLookupDef,
1941
2353
  createRunnableModel,
1942
2354
  createSynchronousModelRunner,
2355
+ decodeConstants,
1943
2356
  decodeLookups,
2357
+ encodeConstants,
1944
2358
  encodeLookups,
1945
2359
  encodeVarIndices,
1946
2360
  execJsModel,
2361
+ getEncodedConstantBufferLengths,
1947
2362
  getEncodedLookupBufferLengths,
1948
2363
  getEncodedVarIndicesLength,
1949
2364
  getJsModelFunctions,