@sdeverywhere/runtime 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +306 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +177 -16
- package/dist/index.d.ts +177 -16
- package/dist/index.js +305 -56
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -207,7 +207,7 @@ function encodeVarIndices(varSpecs, indicesArray) {
|
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
209
|
function getEncodedLookupBufferLengths(lookupDefs) {
|
|
210
|
-
var _a;
|
|
210
|
+
var _a, _b;
|
|
211
211
|
let lookupIndicesLength = 1;
|
|
212
212
|
let lookupsLength = 0;
|
|
213
213
|
for (const lookupDef of lookupDefs) {
|
|
@@ -219,7 +219,7 @@ function getEncodedLookupBufferLengths(lookupDefs) {
|
|
|
219
219
|
const subCount = ((_a = varSpec.subscriptIndices) == null ? void 0 : _a.length) || 0;
|
|
220
220
|
lookupIndicesLength += subCount;
|
|
221
221
|
lookupIndicesLength += 2;
|
|
222
|
-
lookupsLength += lookupDef.points.length;
|
|
222
|
+
lookupsLength += ((_b = lookupDef.points) == null ? void 0 : _b.length) || 0;
|
|
223
223
|
}
|
|
224
224
|
return {
|
|
225
225
|
lookupIndicesLength,
|
|
@@ -239,10 +239,15 @@ function encodeLookups(lookupDefs, lookupIndicesArray, lookupsArray) {
|
|
|
239
239
|
for (let i = 0; i < subCount; i++) {
|
|
240
240
|
lookupIndicesArray[li++] = subs[i];
|
|
241
241
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
242
|
+
if (lookupDef.points !== void 0) {
|
|
243
|
+
lookupIndicesArray[li++] = lookupDataOffset;
|
|
244
|
+
lookupIndicesArray[li++] = lookupDef.points.length;
|
|
245
|
+
lookupsArray == null ? void 0 : lookupsArray.set(lookupDef.points, lookupDataOffset);
|
|
246
|
+
lookupDataOffset += lookupDef.points.length;
|
|
247
|
+
} else {
|
|
248
|
+
lookupIndicesArray[li++] = -1;
|
|
249
|
+
lookupIndicesArray[li++] = 0;
|
|
250
|
+
}
|
|
246
251
|
}
|
|
247
252
|
}
|
|
248
253
|
function decodeLookups(lookupIndicesArray, lookupsArray) {
|
|
@@ -263,10 +268,14 @@ function decodeLookups(lookupIndicesArray, lookupsArray) {
|
|
|
263
268
|
subscriptIndices
|
|
264
269
|
};
|
|
265
270
|
let points;
|
|
266
|
-
if (
|
|
267
|
-
|
|
271
|
+
if (lookupDataOffset >= 0) {
|
|
272
|
+
if (lookupsArray) {
|
|
273
|
+
points = lookupsArray.slice(lookupDataOffset, lookupDataOffset + lookupDataLength);
|
|
274
|
+
} else {
|
|
275
|
+
points = new Float64Array(0);
|
|
276
|
+
}
|
|
268
277
|
} else {
|
|
269
|
-
points =
|
|
278
|
+
points = void 0;
|
|
270
279
|
}
|
|
271
280
|
lookupDefs.push({
|
|
272
281
|
varRef: {
|
|
@@ -280,11 +289,14 @@ function decodeLookups(lookupIndicesArray, lookupsArray) {
|
|
|
280
289
|
|
|
281
290
|
// src/_shared/lookup-def.ts
|
|
282
291
|
function createLookupDef(varRef, points) {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
292
|
+
let flatPoints;
|
|
293
|
+
if (points) {
|
|
294
|
+
flatPoints = new Float64Array(points.length * 2);
|
|
295
|
+
let i = 0;
|
|
296
|
+
for (const p of points) {
|
|
297
|
+
flatPoints[i++] = p.x;
|
|
298
|
+
flatPoints[i++] = p.y;
|
|
299
|
+
}
|
|
288
300
|
}
|
|
289
301
|
return {
|
|
290
302
|
varRef,
|
|
@@ -840,18 +852,59 @@ var _NA_ = -Number.MAX_VALUE;
|
|
|
840
852
|
// src/js-model/js-model-lookup.ts
|
|
841
853
|
var JsModelLookup = class {
|
|
842
854
|
/**
|
|
843
|
-
* @param
|
|
855
|
+
* @param size The number of (x,y) pairs in the lookup.
|
|
844
856
|
* @param data The lookup data, as (x,y) pairs. The length of the array must be
|
|
845
857
|
* >= 2*n. Note that the data will be stored by reference, so if there is a chance
|
|
846
858
|
* that the array will be reused or modified by other code, be sure to pass in a
|
|
847
859
|
* copy of the array.
|
|
848
860
|
*/
|
|
849
|
-
constructor(
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
861
|
+
constructor(size, data) {
|
|
862
|
+
if (data && data.length < size * 2) {
|
|
863
|
+
throw new Error(`Lookup data array length must be >= 2*size (length=${data.length} size=${size}`);
|
|
864
|
+
}
|
|
865
|
+
this.originalData = data;
|
|
866
|
+
this.originalSize = size;
|
|
867
|
+
this.dynamicData = void 0;
|
|
868
|
+
this.dynamicSize = 0;
|
|
869
|
+
this.activeData = this.originalData;
|
|
870
|
+
this.activeSize = this.originalSize;
|
|
871
|
+
this.lastInput = Number.MAX_VALUE;
|
|
872
|
+
this.lastHitIndex = 0;
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Set new data for this lookup instance, or restore the original data.
|
|
876
|
+
*
|
|
877
|
+
* If `data` is undefined, the original data that was supplied to the constructor will
|
|
878
|
+
* be restored as the "active" data. Otherwise, `data` will be copied to an internal
|
|
879
|
+
* data buffer, which will be the "active" data. If `size` is greater than the size
|
|
880
|
+
* passed to previous calls, the internal data buffer will be grown as needed.
|
|
881
|
+
*
|
|
882
|
+
* @param size The number of (x,y) pairs in the lookup.
|
|
883
|
+
* @param data The lookup data, as (x,y) pairs. The length of the array must be
|
|
884
|
+
* >= 2*n. Note that the data will be copied into an internal data buffer, so it
|
|
885
|
+
* is not necessary to defensively copy data before calling this method.
|
|
886
|
+
*/
|
|
887
|
+
setData(size, data) {
|
|
888
|
+
if (data) {
|
|
889
|
+
if (data.length < size * 2) {
|
|
890
|
+
throw new Error(`Lookup data array length must be >= 2*size (length=${data.length} size=${size}`);
|
|
891
|
+
}
|
|
892
|
+
const dataLengthInElems = size * 2;
|
|
893
|
+
if (this.dynamicData === void 0 || dataLengthInElems > this.dynamicData.length) {
|
|
894
|
+
this.dynamicData = new Float64Array(dataLengthInElems);
|
|
895
|
+
}
|
|
896
|
+
this.dynamicSize = size;
|
|
897
|
+
if (size > 0) {
|
|
898
|
+
const subarray = data.subarray(0, dataLengthInElems);
|
|
899
|
+
this.dynamicData.set(subarray);
|
|
900
|
+
}
|
|
901
|
+
this.activeData = this.dynamicData;
|
|
902
|
+
this.activeSize = this.dynamicSize;
|
|
903
|
+
} else {
|
|
904
|
+
this.activeData = this.originalData;
|
|
905
|
+
this.activeSize = this.originalSize;
|
|
854
906
|
}
|
|
907
|
+
this.invertedData = void 0;
|
|
855
908
|
this.lastInput = Number.MAX_VALUE;
|
|
856
909
|
this.lastHitIndex = 0;
|
|
857
910
|
}
|
|
@@ -860,8 +913,8 @@ var JsModelLookup = class {
|
|
|
860
913
|
}
|
|
861
914
|
getValueForY(y) {
|
|
862
915
|
if (this.invertedData === void 0) {
|
|
863
|
-
const numValues = this.
|
|
864
|
-
const normalData = this.
|
|
916
|
+
const numValues = this.activeSize * 2;
|
|
917
|
+
const normalData = this.activeData;
|
|
865
918
|
const invertedData = Array(numValues);
|
|
866
919
|
for (let i = 0; i < numValues; i += 2) {
|
|
867
920
|
invertedData[i] = normalData[i + 1];
|
|
@@ -876,11 +929,11 @@ var JsModelLookup = class {
|
|
|
876
929
|
* NOTE: The x values are assumed to be monotonically increasing.
|
|
877
930
|
*/
|
|
878
931
|
getValue(input, useInvertedData, mode) {
|
|
879
|
-
if (this.
|
|
932
|
+
if (this.activeSize === 0) {
|
|
880
933
|
return _NA_;
|
|
881
934
|
}
|
|
882
|
-
const data = useInvertedData ? this.invertedData : this.
|
|
883
|
-
const max = this.
|
|
935
|
+
const data = useInvertedData ? this.invertedData : this.activeData;
|
|
936
|
+
const max = this.activeSize * 2;
|
|
884
937
|
const useCachedValues = !useInvertedData;
|
|
885
938
|
let startIndex;
|
|
886
939
|
if (useCachedValues && input >= this.lastInput) {
|
|
@@ -939,10 +992,10 @@ var JsModelLookup = class {
|
|
|
939
992
|
* no points) or if the provided time is earlier than the first data point.
|
|
940
993
|
*/
|
|
941
994
|
getValueForGameTime(time, defaultValue) {
|
|
942
|
-
if (this.
|
|
995
|
+
if (this.activeSize <= 0) {
|
|
943
996
|
return defaultValue;
|
|
944
997
|
}
|
|
945
|
-
const x0 = this.
|
|
998
|
+
const x0 = this.activeData[0];
|
|
946
999
|
if (time < x0) {
|
|
947
1000
|
return defaultValue;
|
|
948
1001
|
}
|
|
@@ -957,33 +1010,34 @@ var JsModelLookup = class {
|
|
|
957
1010
|
* lookup behavior, so we implement it as a separate method here.
|
|
958
1011
|
*/
|
|
959
1012
|
getValueBetweenTimes(input, mode) {
|
|
960
|
-
if (this.
|
|
1013
|
+
if (this.activeSize === 0) {
|
|
961
1014
|
return _NA_;
|
|
962
1015
|
}
|
|
963
|
-
const
|
|
1016
|
+
const data = this.activeData;
|
|
1017
|
+
const max = this.activeSize * 2;
|
|
964
1018
|
switch (mode) {
|
|
965
1019
|
case "forward": {
|
|
966
1020
|
input = Math.floor(input);
|
|
967
1021
|
for (let xi = 0; xi < max; xi += 2) {
|
|
968
|
-
const x =
|
|
1022
|
+
const x = data[xi];
|
|
969
1023
|
if (x >= input) {
|
|
970
|
-
return
|
|
1024
|
+
return data[xi + 1];
|
|
971
1025
|
}
|
|
972
1026
|
}
|
|
973
|
-
return
|
|
1027
|
+
return data[max - 1];
|
|
974
1028
|
}
|
|
975
1029
|
case "backward": {
|
|
976
1030
|
input = Math.floor(input);
|
|
977
1031
|
for (let xi = 2; xi < max; xi += 2) {
|
|
978
|
-
const x =
|
|
1032
|
+
const x = data[xi];
|
|
979
1033
|
if (x >= input) {
|
|
980
|
-
return
|
|
1034
|
+
return data[xi - 1];
|
|
981
1035
|
}
|
|
982
1036
|
}
|
|
983
1037
|
if (max >= 4) {
|
|
984
|
-
return
|
|
1038
|
+
return data[max - 3];
|
|
985
1039
|
} else {
|
|
986
|
-
return
|
|
1040
|
+
return data[1];
|
|
987
1041
|
}
|
|
988
1042
|
}
|
|
989
1043
|
case "interpolate":
|
|
@@ -995,17 +1049,17 @@ var JsModelLookup = class {
|
|
|
995
1049
|
throw new Error(msg);
|
|
996
1050
|
}
|
|
997
1051
|
for (let xi = 2; xi < max; xi += 2) {
|
|
998
|
-
const x =
|
|
1052
|
+
const x = data[xi];
|
|
999
1053
|
if (x >= input) {
|
|
1000
|
-
const last_x =
|
|
1001
|
-
const last_y =
|
|
1002
|
-
const y =
|
|
1054
|
+
const last_x = data[xi - 2];
|
|
1055
|
+
const last_y = data[xi - 1];
|
|
1056
|
+
const y = data[xi + 1];
|
|
1003
1057
|
const dx = x - last_x;
|
|
1004
1058
|
const dy = y - last_y;
|
|
1005
1059
|
return last_y + dy / dx * (input - last_x);
|
|
1006
1060
|
}
|
|
1007
1061
|
}
|
|
1008
|
-
return
|
|
1062
|
+
return data[max - 1];
|
|
1009
1063
|
}
|
|
1010
1064
|
}
|
|
1011
1065
|
}
|
|
@@ -1456,7 +1510,8 @@ var MockJsModel = class {
|
|
|
1456
1510
|
if (varId === void 0) {
|
|
1457
1511
|
throw new Error(`No lookup variable found for spec ${varSpec}`);
|
|
1458
1512
|
}
|
|
1459
|
-
|
|
1513
|
+
const numPoints = points ? points.length / 2 : 0;
|
|
1514
|
+
this.lookups.set(varId, new JsModelLookup(numPoints, points));
|
|
1460
1515
|
}
|
|
1461
1516
|
// from JsModel interface
|
|
1462
1517
|
storeOutputs(storeValue) {
|
|
@@ -1585,14 +1640,21 @@ var WasmModel = class {
|
|
|
1585
1640
|
} else {
|
|
1586
1641
|
subIndicesAddress = 0;
|
|
1587
1642
|
}
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1643
|
+
let pointsAddress;
|
|
1644
|
+
let numPoints;
|
|
1645
|
+
if (lookupDef.points) {
|
|
1646
|
+
const numLookupElements = lookupDef.points.length;
|
|
1647
|
+
if (this.lookupDataBuffer === void 0 || this.lookupDataBuffer.numElements < numLookupElements) {
|
|
1648
|
+
(_c = this.lookupDataBuffer) == null ? void 0 : _c.dispose();
|
|
1649
|
+
this.lookupDataBuffer = createFloat64WasmBuffer(this.wasmModule, numLookupElements);
|
|
1650
|
+
}
|
|
1651
|
+
this.lookupDataBuffer.getArrayView().set(lookupDef.points);
|
|
1652
|
+
pointsAddress = this.lookupDataBuffer.getAddress();
|
|
1653
|
+
numPoints = numLookupElements / 2;
|
|
1654
|
+
} else {
|
|
1655
|
+
pointsAddress = 0;
|
|
1656
|
+
numPoints = 0;
|
|
1592
1657
|
}
|
|
1593
|
-
this.lookupDataBuffer.getArrayView().set(lookupDef.points);
|
|
1594
|
-
const pointsAddress = this.lookupDataBuffer.getAddress();
|
|
1595
|
-
const numPoints = numLookupElements / 2;
|
|
1596
1658
|
const varIndex = varSpec.varIndex;
|
|
1597
1659
|
this.wasmSetLookup(varIndex, subIndicesAddress, pointsAddress, numPoints);
|
|
1598
1660
|
}
|
|
@@ -1800,7 +1862,7 @@ var ModelScheduler = class {
|
|
|
1800
1862
|
/** Whether a model run is in progress. */
|
|
1801
1863
|
this.runInProgress = false;
|
|
1802
1864
|
const afterSet = () => {
|
|
1803
|
-
this.
|
|
1865
|
+
this.runModelIfNeeded();
|
|
1804
1866
|
};
|
|
1805
1867
|
for (const userInput of userInputs) {
|
|
1806
1868
|
userInput.callbacks.onSet = afterSet;
|
|
@@ -1811,24 +1873,24 @@ var ModelScheduler = class {
|
|
|
1811
1873
|
}
|
|
1812
1874
|
}
|
|
1813
1875
|
/**
|
|
1814
|
-
* Schedule a
|
|
1876
|
+
* Schedule a model run (if not already pending). When the run is
|
|
1815
1877
|
* complete, save the outputs and call the `onOutputsChanged` callback.
|
|
1816
1878
|
*/
|
|
1817
|
-
|
|
1879
|
+
runModelIfNeeded() {
|
|
1818
1880
|
this.runNeeded = true;
|
|
1819
1881
|
if (this.runInProgress) {
|
|
1820
1882
|
return;
|
|
1821
1883
|
} else {
|
|
1822
1884
|
this.runInProgress = true;
|
|
1823
1885
|
setTimeout(() => {
|
|
1824
|
-
this.
|
|
1886
|
+
this.runModelNow();
|
|
1825
1887
|
}, 0);
|
|
1826
1888
|
}
|
|
1827
1889
|
}
|
|
1828
1890
|
/**
|
|
1829
|
-
* Run the
|
|
1891
|
+
* Run the model asynchronously using the current set of input values.
|
|
1830
1892
|
*/
|
|
1831
|
-
|
|
1893
|
+
runModelNow() {
|
|
1832
1894
|
return __async(this, null, function* () {
|
|
1833
1895
|
var _a;
|
|
1834
1896
|
for (let i = 0; i < this.userInputs.length; i++) {
|
|
@@ -1843,7 +1905,7 @@ var ModelScheduler = class {
|
|
|
1843
1905
|
if (this.runNeeded) {
|
|
1844
1906
|
this.runNeeded = false;
|
|
1845
1907
|
setTimeout(() => {
|
|
1846
|
-
this.
|
|
1908
|
+
this.runModelNow();
|
|
1847
1909
|
}, 0);
|
|
1848
1910
|
} else {
|
|
1849
1911
|
this.runNeeded = false;
|
|
@@ -1865,12 +1927,199 @@ function createSimpleInputValue(varId) {
|
|
|
1865
1927
|
};
|
|
1866
1928
|
return { varId, get, set, reset, callbacks: {} };
|
|
1867
1929
|
}
|
|
1930
|
+
|
|
1931
|
+
// src/model-scheduler/multi-context-model-scheduler.ts
|
|
1932
|
+
var MultiContextModelScheduler = class {
|
|
1933
|
+
/**
|
|
1934
|
+
* @param runner The model runner.
|
|
1935
|
+
* @param options Additional options for the scheduler.
|
|
1936
|
+
* @param options.initialOutputs An optional `Outputs` instance that will be reused
|
|
1937
|
+
* for the initial context. This is useful for saving memory when an `Outputs`
|
|
1938
|
+
* instance was already created for, e.g., a initial baseline/reference run.
|
|
1939
|
+
*/
|
|
1940
|
+
constructor(runner, options) {
|
|
1941
|
+
this.runner = runner;
|
|
1942
|
+
/** The contexts that hold distinct sets of inputs and outputs. */
|
|
1943
|
+
this.contexts = [];
|
|
1944
|
+
/** Whether a model run has been scheduled. */
|
|
1945
|
+
this.runNeeded = false;
|
|
1946
|
+
/** Whether a model run is in progress. */
|
|
1947
|
+
this.runInProgress = false;
|
|
1948
|
+
this.initialOutputs = options == null ? void 0 : options.initialOutputs;
|
|
1949
|
+
}
|
|
1950
|
+
/**
|
|
1951
|
+
* Return true if the scheduler has started any model runs.
|
|
1952
|
+
*/
|
|
1953
|
+
isStarted() {
|
|
1954
|
+
return this.initialOutputs === void 0;
|
|
1955
|
+
}
|
|
1956
|
+
/**
|
|
1957
|
+
* Add a new context that holds a distinct set of model inputs and outputs.
|
|
1958
|
+
* These inputs and outputs are kept separate from those in other contexts,
|
|
1959
|
+
* which allows an application to use the same underlying model to run with
|
|
1960
|
+
* multiple I/O contexts.
|
|
1961
|
+
*
|
|
1962
|
+
* Note that the contexts created before the first scheduled model run
|
|
1963
|
+
* will inherit the data from `initialOutputs` passed to the constructor,
|
|
1964
|
+
* but contexts created after that will initially have output values set
|
|
1965
|
+
* to zero.
|
|
1966
|
+
*
|
|
1967
|
+
* @param inputs The input values, in the same order as in the spec file passed to `sde`.
|
|
1968
|
+
* @param options Additional options for the context.
|
|
1969
|
+
* @param options.externalData Additional data that is external to the model outputs.
|
|
1970
|
+
* For example, this can contain data that was captured from an initial reference
|
|
1971
|
+
* run, or other static data that is displayed in graphs alongside the model
|
|
1972
|
+
* output data in graphs.
|
|
1973
|
+
*/
|
|
1974
|
+
addContext(inputs, options) {
|
|
1975
|
+
let outputs;
|
|
1976
|
+
if (this.initialOutputs !== void 0) {
|
|
1977
|
+
if (this.contexts.length === 0) {
|
|
1978
|
+
outputs = this.initialOutputs;
|
|
1979
|
+
} else {
|
|
1980
|
+
outputs = this.runner.createOutputs();
|
|
1981
|
+
for (const varId of outputs.varIds) {
|
|
1982
|
+
const series0 = this.initialOutputs.getSeriesForVar(varId);
|
|
1983
|
+
const series1 = outputs.getSeriesForVar(varId);
|
|
1984
|
+
for (let i = 0; i < series0.points.length; i++) {
|
|
1985
|
+
series1.points[i].y = series0.points[i].y;
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
} else {
|
|
1990
|
+
outputs = this.runner.createOutputs();
|
|
1991
|
+
}
|
|
1992
|
+
const context = new ModelContextImpl(inputs, outputs, options == null ? void 0 : options.externalData);
|
|
1993
|
+
const afterSet = () => {
|
|
1994
|
+
context.runNeeded = true;
|
|
1995
|
+
this.runModelIfNeeded();
|
|
1996
|
+
};
|
|
1997
|
+
for (const input of inputs) {
|
|
1998
|
+
input.callbacks.onSet = afterSet;
|
|
1999
|
+
}
|
|
2000
|
+
this.contexts.push(context);
|
|
2001
|
+
return context;
|
|
2002
|
+
}
|
|
2003
|
+
/**
|
|
2004
|
+
* Remove the given context from the set of contexts managed by the scheduler.
|
|
2005
|
+
*
|
|
2006
|
+
* @param context The context to remove.
|
|
2007
|
+
*/
|
|
2008
|
+
removeContext(context) {
|
|
2009
|
+
const index = this.contexts.findIndex((c) => c === context);
|
|
2010
|
+
if (index >= 0) {
|
|
2011
|
+
this.contexts.splice(index, 1);
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
/**
|
|
2015
|
+
* Schedule a model run (if not already pending). When the run is
|
|
2016
|
+
* complete, save the outputs and call the `onOutputsChanged` callback.
|
|
2017
|
+
*/
|
|
2018
|
+
runModelIfNeeded() {
|
|
2019
|
+
this.runNeeded = true;
|
|
2020
|
+
if (this.runInProgress) {
|
|
2021
|
+
return;
|
|
2022
|
+
} else {
|
|
2023
|
+
this.runInProgress = true;
|
|
2024
|
+
setTimeout(() => {
|
|
2025
|
+
this.runModelNow();
|
|
2026
|
+
}, 0);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
/**
|
|
2030
|
+
* Run the model asynchronously for all relevant contexts.
|
|
2031
|
+
*/
|
|
2032
|
+
runModelNow() {
|
|
2033
|
+
return __async(this, null, function* () {
|
|
2034
|
+
this.initialOutputs = void 0;
|
|
2035
|
+
for (const context of this.contexts) {
|
|
2036
|
+
if (context.runNeeded) {
|
|
2037
|
+
context.runNeeded = false;
|
|
2038
|
+
yield this.runModelNowForContext(context);
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
if (this.runNeeded) {
|
|
2042
|
+
this.runNeeded = false;
|
|
2043
|
+
setTimeout(() => {
|
|
2044
|
+
this.runModelNow();
|
|
2045
|
+
}, 0);
|
|
2046
|
+
} else {
|
|
2047
|
+
this.runNeeded = false;
|
|
2048
|
+
this.runInProgress = false;
|
|
2049
|
+
}
|
|
2050
|
+
});
|
|
2051
|
+
}
|
|
2052
|
+
/**
|
|
2053
|
+
* Run the model asynchronously using the current set of input values in the given context.
|
|
2054
|
+
*
|
|
2055
|
+
* @param context The context to use for the model run.
|
|
2056
|
+
*/
|
|
2057
|
+
runModelNowForContext(context) {
|
|
2058
|
+
return __async(this, null, function* () {
|
|
2059
|
+
var _a;
|
|
2060
|
+
if (this.currentInputs === void 0) {
|
|
2061
|
+
this.currentInputs = Array(context.inputsArray.length);
|
|
2062
|
+
}
|
|
2063
|
+
for (let i = 0; i < context.inputsArray.length; i++) {
|
|
2064
|
+
this.currentInputs[i] = context.inputsArray[i].get();
|
|
2065
|
+
}
|
|
2066
|
+
try {
|
|
2067
|
+
yield this.runner.runModel(this.currentInputs, context.outputs);
|
|
2068
|
+
(_a = context.onOutputsChanged) == null ? void 0 : _a.call(context);
|
|
2069
|
+
} catch (e) {
|
|
2070
|
+
console.error("ERROR: The scheduler encountered an error when running the model:", e);
|
|
2071
|
+
}
|
|
2072
|
+
});
|
|
2073
|
+
}
|
|
2074
|
+
};
|
|
2075
|
+
var ModelContextImpl = class {
|
|
2076
|
+
/**
|
|
2077
|
+
* @hidden This is intended for use by `MultiContextModelScheduler` only.
|
|
2078
|
+
*
|
|
2079
|
+
* @param inputs The input values, in the same order as in the spec file passed to `sde`.
|
|
2080
|
+
* @param outputs The structure into which the model outputs will be stored.
|
|
2081
|
+
* @param externalData Additional data that is external to the model outputs. For example, this can contain
|
|
2082
|
+
* data that was captured from an initial reference run, or other static data that is displayed in graphs
|
|
2083
|
+
* alongside the model output data in graphs.
|
|
2084
|
+
*/
|
|
2085
|
+
constructor(inputs, outputs, externalData) {
|
|
2086
|
+
this.externalData = externalData;
|
|
2087
|
+
/**
|
|
2088
|
+
* Whether a model run is needed for this context.
|
|
2089
|
+
* @hidden This is intended for use by `MultiContextModelScheduler` only.
|
|
2090
|
+
*/
|
|
2091
|
+
this.runNeeded = false;
|
|
2092
|
+
this.inputsArray = Array.from(inputs);
|
|
2093
|
+
this.outputs = outputs;
|
|
2094
|
+
}
|
|
2095
|
+
/**
|
|
2096
|
+
* Return the series data for the given model output variable or external
|
|
2097
|
+
* dataset.
|
|
2098
|
+
*
|
|
2099
|
+
* @param varId The ID of the output variable associated with the data.
|
|
2100
|
+
* @param sourceName The external data source name (e.g. "Ref"), or
|
|
2101
|
+
* undefined to use the latest model output data from this context.
|
|
2102
|
+
*/
|
|
2103
|
+
getSeriesForVar(varId, sourceName) {
|
|
2104
|
+
if (sourceName === void 0) {
|
|
2105
|
+
return this.outputs.getSeriesForVar(varId);
|
|
2106
|
+
} else {
|
|
2107
|
+
const dataForSource = this.externalData.get(sourceName);
|
|
2108
|
+
if (dataForSource !== void 0) {
|
|
2109
|
+
return dataForSource.get(varId);
|
|
2110
|
+
} else {
|
|
2111
|
+
return void 0;
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
};
|
|
1868
2116
|
export {
|
|
1869
2117
|
BufferedRunModelParams,
|
|
1870
2118
|
MockJsModel,
|
|
1871
2119
|
MockWasmModule,
|
|
1872
2120
|
ModelListing,
|
|
1873
2121
|
ModelScheduler,
|
|
2122
|
+
MultiContextModelScheduler,
|
|
1874
2123
|
Outputs,
|
|
1875
2124
|
ReferencedRunModelParams,
|
|
1876
2125
|
Series,
|