@sdeverywhere/runtime 0.2.6 → 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/dist/index.d.cts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { Result } from 'neverthrow';
2
2
 
3
+ /** The name of a data source for external/static datasets, e.g., 'Ref', 'Constants'. */
4
+ type SourceName = string;
3
5
  /** A variable name, as used in the modeling tool. */
4
6
  type VarName = string;
5
7
  /** A variable identifier, as used in model code generated by SDEverywhere. */
@@ -86,6 +88,10 @@ declare function createInputValue(varId: InputVarId, defaultValue: number, initi
86
88
 
87
89
  /** Indicates the type of error encountered when parsing an outputs buffer. */
88
90
  type ParseError = 'invalid-point-count';
91
+ /** Type alias for a map that holds a `Series` instance for each output (or static) variable ID. */
92
+ type SeriesMap = Map<OutputVarId, Series>;
93
+ /** Type alias for a map that holds data for a given source name. */
94
+ type DataMap = Map<SourceName, SeriesMap>;
89
95
  /**
90
96
  * A time series of data points for an output variable.
91
97
  */
@@ -908,7 +914,7 @@ declare class MockWasmModule implements WasmModule {
908
914
  }
909
915
 
910
916
  /**
911
- * Abstraction that allows for running the wasm model on the JS thread
917
+ * Abstraction that allows for running a generated model on the JS thread
912
918
  * or asynchronously (e.g. in a Web Worker), depending on the implementation.
913
919
  */
914
920
  interface ModelRunner {
@@ -965,7 +971,7 @@ declare function createRunnableModel(generatedModel: GeneratedModel): RunnableMo
965
971
  declare function createSynchronousModelRunner(generatedModel: GeneratedModel): ModelRunner;
966
972
 
967
973
  /**
968
- * A high-level interface that schedules running of the underlying `WasmModel`.
974
+ * A high-level interface that schedules the underlying `ModelRunner`.
969
975
  *
970
976
  * When one or more input values are changed, this class will schedule a model
971
977
  * run to be completed as soon as possible. When the model run has completed,
@@ -994,14 +1000,127 @@ declare class ModelScheduler {
994
1000
  */
995
1001
  constructor(runner: ModelRunner, userInputs: InputValue[], outputs: Outputs);
996
1002
  /**
997
- * Schedule a wasm model run (if not already pending). When the run is
1003
+ * Schedule a model run (if not already pending). When the run is
998
1004
  * complete, save the outputs and call the `onOutputsChanged` callback.
999
1005
  */
1000
- private runWasmModelIfNeeded;
1006
+ private runModelIfNeeded;
1001
1007
  /**
1002
- * Run the wasm model asynchronously using the current set of input values.
1008
+ * Run the model asynchronously using the current set of input values.
1003
1009
  */
1004
- private runWasmModelNow;
1010
+ private runModelNow;
1011
+ }
1012
+
1013
+ /**
1014
+ * Defines a context that holds a distinct set of model inputs and outputs.
1015
+ * These inputs and outputs are kept separate from those in other contexts,
1016
+ * which allows an application to use the same underlying model instance
1017
+ * with multiple sets of inputs and outputs.
1018
+ */
1019
+ interface ModelContext {
1020
+ /**
1021
+ * Called when the outputs have been updated after a model run.
1022
+ */
1023
+ onOutputsChanged?: () => void;
1024
+ /**
1025
+ * Return the series data for the given model output variable or external
1026
+ * dataset.
1027
+ *
1028
+ * @param varId The ID of the output variable associated with the data.
1029
+ * @param sourceName The external data source name (e.g. "Ref"), or
1030
+ * undefined to use the latest model output data from this context.
1031
+ */
1032
+ getSeriesForVar(varId: OutputVarId, sourceName?: SourceName): Series | undefined;
1033
+ }
1034
+ /**
1035
+ * A high-level interface that schedules running of the underlying `ModelRunner`.
1036
+ *
1037
+ * This class is similar to the (single context) `ModelScheduler` class, except
1038
+ * this one supports multiple contexts, each with its own distinct set of
1039
+ * inputs and outputs. This is useful for running the same underlying model
1040
+ * instance with different sets of inputs and outputs. For example, you can
1041
+ * use this to show the outputs for multiple scenarios in a single graph, or
1042
+ * multiple scenarios across different graphs.
1043
+ *
1044
+ * When input values are changed in one or more contexts, this class will schedule
1045
+ * a model run for each changed context to be completed as soon as possible.
1046
+ * When the model run has completed, the context's `onOutputsChanged` function
1047
+ * is called to notify that new output data is available for that context.
1048
+ *
1049
+ * The `ModelRunner` is pluggable to allow for running the model synchronously
1050
+ * (on the main JavaScript thread) or asynchronously (in a Web Worker or Node.js
1051
+ * worker thread).
1052
+ */
1053
+ declare class MultiContextModelScheduler {
1054
+ private readonly runner;
1055
+ /**
1056
+ * An optional `Outputs` instance that will be reused for the initial context. This will
1057
+ * be set to undefined after it is used for the first context.
1058
+ */
1059
+ private initialOutputs?;
1060
+ /** The second array that holds a stable copy of the user inputs. */
1061
+ private currentInputs;
1062
+ /** The contexts that hold distinct sets of inputs and outputs. */
1063
+ private readonly contexts;
1064
+ /** Whether a model run has been scheduled. */
1065
+ private runNeeded;
1066
+ /** Whether a model run is in progress. */
1067
+ private runInProgress;
1068
+ /**
1069
+ * @param runner The model runner.
1070
+ * @param options Additional options for the scheduler.
1071
+ * @param options.initialOutputs An optional `Outputs` instance that will be reused
1072
+ * for the initial context. This is useful for saving memory when an `Outputs`
1073
+ * instance was already created for, e.g., a initial baseline/reference run.
1074
+ */
1075
+ constructor(runner: ModelRunner, options?: {
1076
+ initialOutputs?: Outputs;
1077
+ });
1078
+ /**
1079
+ * Return true if the scheduler has started any model runs.
1080
+ */
1081
+ isStarted(): boolean;
1082
+ /**
1083
+ * Add a new context that holds a distinct set of model inputs and outputs.
1084
+ * These inputs and outputs are kept separate from those in other contexts,
1085
+ * which allows an application to use the same underlying model to run with
1086
+ * multiple I/O contexts.
1087
+ *
1088
+ * Note that the contexts created before the first scheduled model run
1089
+ * will inherit the data from `initialOutputs` passed to the constructor,
1090
+ * but contexts created after that will initially have output values set
1091
+ * to zero.
1092
+ *
1093
+ * @param inputs The input values, in the same order as in the spec file passed to `sde`.
1094
+ * @param options Additional options for the context.
1095
+ * @param options.externalData Additional data that is external to the model outputs.
1096
+ * For example, this can contain data that was captured from an initial reference
1097
+ * run, or other static data that is displayed in graphs alongside the model
1098
+ * output data in graphs.
1099
+ */
1100
+ addContext(inputs: InputValue[], options?: {
1101
+ externalData?: DataMap;
1102
+ }): ModelContext;
1103
+ /**
1104
+ * Remove the given context from the set of contexts managed by the scheduler.
1105
+ *
1106
+ * @param context The context to remove.
1107
+ */
1108
+ removeContext(context: ModelContext): void;
1109
+ /**
1110
+ * Schedule a model run (if not already pending). When the run is
1111
+ * complete, save the outputs and call the `onOutputsChanged` callback.
1112
+ */
1113
+ private runModelIfNeeded;
1114
+ /**
1115
+ * Run the model asynchronously for all relevant contexts.
1116
+ */
1117
+ private runModelNow;
1118
+ /**
1119
+ * Run the model asynchronously using the current set of input values in the given context.
1120
+ *
1121
+ * @param context The context to use for the model run.
1122
+ */
1123
+ private runModelNowForContext;
1005
1124
  }
1006
1125
 
1007
1126
  /**
@@ -1018,4 +1137,4 @@ declare function perfNow(): unknown;
1018
1137
  */
1019
1138
  declare function perfElapsed(t0: unknown): number;
1020
1139
 
1021
- export { BufferedRunModelParams, type GeneratedModel, type InputCallbacks, type InputValue, type InputVarId, type JsModel, type JsModelFunctionContext, type JsModelFunctions, type LookupDef, MockJsModel, MockWasmModule, ModelListing, type ModelListingSpecs, type ModelRunner, ModelScheduler, type OnEvalAux, type OnRunModel, type OutputVarId, Outputs, type ParseError, type Point, ReferencedRunModelParams, type RunModelOptions, type RunModelParams, type RunnableModel, Series, type VarId, type VarName, type VarRef, type VarSpec, type WasmModule, createInputValue, createLookupDef, createRunnableModel, createSynchronousModelRunner, decodeLookups, encodeLookups, encodeVarIndices, execJsModel, getEncodedLookupBufferLengths, getEncodedVarIndicesLength, getJsModelFunctions, initJsModel, initWasmModel, perfElapsed, perfNow };
1140
+ export { BufferedRunModelParams, type DataMap, type GeneratedModel, type InputCallbacks, type InputValue, type InputVarId, type JsModel, type JsModelFunctionContext, type JsModelFunctions, type LookupDef, MockJsModel, MockWasmModule, type ModelContext, ModelListing, type ModelListingSpecs, type ModelRunner, ModelScheduler, MultiContextModelScheduler, type OnEvalAux, type OnRunModel, type OutputVarId, Outputs, type ParseError, type Point, ReferencedRunModelParams, type RunModelOptions, type RunModelParams, type RunnableModel, Series, type SeriesMap, type SourceName, type VarId, type VarName, type VarRef, type VarSpec, type WasmModule, createInputValue, createLookupDef, createRunnableModel, createSynchronousModelRunner, decodeLookups, encodeLookups, encodeVarIndices, execJsModel, getEncodedLookupBufferLengths, getEncodedVarIndicesLength, getJsModelFunctions, initJsModel, initWasmModel, perfElapsed, perfNow };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { Result } from 'neverthrow';
2
2
 
3
+ /** The name of a data source for external/static datasets, e.g., 'Ref', 'Constants'. */
4
+ type SourceName = string;
3
5
  /** A variable name, as used in the modeling tool. */
4
6
  type VarName = string;
5
7
  /** A variable identifier, as used in model code generated by SDEverywhere. */
@@ -86,6 +88,10 @@ declare function createInputValue(varId: InputVarId, defaultValue: number, initi
86
88
 
87
89
  /** Indicates the type of error encountered when parsing an outputs buffer. */
88
90
  type ParseError = 'invalid-point-count';
91
+ /** Type alias for a map that holds a `Series` instance for each output (or static) variable ID. */
92
+ type SeriesMap = Map<OutputVarId, Series>;
93
+ /** Type alias for a map that holds data for a given source name. */
94
+ type DataMap = Map<SourceName, SeriesMap>;
89
95
  /**
90
96
  * A time series of data points for an output variable.
91
97
  */
@@ -908,7 +914,7 @@ declare class MockWasmModule implements WasmModule {
908
914
  }
909
915
 
910
916
  /**
911
- * Abstraction that allows for running the wasm model on the JS thread
917
+ * Abstraction that allows for running a generated model on the JS thread
912
918
  * or asynchronously (e.g. in a Web Worker), depending on the implementation.
913
919
  */
914
920
  interface ModelRunner {
@@ -965,7 +971,7 @@ declare function createRunnableModel(generatedModel: GeneratedModel): RunnableMo
965
971
  declare function createSynchronousModelRunner(generatedModel: GeneratedModel): ModelRunner;
966
972
 
967
973
  /**
968
- * A high-level interface that schedules running of the underlying `WasmModel`.
974
+ * A high-level interface that schedules the underlying `ModelRunner`.
969
975
  *
970
976
  * When one or more input values are changed, this class will schedule a model
971
977
  * run to be completed as soon as possible. When the model run has completed,
@@ -994,14 +1000,127 @@ declare class ModelScheduler {
994
1000
  */
995
1001
  constructor(runner: ModelRunner, userInputs: InputValue[], outputs: Outputs);
996
1002
  /**
997
- * Schedule a wasm model run (if not already pending). When the run is
1003
+ * Schedule a model run (if not already pending). When the run is
998
1004
  * complete, save the outputs and call the `onOutputsChanged` callback.
999
1005
  */
1000
- private runWasmModelIfNeeded;
1006
+ private runModelIfNeeded;
1001
1007
  /**
1002
- * Run the wasm model asynchronously using the current set of input values.
1008
+ * Run the model asynchronously using the current set of input values.
1003
1009
  */
1004
- private runWasmModelNow;
1010
+ private runModelNow;
1011
+ }
1012
+
1013
+ /**
1014
+ * Defines a context that holds a distinct set of model inputs and outputs.
1015
+ * These inputs and outputs are kept separate from those in other contexts,
1016
+ * which allows an application to use the same underlying model instance
1017
+ * with multiple sets of inputs and outputs.
1018
+ */
1019
+ interface ModelContext {
1020
+ /**
1021
+ * Called when the outputs have been updated after a model run.
1022
+ */
1023
+ onOutputsChanged?: () => void;
1024
+ /**
1025
+ * Return the series data for the given model output variable or external
1026
+ * dataset.
1027
+ *
1028
+ * @param varId The ID of the output variable associated with the data.
1029
+ * @param sourceName The external data source name (e.g. "Ref"), or
1030
+ * undefined to use the latest model output data from this context.
1031
+ */
1032
+ getSeriesForVar(varId: OutputVarId, sourceName?: SourceName): Series | undefined;
1033
+ }
1034
+ /**
1035
+ * A high-level interface that schedules running of the underlying `ModelRunner`.
1036
+ *
1037
+ * This class is similar to the (single context) `ModelScheduler` class, except
1038
+ * this one supports multiple contexts, each with its own distinct set of
1039
+ * inputs and outputs. This is useful for running the same underlying model
1040
+ * instance with different sets of inputs and outputs. For example, you can
1041
+ * use this to show the outputs for multiple scenarios in a single graph, or
1042
+ * multiple scenarios across different graphs.
1043
+ *
1044
+ * When input values are changed in one or more contexts, this class will schedule
1045
+ * a model run for each changed context to be completed as soon as possible.
1046
+ * When the model run has completed, the context's `onOutputsChanged` function
1047
+ * is called to notify that new output data is available for that context.
1048
+ *
1049
+ * The `ModelRunner` is pluggable to allow for running the model synchronously
1050
+ * (on the main JavaScript thread) or asynchronously (in a Web Worker or Node.js
1051
+ * worker thread).
1052
+ */
1053
+ declare class MultiContextModelScheduler {
1054
+ private readonly runner;
1055
+ /**
1056
+ * An optional `Outputs` instance that will be reused for the initial context. This will
1057
+ * be set to undefined after it is used for the first context.
1058
+ */
1059
+ private initialOutputs?;
1060
+ /** The second array that holds a stable copy of the user inputs. */
1061
+ private currentInputs;
1062
+ /** The contexts that hold distinct sets of inputs and outputs. */
1063
+ private readonly contexts;
1064
+ /** Whether a model run has been scheduled. */
1065
+ private runNeeded;
1066
+ /** Whether a model run is in progress. */
1067
+ private runInProgress;
1068
+ /**
1069
+ * @param runner The model runner.
1070
+ * @param options Additional options for the scheduler.
1071
+ * @param options.initialOutputs An optional `Outputs` instance that will be reused
1072
+ * for the initial context. This is useful for saving memory when an `Outputs`
1073
+ * instance was already created for, e.g., a initial baseline/reference run.
1074
+ */
1075
+ constructor(runner: ModelRunner, options?: {
1076
+ initialOutputs?: Outputs;
1077
+ });
1078
+ /**
1079
+ * Return true if the scheduler has started any model runs.
1080
+ */
1081
+ isStarted(): boolean;
1082
+ /**
1083
+ * Add a new context that holds a distinct set of model inputs and outputs.
1084
+ * These inputs and outputs are kept separate from those in other contexts,
1085
+ * which allows an application to use the same underlying model to run with
1086
+ * multiple I/O contexts.
1087
+ *
1088
+ * Note that the contexts created before the first scheduled model run
1089
+ * will inherit the data from `initialOutputs` passed to the constructor,
1090
+ * but contexts created after that will initially have output values set
1091
+ * to zero.
1092
+ *
1093
+ * @param inputs The input values, in the same order as in the spec file passed to `sde`.
1094
+ * @param options Additional options for the context.
1095
+ * @param options.externalData Additional data that is external to the model outputs.
1096
+ * For example, this can contain data that was captured from an initial reference
1097
+ * run, or other static data that is displayed in graphs alongside the model
1098
+ * output data in graphs.
1099
+ */
1100
+ addContext(inputs: InputValue[], options?: {
1101
+ externalData?: DataMap;
1102
+ }): ModelContext;
1103
+ /**
1104
+ * Remove the given context from the set of contexts managed by the scheduler.
1105
+ *
1106
+ * @param context The context to remove.
1107
+ */
1108
+ removeContext(context: ModelContext): void;
1109
+ /**
1110
+ * Schedule a model run (if not already pending). When the run is
1111
+ * complete, save the outputs and call the `onOutputsChanged` callback.
1112
+ */
1113
+ private runModelIfNeeded;
1114
+ /**
1115
+ * Run the model asynchronously for all relevant contexts.
1116
+ */
1117
+ private runModelNow;
1118
+ /**
1119
+ * Run the model asynchronously using the current set of input values in the given context.
1120
+ *
1121
+ * @param context The context to use for the model run.
1122
+ */
1123
+ private runModelNowForContext;
1005
1124
  }
1006
1125
 
1007
1126
  /**
@@ -1018,4 +1137,4 @@ declare function perfNow(): unknown;
1018
1137
  */
1019
1138
  declare function perfElapsed(t0: unknown): number;
1020
1139
 
1021
- export { BufferedRunModelParams, type GeneratedModel, type InputCallbacks, type InputValue, type InputVarId, type JsModel, type JsModelFunctionContext, type JsModelFunctions, type LookupDef, MockJsModel, MockWasmModule, ModelListing, type ModelListingSpecs, type ModelRunner, ModelScheduler, type OnEvalAux, type OnRunModel, type OutputVarId, Outputs, type ParseError, type Point, ReferencedRunModelParams, type RunModelOptions, type RunModelParams, type RunnableModel, Series, type VarId, type VarName, type VarRef, type VarSpec, type WasmModule, createInputValue, createLookupDef, createRunnableModel, createSynchronousModelRunner, decodeLookups, encodeLookups, encodeVarIndices, execJsModel, getEncodedLookupBufferLengths, getEncodedVarIndicesLength, getJsModelFunctions, initJsModel, initWasmModel, perfElapsed, perfNow };
1140
+ export { BufferedRunModelParams, type DataMap, type GeneratedModel, type InputCallbacks, type InputValue, type InputVarId, type JsModel, type JsModelFunctionContext, type JsModelFunctions, type LookupDef, MockJsModel, MockWasmModule, type ModelContext, ModelListing, type ModelListingSpecs, type ModelRunner, ModelScheduler, MultiContextModelScheduler, type OnEvalAux, type OnRunModel, type OutputVarId, Outputs, type ParseError, type Point, ReferencedRunModelParams, type RunModelOptions, type RunModelParams, type RunnableModel, Series, type SeriesMap, type SourceName, type VarId, type VarName, type VarRef, type VarSpec, type WasmModule, createInputValue, createLookupDef, createRunnableModel, createSynchronousModelRunner, decodeLookups, encodeLookups, encodeVarIndices, execJsModel, getEncodedLookupBufferLengths, getEncodedVarIndicesLength, getJsModelFunctions, initJsModel, initWasmModel, perfElapsed, perfNow };
package/dist/index.js CHANGED
@@ -1862,7 +1862,7 @@ var ModelScheduler = class {
1862
1862
  /** Whether a model run is in progress. */
1863
1863
  this.runInProgress = false;
1864
1864
  const afterSet = () => {
1865
- this.runWasmModelIfNeeded();
1865
+ this.runModelIfNeeded();
1866
1866
  };
1867
1867
  for (const userInput of userInputs) {
1868
1868
  userInput.callbacks.onSet = afterSet;
@@ -1873,24 +1873,24 @@ var ModelScheduler = class {
1873
1873
  }
1874
1874
  }
1875
1875
  /**
1876
- * Schedule a wasm model run (if not already pending). When the run is
1876
+ * Schedule a model run (if not already pending). When the run is
1877
1877
  * complete, save the outputs and call the `onOutputsChanged` callback.
1878
1878
  */
1879
- runWasmModelIfNeeded() {
1879
+ runModelIfNeeded() {
1880
1880
  this.runNeeded = true;
1881
1881
  if (this.runInProgress) {
1882
1882
  return;
1883
1883
  } else {
1884
1884
  this.runInProgress = true;
1885
1885
  setTimeout(() => {
1886
- this.runWasmModelNow();
1886
+ this.runModelNow();
1887
1887
  }, 0);
1888
1888
  }
1889
1889
  }
1890
1890
  /**
1891
- * Run the wasm model asynchronously using the current set of input values.
1891
+ * Run the model asynchronously using the current set of input values.
1892
1892
  */
1893
- runWasmModelNow() {
1893
+ runModelNow() {
1894
1894
  return __async(this, null, function* () {
1895
1895
  var _a;
1896
1896
  for (let i = 0; i < this.userInputs.length; i++) {
@@ -1905,7 +1905,7 @@ var ModelScheduler = class {
1905
1905
  if (this.runNeeded) {
1906
1906
  this.runNeeded = false;
1907
1907
  setTimeout(() => {
1908
- this.runWasmModelNow();
1908
+ this.runModelNow();
1909
1909
  }, 0);
1910
1910
  } else {
1911
1911
  this.runNeeded = false;
@@ -1927,12 +1927,199 @@ function createSimpleInputValue(varId) {
1927
1927
  };
1928
1928
  return { varId, get, set, reset, callbacks: {} };
1929
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
+ };
1930
2116
  export {
1931
2117
  BufferedRunModelParams,
1932
2118
  MockJsModel,
1933
2119
  MockWasmModule,
1934
2120
  ModelListing,
1935
2121
  ModelScheduler,
2122
+ MultiContextModelScheduler,
1936
2123
  Outputs,
1937
2124
  ReferencedRunModelParams,
1938
2125
  Series,