@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/README.md CHANGED
@@ -52,7 +52,7 @@ import loadGeneratedModel from './sde-prep/generated-model.js'
52
52
  ### 2. Initialize a `ModelRunner`
53
53
 
54
54
  The next step is to create a `ModelRunner` instance, which simplifies
55
- the process of running a `WasmModel` with a given set of inputs and
55
+ the process of running a generated model with a given set of inputs and
56
56
  parsing the outputs.
57
57
  The `ModelRunner` produces an `Outputs` instance that provides easy
58
58
  access to time series data for each output variable in the model.
package/dist/index.cjs CHANGED
@@ -58,6 +58,7 @@ __export(src_exports, {
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,
@@ -1906,7 +1907,7 @@ var ModelScheduler = class {
1906
1907
  /** Whether a model run is in progress. */
1907
1908
  this.runInProgress = false;
1908
1909
  const afterSet = () => {
1909
- this.runWasmModelIfNeeded();
1910
+ this.runModelIfNeeded();
1910
1911
  };
1911
1912
  for (const userInput of userInputs) {
1912
1913
  userInput.callbacks.onSet = afterSet;
@@ -1917,24 +1918,24 @@ var ModelScheduler = class {
1917
1918
  }
1918
1919
  }
1919
1920
  /**
1920
- * Schedule a wasm model run (if not already pending). When the run is
1921
+ * Schedule a model run (if not already pending). When the run is
1921
1922
  * complete, save the outputs and call the `onOutputsChanged` callback.
1922
1923
  */
1923
- runWasmModelIfNeeded() {
1924
+ runModelIfNeeded() {
1924
1925
  this.runNeeded = true;
1925
1926
  if (this.runInProgress) {
1926
1927
  return;
1927
1928
  } else {
1928
1929
  this.runInProgress = true;
1929
1930
  setTimeout(() => {
1930
- this.runWasmModelNow();
1931
+ this.runModelNow();
1931
1932
  }, 0);
1932
1933
  }
1933
1934
  }
1934
1935
  /**
1935
- * Run the wasm model asynchronously using the current set of input values.
1936
+ * Run the model asynchronously using the current set of input values.
1936
1937
  */
1937
- runWasmModelNow() {
1938
+ runModelNow() {
1938
1939
  return __async(this, null, function* () {
1939
1940
  var _a;
1940
1941
  for (let i = 0; i < this.userInputs.length; i++) {
@@ -1949,7 +1950,7 @@ var ModelScheduler = class {
1949
1950
  if (this.runNeeded) {
1950
1951
  this.runNeeded = false;
1951
1952
  setTimeout(() => {
1952
- this.runWasmModelNow();
1953
+ this.runModelNow();
1953
1954
  }, 0);
1954
1955
  } else {
1955
1956
  this.runNeeded = false;
@@ -1971,6 +1972,192 @@ function createSimpleInputValue(varId) {
1971
1972
  };
1972
1973
  return { varId, get, set, reset, callbacks: {} };
1973
1974
  }
1975
+
1976
+ // src/model-scheduler/multi-context-model-scheduler.ts
1977
+ var MultiContextModelScheduler = class {
1978
+ /**
1979
+ * @param runner The model runner.
1980
+ * @param options Additional options for the scheduler.
1981
+ * @param options.initialOutputs An optional `Outputs` instance that will be reused
1982
+ * for the initial context. This is useful for saving memory when an `Outputs`
1983
+ * instance was already created for, e.g., a initial baseline/reference run.
1984
+ */
1985
+ constructor(runner, options) {
1986
+ this.runner = runner;
1987
+ /** The contexts that hold distinct sets of inputs and outputs. */
1988
+ this.contexts = [];
1989
+ /** Whether a model run has been scheduled. */
1990
+ this.runNeeded = false;
1991
+ /** Whether a model run is in progress. */
1992
+ this.runInProgress = false;
1993
+ this.initialOutputs = options == null ? void 0 : options.initialOutputs;
1994
+ }
1995
+ /**
1996
+ * Return true if the scheduler has started any model runs.
1997
+ */
1998
+ isStarted() {
1999
+ return this.initialOutputs === void 0;
2000
+ }
2001
+ /**
2002
+ * Add a new context that holds a distinct set of model inputs and outputs.
2003
+ * These inputs and outputs are kept separate from those in other contexts,
2004
+ * which allows an application to use the same underlying model to run with
2005
+ * multiple I/O contexts.
2006
+ *
2007
+ * Note that the contexts created before the first scheduled model run
2008
+ * will inherit the data from `initialOutputs` passed to the constructor,
2009
+ * but contexts created after that will initially have output values set
2010
+ * to zero.
2011
+ *
2012
+ * @param inputs The input values, in the same order as in the spec file passed to `sde`.
2013
+ * @param options Additional options for the context.
2014
+ * @param options.externalData Additional data that is external to the model outputs.
2015
+ * For example, this can contain data that was captured from an initial reference
2016
+ * run, or other static data that is displayed in graphs alongside the model
2017
+ * output data in graphs.
2018
+ */
2019
+ addContext(inputs, options) {
2020
+ let outputs;
2021
+ if (this.initialOutputs !== void 0) {
2022
+ if (this.contexts.length === 0) {
2023
+ outputs = this.initialOutputs;
2024
+ } else {
2025
+ outputs = this.runner.createOutputs();
2026
+ for (const varId of outputs.varIds) {
2027
+ const series0 = this.initialOutputs.getSeriesForVar(varId);
2028
+ const series1 = outputs.getSeriesForVar(varId);
2029
+ for (let i = 0; i < series0.points.length; i++) {
2030
+ series1.points[i].y = series0.points[i].y;
2031
+ }
2032
+ }
2033
+ }
2034
+ } else {
2035
+ outputs = this.runner.createOutputs();
2036
+ }
2037
+ const context = new ModelContextImpl(inputs, outputs, options == null ? void 0 : options.externalData);
2038
+ const afterSet = () => {
2039
+ context.runNeeded = true;
2040
+ this.runModelIfNeeded();
2041
+ };
2042
+ for (const input of inputs) {
2043
+ input.callbacks.onSet = afterSet;
2044
+ }
2045
+ this.contexts.push(context);
2046
+ return context;
2047
+ }
2048
+ /**
2049
+ * Remove the given context from the set of contexts managed by the scheduler.
2050
+ *
2051
+ * @param context The context to remove.
2052
+ */
2053
+ removeContext(context) {
2054
+ const index = this.contexts.findIndex((c) => c === context);
2055
+ if (index >= 0) {
2056
+ this.contexts.splice(index, 1);
2057
+ }
2058
+ }
2059
+ /**
2060
+ * Schedule a model run (if not already pending). When the run is
2061
+ * complete, save the outputs and call the `onOutputsChanged` callback.
2062
+ */
2063
+ runModelIfNeeded() {
2064
+ this.runNeeded = true;
2065
+ if (this.runInProgress) {
2066
+ return;
2067
+ } else {
2068
+ this.runInProgress = true;
2069
+ setTimeout(() => {
2070
+ this.runModelNow();
2071
+ }, 0);
2072
+ }
2073
+ }
2074
+ /**
2075
+ * Run the model asynchronously for all relevant contexts.
2076
+ */
2077
+ runModelNow() {
2078
+ return __async(this, null, function* () {
2079
+ this.initialOutputs = void 0;
2080
+ for (const context of this.contexts) {
2081
+ if (context.runNeeded) {
2082
+ context.runNeeded = false;
2083
+ yield this.runModelNowForContext(context);
2084
+ }
2085
+ }
2086
+ if (this.runNeeded) {
2087
+ this.runNeeded = false;
2088
+ setTimeout(() => {
2089
+ this.runModelNow();
2090
+ }, 0);
2091
+ } else {
2092
+ this.runNeeded = false;
2093
+ this.runInProgress = false;
2094
+ }
2095
+ });
2096
+ }
2097
+ /**
2098
+ * Run the model asynchronously using the current set of input values in the given context.
2099
+ *
2100
+ * @param context The context to use for the model run.
2101
+ */
2102
+ runModelNowForContext(context) {
2103
+ return __async(this, null, function* () {
2104
+ var _a;
2105
+ if (this.currentInputs === void 0) {
2106
+ this.currentInputs = Array(context.inputsArray.length);
2107
+ }
2108
+ for (let i = 0; i < context.inputsArray.length; i++) {
2109
+ this.currentInputs[i] = context.inputsArray[i].get();
2110
+ }
2111
+ try {
2112
+ yield this.runner.runModel(this.currentInputs, context.outputs);
2113
+ (_a = context.onOutputsChanged) == null ? void 0 : _a.call(context);
2114
+ } catch (e) {
2115
+ console.error("ERROR: The scheduler encountered an error when running the model:", e);
2116
+ }
2117
+ });
2118
+ }
2119
+ };
2120
+ var ModelContextImpl = class {
2121
+ /**
2122
+ * @hidden This is intended for use by `MultiContextModelScheduler` only.
2123
+ *
2124
+ * @param inputs The input values, in the same order as in the spec file passed to `sde`.
2125
+ * @param outputs The structure into which the model outputs will be stored.
2126
+ * @param externalData Additional data that is external to the model outputs. For example, this can contain
2127
+ * data that was captured from an initial reference run, or other static data that is displayed in graphs
2128
+ * alongside the model output data in graphs.
2129
+ */
2130
+ constructor(inputs, outputs, externalData) {
2131
+ this.externalData = externalData;
2132
+ /**
2133
+ * Whether a model run is needed for this context.
2134
+ * @hidden This is intended for use by `MultiContextModelScheduler` only.
2135
+ */
2136
+ this.runNeeded = false;
2137
+ this.inputsArray = Array.from(inputs);
2138
+ this.outputs = outputs;
2139
+ }
2140
+ /**
2141
+ * Return the series data for the given model output variable or external
2142
+ * dataset.
2143
+ *
2144
+ * @param varId The ID of the output variable associated with the data.
2145
+ * @param sourceName The external data source name (e.g. "Ref"), or
2146
+ * undefined to use the latest model output data from this context.
2147
+ */
2148
+ getSeriesForVar(varId, sourceName) {
2149
+ if (sourceName === void 0) {
2150
+ return this.outputs.getSeriesForVar(varId);
2151
+ } else {
2152
+ const dataForSource = this.externalData.get(sourceName);
2153
+ if (dataForSource !== void 0) {
2154
+ return dataForSource.get(varId);
2155
+ } else {
2156
+ return void 0;
2157
+ }
2158
+ }
2159
+ }
2160
+ };
1974
2161
  // Annotate the CommonJS export names for ESM import in node:
1975
2162
  0 && (module.exports = {
1976
2163
  BufferedRunModelParams,
@@ -1978,6 +2165,7 @@ function createSimpleInputValue(varId) {
1978
2165
  MockWasmModule,
1979
2166
  ModelListing,
1980
2167
  ModelScheduler,
2168
+ MultiContextModelScheduler,
1981
2169
  Outputs,
1982
2170
  ReferencedRunModelParams,
1983
2171
  Series,