@sdeverywhere/runtime 0.2.7 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +250 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -4
- package/dist/index.d.ts +87 -4
- package/dist/index.js +243 -15
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/_shared/inputs.ts","../src/_shared/outputs.ts","../src/_shared/var-indices.ts","../src/_shared/lookup-def.ts","../src/model-listing/model-listing.ts","../src/runnable-model/resolve-var-ref.ts","../src/runnable-model/buffered-run-model-params.ts","../src/runnable-model/referenced-run-model-params.ts","../src/js-model/js-model-constants.ts","../src/js-model/js-model-lookup.ts","../src/js-model/js-model-functions.ts","../src/perf/perf.ts","../src/runnable-model/base-runnable-model.ts","../src/js-model/js-model.ts","../src/js-model/exec-js-model.ts","../src/js-model/_mocks/mock-js-model.ts","../src/wasm-model/wasm-buffer.ts","../src/wasm-model/wasm-model.ts","../src/wasm-model/_mocks/mock-wasm-module.ts","../src/model-runner/synchronous-model-runner.ts","../src/model-scheduler/model-scheduler.ts","../src/model-scheduler/multi-context-model-scheduler.ts"],"sourcesContent":["// Copyright (c) 2020-2022 Climate Interactive / New Venture Fund\n\nimport type { InputVarId } from './types'\n\n/** Callback functions that are called when the input value is changed. */\nexport interface InputCallbacks {\n /** Called after a new value is set. */\n onSet?: () => void\n}\n\n/**\n * Represents a writable model input.\n */\nexport interface InputValue {\n /** The ID of the associated input variable, as used in SDEverywhere. */\n varId: InputVarId\n /** Get the current value of the input. */\n get: () => number\n /** Set the input to the given value. */\n set: (value: number) => void\n /** Reset the input to its default value. */\n reset: () => void\n /** Callback functions that are called when the input value is changed. */\n callbacks: InputCallbacks\n}\n\n/**\n * Create a basic `InputValue` instance that notifies when a new value is set.\n *\n * @param varId The input variable ID, as used in SDEverywhere.\n * @param defaultValue The default value of the input.\n * @param initialValue The inital value of the input; if undefined, will use `defaultValue`.\n */\nexport function createInputValue(varId: InputVarId, defaultValue: number, initialValue?: number): InputValue {\n let currentValue = initialValue !== undefined ? initialValue : defaultValue\n\n // The `onSet` callback is initially undefined but will be installed by `ModelScheduler`\n const callbacks: InputCallbacks = {}\n\n const get = () => {\n return currentValue\n }\n\n const set = (newValue: number) => {\n if (newValue !== currentValue) {\n currentValue = newValue\n callbacks.onSet?.()\n }\n }\n\n const reset = () => {\n set(defaultValue)\n }\n\n return { varId, get, set, reset, callbacks }\n}\n","// Copyright (c) 2020-2022 Climate Interactive / New Venture Fund\n\nimport type { Result } from 'neverthrow'\nimport { ok, err } from 'neverthrow'\n\nimport type { OutputVarId, Point, SourceName, VarSpec } from './types'\n\n/** Indicates the type of error encountered when parsing an outputs buffer. */\nexport type ParseError = 'invalid-point-count'\n\n/** Type alias for a map that holds a `Series` instance for each output (or static) variable ID. */\nexport type SeriesMap = Map<OutputVarId, Series>\n\n/** Type alias for a map that holds data for a given source name. */\nexport type DataMap = Map<SourceName, SeriesMap>\n\n/**\n * A time series of data points for an output variable.\n */\nexport class Series {\n /**\n * @param varId The ID for the output variable (as used by SDEverywhere).\n * @param points The data points for the variable, one point per time increment.\n */\n constructor(public readonly varId: OutputVarId, public readonly points: Point[]) {}\n\n /**\n * Return the Y value at the given time. Note that this does not attempt to interpolate\n * if there is no data point defined for the given time and will return undefined in\n * that case.\n *\n * @param time The x (time) value.\n * @return The y value for the given time, or undefined if there is no data point defined\n * for the given time.\n */\n getValueAtTime(time: number): number | undefined {\n // TODO: Add option to allow interpolation if the given time value is in between points\n // TODO: Use binary search to make lookups faster\n return this.points.find(p => p.x === time)?.y\n }\n\n /**\n * Create a new `Series` instance that is a copy of this one.\n */\n copy(): Series {\n // Create a deep copy\n const pointsCopy = this.points.map(p => ({ ...p }))\n return new Series(this.varId, pointsCopy)\n }\n}\n\n/** Represents the outputs from a model run. */\nexport class Outputs {\n /** The number of data points in each series. */\n public readonly seriesLength: number\n /** The array of series, one for each output variable. */\n public readonly varSeries: Series[]\n\n /**\n * The latest model run time, in milliseconds.\n * @hidden This is not yet part of the public API; it is exposed here for use\n * in performance testing tools.\n */\n public runTimeInMillis: number\n\n /**\n * The optional set of specs that dictate which variables from the model will be\n * stored in this `Outputs` instance. If undefined, the default set of outputs\n * will be stored (as configured in `varIds`).\n * @hidden This is not yet part of the public API; it is exposed here for use\n * in experimental testing tools.\n */\n public varSpecs?: VarSpec[]\n\n /**\n * @param varIds The output variable identifiers.\n * @param startTime The start time for the model.\n * @param endTime The end time for the model.\n * @param saveFreq The frequency with which output values are saved (aka `SAVEPER`).\n */\n constructor(\n public readonly varIds: OutputVarId[],\n public readonly startTime: number,\n public readonly endTime: number,\n public readonly saveFreq = 1\n ) {\n // Each series will include one data point per \"save\", inclusive of the\n // start and end times\n this.seriesLength = Math.round((endTime - startTime) / saveFreq) + 1\n\n // Create an array of arrays, one for each output variable\n this.varSeries = new Array(varIds.length)\n\n // Populate the arrays, filling in the time for each point\n for (let i = 0; i < varIds.length; i++) {\n const points: Point[] = new Array(this.seriesLength)\n for (let j = 0; j < this.seriesLength; j++) {\n points[j] = { x: startTime + j * saveFreq, y: 0 }\n }\n const varId = varIds[i]\n this.varSeries[i] = new Series(varId, points)\n }\n }\n\n /**\n * The optional set of specs that dictate which variables from the model will be\n * stored in this `Outputs` instance. If undefined, the default set of outputs\n * will be stored (as configured in `varIds`).\n * @hidden This is not yet part of the public API; it is exposed here for use\n * in experimental testing tools.\n */\n setVarSpecs(varSpecs: VarSpec[]) {\n if (varSpecs.length !== this.varIds.length) {\n throw new Error('Length of output varSpecs must match that of varIds')\n }\n this.varSpecs = varSpecs\n }\n\n /**\n * Parse the given raw float buffer (produced by the model) and store the values\n * into this `Outputs` instance.\n *\n * Note that the length of `outputsBuffer` must be greater than or equal to\n * the capacity of this `Outputs` instance. The `Outputs` instance is allowed\n * to be smaller to support the case where you want to extract a subset of\n * the time range in the buffer produced by the model.\n *\n * @param outputsBuffer The raw outputs buffer produced by the model.\n * @param rowLength The number of elements per row (one element per save point).\n * @return An `ok` result if the buffer is valid, otherwise an `err` result.\n */\n updateFromBuffer(outputsBuffer: Float64Array, rowLength: number): Result<void, ParseError> {\n const result = parseOutputsBuffer(outputsBuffer, rowLength, this)\n if (result.isOk()) {\n return ok(undefined)\n } else {\n return err(result.error)\n }\n }\n\n /**\n * Return the series for the given output variable.\n *\n * @param varId The ID of the output variable (as used by SDEverywhere).\n */\n getSeriesForVar(varId: OutputVarId): Series | undefined {\n const seriesIndex = this.varIds.indexOf(varId)\n if (seriesIndex >= 0) {\n return this.varSeries[seriesIndex]\n } else {\n // TODO: Error\n return undefined\n }\n }\n}\n\n/**\n * Parse the raw buffer produced by the model and store the values in the\n * given (reused) `Outputs` object.\n *\n * @param outputsBuffer The raw outputs buffer produced by the model.\n * @param rowLength The number of elements per row (one element per year or save point).\n * @return An `ok` result if the buffer is valid, otherwise an `err` result.\n * @hidden\n */\nfunction parseOutputsBuffer(\n outputsBuffer: Float64Array,\n rowLength: number,\n outputs: Outputs\n): Result<Outputs, ParseError> {\n const varCount = outputs.varIds.length\n const seriesLength = outputs.seriesLength\n if (rowLength < seriesLength || outputsBuffer.length < varCount * seriesLength) {\n return err('invalid-point-count')\n }\n\n // The buffer populated by the C `runModelWithBuffers` function is already\n // transposed, so the first \"row\" contains the values for the first output\n // variable (from start time to end time), and so on.\n for (let outputVarIndex = 0; outputVarIndex < varCount; outputVarIndex++) {\n const series = outputs.varSeries[outputVarIndex]\n let sourceIndex = rowLength * outputVarIndex\n for (let valueIndex = 0; valueIndex < seriesLength; valueIndex++) {\n series.points[valueIndex].y = validateNumber(outputsBuffer[sourceIndex])\n sourceIndex++\n }\n }\n\n return ok(outputs)\n}\n\n/**\n * Return the given number if it is valid, or undefined if it is invalid.\n *\n * SDE converts Vensim's `:NA:` values to `-DBL_MAX`, so if we see a very large negative\n * value, convert it to `undefined`. This is preferable to including extreme values\n * because some charting libraries (e.g. Chart.js) appear to choke on these large values\n * in certain browsers (e.g. Safari), but `undefined` appears to be handled better and\n * does a better job of signaling that the data point is undefined.\n *\n * @hidden\n */\nfunction validateNumber(x: number): number | undefined {\n if (!isNaN(x) && x > -1e32) {\n return x\n } else {\n return undefined\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport type { LookupDef } from './lookup-def'\nimport type { VarSpec } from './types'\n\n/**\n * Return the length of the array that is required to store the variable\n * indices for the given `VarSpec` instances.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param varSpecs The `VarSpec` instances to encode.\n */\nexport function getEncodedVarIndicesLength(varSpecs: VarSpec[]): number {\n // The indices buffer has the following format:\n // variable count\n // varN index\n // varN subscript count\n // varN sub1 index\n // varN sub2 index\n // ...\n // varN subM index\n // ... (repeat for each var spec)\n\n // Start with one element for the total variable count\n let length = 1\n\n for (const varSpec of varSpecs) {\n // Include one element for the variable index and one for the subscript count\n length += 2\n\n // Include one element for each subscript\n const subCount = varSpec.subscriptIndices?.length || 0\n length += subCount\n }\n\n return length\n}\n\n/**\n * Encode variable indices to the given array.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param varSpecs The `VarSpec` instances to encode.\n */\nexport function encodeVarIndices(varSpecs: VarSpec[], indicesArray: Int32Array): void {\n // Write the variable count\n let offset = 0\n indicesArray[offset++] = varSpecs.length\n\n // Write the indices for each variable\n for (const varSpec of varSpecs) {\n // Write the variable index\n indicesArray[offset++] = varSpec.varIndex\n\n // Write the subscript count\n const subs = varSpec.subscriptIndices\n const subCount = subs?.length || 0\n indicesArray[offset++] = subCount\n\n // Write the subscript indices\n for (let i = 0; i < subCount; i++) {\n indicesArray[offset++] = subs[i]\n }\n }\n}\n\n/**\n * Return the lengths of the arrays that are required to store the lookup data\n * and indices for the given `LookupDef` instances.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param lookupDefs The `LookupDef` instances to encode.\n */\nexport function getEncodedLookupBufferLengths(lookupDefs: LookupDef[]): {\n lookupIndicesLength: number\n lookupsLength: number\n} {\n // The lookups buffer includes all data points for the provided lookup overrides\n // (added sequentially, with no padding between datasets). The lookup indices\n // buffer has the following format:\n // lookup count\n // lookupN var index\n // lookupN subscript count\n // lookupN sub1 index\n // lookupN sub2 index\n // ...\n // lookupN subM index\n // lookupN data offset (relative to the start of the lookups buffer, in float64 elements)\n // lookupN data length (in float64 elements)\n // ... (repeat for each lookup)\n\n // Start with one element for the total lookup variable count\n let lookupIndicesLength = 1\n let lookupsLength = 0\n\n for (const lookupDef of lookupDefs) {\n // Ensure that the var spec has already been resolved\n const varSpec = lookupDef.varRef.varSpec\n if (varSpec === undefined) {\n throw new Error('Cannot compute lookup buffer lengths until all lookup var specs are defined')\n }\n\n // Include one element for the variable index and one for the subscript count\n lookupIndicesLength += 2\n\n // Include one element for each subscript\n const subCount = varSpec.subscriptIndices?.length || 0\n lookupIndicesLength += subCount\n\n // Include one element for the data offset and one element for the data length\n lookupIndicesLength += 2\n\n // Add the length of the lookup points array\n lookupsLength += lookupDef.points?.length || 0\n }\n\n return {\n lookupIndicesLength,\n lookupsLength\n }\n}\n\n/**\n * Encode lookup data and indices to the given arrays.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param lookupDefs The `LookupDef` instances to encode.\n * @param lookupIndicesArray The view on the lookup indices buffer.\n * @param lookupsArray The view on the lookup data buffer. This can be undefined in\n * the case where the data for the lookup(s) is empty.\n */\nexport function encodeLookups(\n lookupDefs: LookupDef[],\n lookupIndicesArray: Int32Array,\n lookupsArray: Float64Array | undefined\n): void {\n // Write the lookup variable count\n let li = 0\n lookupIndicesArray[li++] = lookupDefs.length\n\n // Write the indices and data for each lookup\n let lookupDataOffset = 0\n for (const lookupDef of lookupDefs) {\n // Write the lookup variable index\n const varSpec = lookupDef.varRef.varSpec\n lookupIndicesArray[li++] = varSpec.varIndex\n\n // Write the subscript count\n const subs = varSpec.subscriptIndices\n const subCount = subs?.length || 0\n lookupIndicesArray[li++] = subCount\n\n // Write the subscript indices\n for (let i = 0; i < subCount; i++) {\n lookupIndicesArray[li++] = subs[i]\n }\n\n if (lookupDef.points !== undefined) {\n // Write the lookup data offset and length for this variable\n lookupIndicesArray[li++] = lookupDataOffset\n lookupIndicesArray[li++] = lookupDef.points.length\n\n // Write the lookup data. Note that `lookupsView` can be undefined in the case\n // where the lookup data is empty.\n lookupsArray?.set(lookupDef.points, lookupDataOffset)\n lookupDataOffset += lookupDef.points.length\n } else {\n // Note that the points array can be undefined, which is used to indicate\n // that the lookup should be reset to its original data. In this case,\n // we use -1 for the data offset, which will be translated to NULL/undefined\n // when passed to the `setLookup` call.\n lookupIndicesArray[li++] = -1\n lookupIndicesArray[li++] = 0\n }\n }\n}\n\n/**\n * Decode lookup data and indices from the given buffer views and return the\n * reconstructed `LookupDef` instances.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param lookupIndicesArray The view on the lookup indices buffer.\n * @param lookupsArray The view on the lookup data buffer. This can be undefined in\n * the case where the data for the lookup(s) is empty.\n */\nexport function decodeLookups(lookupIndicesArray: Int32Array, lookupsArray: Float64Array | undefined): LookupDef[] {\n const lookupDefs: LookupDef[] = []\n let li = 0\n\n // Read the lookup variable count\n const lookupCount = lookupIndicesArray[li++]\n\n // Read the metadata for each variable from the lookup indices buffer\n for (let i = 0; i < lookupCount; i++) {\n // Read the lookup variable index\n const varIndex = lookupIndicesArray[li++]\n\n // Read the subscript count\n const subCount = lookupIndicesArray[li++]\n\n // Read the subscript indices\n const subscriptIndices: number[] = subCount > 0 ? Array(subCount) : undefined\n for (let subIndex = 0; subIndex < subCount; subIndex++) {\n subscriptIndices[subIndex] = lookupIndicesArray[li++]\n }\n\n // Read the lookup data offset and length for this variable\n const lookupDataOffset = lookupIndicesArray[li++]\n const lookupDataLength = lookupIndicesArray[li++]\n\n // Create a `VarSpec` for the variable\n const varSpec: VarSpec = {\n varIndex,\n subscriptIndices\n }\n\n let points: Float64Array\n if (lookupDataOffset >= 0) {\n // Copy the data from the lookup data buffer. Note that `lookupsArray` can be undefined\n // in the case where the lookup data is empty.\n // TODO: We can use `subarray` here instead of `slice` and let the model implementations\n // copy the data if needed on their side\n if (lookupsArray) {\n points = lookupsArray.slice(lookupDataOffset, lookupDataOffset + lookupDataLength)\n } else {\n points = new Float64Array(0)\n }\n } else {\n // A negative data offset value is used in the case where the points array is undefined,\n // which is used to indicate that the lookup should be reset to its original data\n points = undefined\n }\n lookupDefs.push({\n varRef: {\n varSpec\n },\n points\n })\n }\n\n return lookupDefs\n}\n","// Copyright (c) 2020-2022 Climate Interactive / New Venture Fund\n\nimport type { Point, VarRef } from './types'\n\n/**\n * Specifies the data that will be used to set or override a lookup definition.\n */\nexport interface LookupDef {\n /** The reference that identifies the lookup or data variable to be modified. */\n varRef: VarRef\n\n /** The lookup data as a flat array of (x,y) pairs. */\n points?: Float64Array\n}\n\n/**\n * Create a `LookupDef` instance from the given array of `Point` objects.\n *\n * @param varRef The reference to the lookup or data variable to be modified.\n * @param points The lookup data as an array of `Point` objects. This can be\n * undefined, in which case the lookup data will be reset to the original data.\n */\nexport function createLookupDef(varRef: VarRef, points: Point[] | undefined): LookupDef {\n let flatPoints: Float64Array\n if (points) {\n flatPoints = new Float64Array(points.length * 2)\n let i = 0\n for (const p of points) {\n flatPoints[i++] = p.x\n flatPoints[i++] = p.y\n }\n }\n\n return {\n varRef,\n points: flatPoints\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport type { OutputVarId, VarId, VarName, VarSpec } from '../_shared'\nimport { Outputs } from '../_shared'\n\ntype SubscriptId = string\ntype DimensionId = string\n\n/**\n * Holds information about a subscript used in the model.\n */\ninterface Subscript {\n /** The subscript identifier, as used in SDE. */\n id: SubscriptId\n /* The zero-based index for the subscript within the dimension. */\n index: number\n}\n\n/**\n * Holds information about a dimension (subscript family) used in the model.\n */\ninterface Dimension {\n /** The dimension identifier, as used in SDE. */\n id: DimensionId\n /** The set of subscripts in this dimension. */\n subscripts: Subscript[]\n}\n\n/**\n * This matches the shape of the minimal model `listing_min.json` that is generated\n * by the `sde generate --list` command.\n *\n * @hidden This is not yet part of the public API; it is exposed here for\n * internal use only.\n */\nexport interface ModelListingSpecs {\n dimensions: {\n id: DimensionId\n subIds: SubscriptId[]\n }[]\n\n variables: {\n id: VarId\n index: number\n dimIds?: DimensionId[]\n }[]\n}\n\n/**\n * @hidden This is not yet part of the public API; it is exposed here for use\n * in experimental testing tools.\n */\nexport class ModelListing {\n public readonly varSpecs: Map<VarId, VarSpec> = new Map()\n\n constructor(listingObj: ModelListingSpecs) {\n // Put dimension info into a map for easier access\n const dimensions: Map<DimensionId, Dimension> = new Map()\n for (const dimInfo of listingObj.dimensions) {\n const dimId = dimInfo.id\n const subscripts: Subscript[] = []\n for (let i = 0; i < dimInfo.subIds.length; i++) {\n subscripts.push({\n id: dimInfo.subIds[i],\n index: i\n })\n }\n dimensions.set(dimId, {\n id: dimId,\n subscripts\n })\n }\n\n function dimensionForId(dimId: DimensionId): Dimension {\n const dim = dimensions.get(dimId)\n if (dim === undefined) {\n throw new Error(`No dimension info found for id=${dimId}`)\n }\n return dim\n }\n\n // Gather the set of unique variables (consolidating refs that have different\n // subscripts but refer to the same variable)\n const baseVarIds: Set<OutputVarId> = new Set()\n for (const v of listingObj.variables) {\n // Get the base name of the variable (without subscripts)\n const baseVarId = varIdWithoutSubscripts(v.id)\n\n if (!baseVarIds.has(baseVarId)) {\n // Look up dimensions from the map\n const dimIds: DimensionId[] = v.dimIds || []\n const dimensions = dimIds.map(dimensionForId)\n\n // Expand and add all combinations of subscripts\n if (dimensions.length > 0) {\n // The variable is subscripted\n const dimSubs: Subscript[][] = []\n for (const dim of dimensions) {\n // For each dimension, get the array of subscripts;\n // for example, if the dimension has 3 subscripts, push\n // an array like ['_a1', '_a2', '_a3']\n dimSubs.push(dim.subscripts)\n }\n const combos = cartesianProductOf(dimSubs)\n for (const combo of combos) {\n // Add a spec for this var+subscript(s)\n const subs = combo.map(sub => sub.id).join(',')\n const subIndices = combo.map(sub => sub.index)\n const fullVarId = `${baseVarId}[${subs}]`\n this.varSpecs.set(fullVarId, {\n varIndex: v.index,\n subscriptIndices: subIndices\n })\n }\n } else {\n // The variable is not subscripted\n this.varSpecs.set(baseVarId, {\n varIndex: v.index\n })\n }\n\n // Mark this variable as visited\n baseVarIds.add(baseVarId)\n }\n }\n }\n\n /**\n * Return the `VarSpec` for the given variable ID, or undefined if there is no spec defined\n * in the listing for that variable.\n */\n getSpecForVarId(varId: VarId): VarSpec | undefined {\n return this.varSpecs.get(varId)\n }\n\n /**\n * Return the `VarSpec` for the given variable name, or undefined if there is no spec defined\n * in the listing for that variable.\n */\n getSpecForVarName(varName: VarName): VarSpec | undefined {\n const varId = sdeVarIdForVensimVarName(varName)\n return this.varSpecs.get(varId)\n }\n\n /**\n * Create a new `Outputs` instance that uses the same start/end years as the given \"normal\"\n * `Outputs` instance but is prepared for reading the specified internal variables from the model.\n *\n * @param normalOutputs The `Outputs` that is used to access normal output variables from the model.\n * @param varIds The variable IDs to include with the new `Outputs` instance.\n */\n deriveOutputs(normalOutputs: Outputs, varIds: OutputVarId[]): Outputs {\n // Look up a `VarSpec` for each variable ID\n const varSpecs: VarSpec[] = []\n for (const varId of varIds) {\n const varSpec = this.varSpecs.get(varId)\n if (varSpec !== undefined) {\n varSpecs.push(varSpec)\n } else {\n // TODO: Throw error or just log warning?\n console.warn(`WARNING: No output var spec found for id=${varId}`)\n }\n }\n\n // Create a new `Outputs` instance that accepts the internal variables\n const newOutputs = new Outputs(varIds, normalOutputs.startTime, normalOutputs.endTime, normalOutputs.saveFreq)\n newOutputs.varSpecs = varSpecs\n return newOutputs\n }\n}\n\n/**\n * Helper function that returns the base name of a variable without the subscripts.\n */\nfunction varIdWithoutSubscripts(fullVarId: string): string {\n const bracketIndex = fullVarId.indexOf('[')\n if (bracketIndex >= 0) {\n return fullVarId.substring(0, bracketIndex)\n } else {\n return fullVarId\n }\n}\n\n/**\n * Return the cartesian product of the given array of arrays.\n *\n * For example, if we have an array that lists out two dimensions:\n * [ ['a1','a2'], ['b1','b2','b3'] ]\n * this function will return all the combinations, e.g.:\n * [ ['a1', 'b1'], ['a1', 'b2'], ['a1', 'b3'], ['a2', 'b1'], ... ]\n *\n * This can be used in place of nested for loops and has the benefit of working\n * for multi-dimensional inputs.\n */\nfunction cartesianProductOf<T>(arr: T[][]): T[][] {\n // Implementation based on: https://stackoverflow.com/a/36234242\n return arr.reduce(\n (a, b) => {\n return a.map(x => b.map(y => x.concat([y]))).reduce((v, w) => v.concat(w), [])\n },\n [[]]\n )\n}\n\n/**\n * Helper function that converts a Vensim variable or subscript name\n * into a valid C identifier as used by SDE.\n * TODO: Import helper function from `compile` package instead\n */\nfunction sdeVarIdForVensimName(name: string): string {\n return (\n '_' +\n name\n .trim()\n .replace(/\"/g, '_')\n .replace(/\\s+!$/g, '!')\n .replace(/\\s/g, '_')\n .replace(/,/g, '_')\n .replace(/-/g, '_')\n .replace(/\\./g, '_')\n .replace(/\\$/g, '_')\n .replace(/'/g, '_')\n .replace(/&/g, '_')\n .replace(/%/g, '_')\n .replace(/\\//g, '_')\n .replace(/\\|/g, '_')\n .toLowerCase()\n )\n}\n\n/**\n * Helper function that converts a Vensim variable name (possibly containing\n * subscripts) into a valid C identifier as used by SDE.\n * TODO: Import helper function from `compile` package instead\n */\nfunction sdeVarIdForVensimVarName(varName: string): string {\n const m = varName.match(/([^[]+)(?:\\[([^\\]]+)\\])?/)\n if (!m) {\n throw new Error(`Invalid Vensim name: ${varName}`)\n }\n let id = sdeVarIdForVensimName(m[1])\n if (m[2]) {\n const subscripts = m[2].split(',').map(x => sdeVarIdForVensimName(x))\n id += `[${subscripts.join(',')}]`\n }\n\n return id\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport type { VarRef, VarSpec } from '../_shared'\nimport type { ModelListing } from '../model-listing'\n\n/**\n * Resolve the provided variable reference using the `ModelListing` and variable name\n * or identifier.\n *\n * - If `varRef` has a defined `varSpec`, it is assumed to be valid.\n * - Otherwise, if `varRef` has a defined `varId`, it will be used to locate the\n * corresponding `varSpec` in the provided listing.\n * - Otherwise, if `varRef` has a defined `varName`, it will be used to locate the\n * corresponding `varSpec` in the provided listing.\n *\n * If the `varSpec` is found, this will set the `varSpec` property on the provided `varRef`.\n * Otherwise, this will throw an error.\n *\n * @hidden This is not part of the public API; it is exposed here for internal\n * use only.\n *\n * @param listing The model listing.\n * @param varRef The variable reference.\n * @param varKind The kind of variable (e.g., \"lookup\"), used to build an error message.\n */\nexport function resolveVarRef(listing: ModelListing | undefined, varRef: VarRef, varKind: string): VarSpec {\n if (varRef.varSpec) {\n // We assume the spec is valid\n // TODO: Should we validate the spec here?\n return\n }\n\n if (listing === undefined) {\n throw new Error(\n `Unable to resolve ${varKind} variable references by name or identifier when model listing is unavailable`\n )\n }\n\n if (varRef.varId) {\n const varSpec = listing?.getSpecForVarId(varRef.varId)\n if (varSpec) {\n varRef.varSpec = varSpec\n } else {\n throw new Error(`Failed to resolve ${varKind} variable reference for varId=${varRef.varId}`)\n }\n } else {\n const varSpec = listing?.getSpecForVarName(varRef.varName)\n if (varSpec) {\n varRef.varSpec = varSpec\n } else {\n throw new Error(`Failed to resolve ${varKind} variable reference for varName='${varRef.varId}'`)\n }\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport {\n decodeLookups,\n encodeLookups,\n encodeVarIndices,\n getEncodedLookupBufferLengths,\n getEncodedVarIndicesLength\n} from '../_shared'\nimport type { InputValue, LookupDef, Outputs } from '../_shared'\nimport type { ModelListing } from '../model-listing'\nimport { resolveVarRef } from './resolve-var-ref'\nimport type { RunModelOptions } from './run-model-options'\nimport type { RunModelParams } from './run-model-params'\n\nconst headerLengthInElements = 16\nconst extrasLengthInElements = 1\n\ninterface Section<ArrayType> {\n /** The view on the section of the `encoded` buffer, or undefined if the section is empty. */\n view?: ArrayType\n\n /** The byte offset of the section. */\n offsetInBytes: number\n\n /** The length (in elements) of the section. */\n lengthInElements: number\n\n /**\n * Update the view for this section.\n */\n update(encoded: ArrayBuffer, offsetInBytes: number, lengthInElements: number): void\n}\n\nclass Int32Section implements Section<Int32Array> {\n view?: Int32Array\n offsetInBytes = 0\n lengthInElements = 0\n update(encoded: ArrayBuffer, offsetInBytes: number, lengthInElements: number): void {\n this.view = lengthInElements > 0 ? new Int32Array(encoded, offsetInBytes, lengthInElements) : undefined\n this.offsetInBytes = offsetInBytes\n this.lengthInElements = lengthInElements\n }\n}\n\nclass Float64Section implements Section<Float64Array> {\n view?: Float64Array\n offsetInBytes = 0\n lengthInElements = 0\n update(encoded: ArrayBuffer, offsetInBytes: number, lengthInElements: number): void {\n this.view = lengthInElements > 0 ? new Float64Array(encoded, offsetInBytes, lengthInElements) : undefined\n this.offsetInBytes = offsetInBytes\n this.lengthInElements = lengthInElements\n }\n}\n\n/**\n * An implementation of `RunModelParams` that copies the input and output arrays into a single,\n * combined buffer. This implementation is designed to work with an asynchronous `ModelRunner`\n * implementation because the buffer can be transferred to/from a Web Worker or Node.js worker\n * thread without copying (if it is marked `Transferable`).\n *\n * @hidden This is not yet exposed in the public API; it is currently only used by\n * the implementations of the `RunnableModel` interface.\n */\nexport class BufferedRunModelParams implements RunModelParams {\n /**\n * The array that holds all input and output values. This is grown as needed. The memory\n * layout of the buffer is as follows:\n * header\n * extras (holds elapsed time, etc)\n * inputs\n * outputs\n * outputIndices\n * lookups (data)\n * lookupIndices\n */\n private encoded: ArrayBuffer\n\n /**\n * The header section of the `encoded` buffer. The header declares the byte offset and length\n * (in elements) of each section of the buffer.\n */\n private readonly header = new Int32Section()\n\n /** The extras section of the `encoded` buffer (holds elapsed time, etc). */\n private readonly extras = new Float64Section()\n\n /** The inputs section of the `encoded` buffer. */\n private readonly inputs = new Float64Section()\n\n /** The outputs section of the `encoded` buffer. */\n private readonly outputs = new Float64Section()\n\n /** The output indices section of the `encoded` buffer. */\n private readonly outputIndices = new Int32Section()\n\n /** The lookup data section of the `encoded` buffer. */\n private readonly lookups = new Float64Section()\n\n /** The lookup indices section of the `encoded` buffer. */\n private readonly lookupIndices = new Int32Section()\n\n /**\n * @param listing The model listing that is used to locate a variable that is referenced by\n * name or identifier. If undefined, variables cannot be referenced by name or identifier,\n * and can only be referenced using a valid `VarSpec`.\n */\n constructor(private readonly listing?: ModelListing) {}\n\n /**\n * Return the encoded buffer from this instance, which can be passed to `updateFromEncodedBuffer`.\n */\n getEncodedBuffer(): ArrayBuffer {\n return this.encoded\n }\n\n // from RunModelParams interface\n getInputs(): Float64Array | undefined {\n return this.inputs.view\n }\n\n // from RunModelParams interface\n copyInputs(array: Float64Array | undefined, create: (numElements: number) => Float64Array): void {\n if (this.inputs.lengthInElements === 0) {\n // Note that the inputs section will be empty if the inputs parameter is empty,\n // so we can skip copying in this case\n return\n }\n\n // Allocate (or reallocate) an array, if needed\n if (array === undefined || array.length < this.inputs.lengthInElements) {\n array = create(this.inputs.lengthInElements)\n }\n\n // Copy from the internal buffer to the array\n array.set(this.inputs.view)\n }\n\n // from RunModelParams interface\n getOutputIndicesLength(): number {\n return this.outputIndices.lengthInElements\n }\n\n // from RunModelParams interface\n getOutputIndices(): Int32Array | undefined {\n return this.outputIndices.view\n }\n\n // from RunModelParams interface\n copyOutputIndices(array: Int32Array | undefined, create: (numElements: number) => Int32Array): void {\n if (this.outputIndices.lengthInElements === 0) {\n // Note that the output indices section can be empty if the output indices are\n // not provided, so we can skip copying in this case\n return\n }\n\n // Allocate (or reallocate) an array, if needed\n if (array === undefined || array.length < this.outputIndices.lengthInElements) {\n array = create(this.outputIndices.lengthInElements)\n }\n\n // Copy from the internal buffer to the array\n array.set(this.outputIndices.view)\n }\n\n // from RunModelParams interface\n getOutputsLength(): number {\n return this.outputs.lengthInElements\n }\n\n // from RunModelParams interface\n getOutputs(): Float64Array | undefined {\n return this.outputs.view\n }\n\n // from RunModelParams interface\n getOutputsObject(): Outputs | undefined {\n // This implementation does not keep a reference to the original `Outputs` instance,\n // so we return undefined here\n return undefined\n }\n\n // from RunModelParams interface\n storeOutputs(array: Float64Array): void {\n if (this.outputs.view === undefined) {\n return\n }\n\n // Copy from the given array to the internal buffer. Note that the given array\n // can be longer than the internal buffer. This can happen in the case where the\n // model has an outputs buffer already allocated that was sized to accommodate a\n // certain amount of outputs, and then a later model run used a smaller amount of\n // outputs. In this case, the model may choose to keep the reuse the buffer\n // rather than reallocate/shrink the buffer, so we need to copy a subset here.\n if (array.length > this.outputs.view.length) {\n this.outputs.view.set(array.subarray(0, this.outputs.view.length))\n } else {\n this.outputs.view.set(array)\n }\n }\n\n // from RunModelParams interface\n getLookups(): LookupDef[] | undefined {\n if (this.lookupIndices.lengthInElements === 0) {\n return undefined\n }\n\n // Reconstruct the `LookupDef` instances using the data from the lookup data and\n // indices buffers\n return decodeLookups(this.lookupIndices.view, this.lookups.view)\n }\n\n // from RunModelParams interface\n getElapsedTime(): number {\n return this.extras.view[0]\n }\n\n // from RunModelParams interface\n storeElapsedTime(elapsed: number): void {\n // Store elapsed time in the extras section\n this.extras.view[0] = elapsed\n }\n\n /**\n * Copy the outputs buffer to the given `Outputs` instance. This should be called\n * after the `runModel` call has completed so that the output values are copied from\n * the internal buffer to the `Outputs` instance that was passed to `runModel`.\n *\n * @param outputs The `Outputs` instance into which the output values will be copied.\n */\n finalizeOutputs(outputs: Outputs): void {\n // Copy the output values to the `Outputs` instance\n if (this.outputs.view) {\n outputs.updateFromBuffer(this.outputs.view, outputs.seriesLength)\n }\n\n // Store the elapsed time value in the `Outputs` instance\n outputs.runTimeInMillis = this.getElapsedTime()\n }\n\n /**\n * Update this instance using the parameters that are passed to a `runModel` call.\n *\n * @param inputs The model input values (must be in the same order as in the spec file).\n * @param outputs The structure into which the model outputs will be stored.\n * @param options Additional options that influence the model run.\n */\n updateFromParams(inputs: number[] | InputValue[], outputs: Outputs, options?: RunModelOptions): void {\n // Determine the number of elements in the input and output sections\n const inputsLengthInElements = inputs.length\n const outputsLengthInElements = outputs.varIds.length * outputs.seriesLength\n\n // Determine the number of elements in the output indices section\n let outputIndicesLengthInElements: number\n const outputVarSpecs = outputs.varSpecs\n if (outputVarSpecs !== undefined && outputVarSpecs.length > 0) {\n // Compute the required length of the output indices buffer\n outputIndicesLengthInElements = getEncodedVarIndicesLength(outputVarSpecs)\n } else {\n // Don't use the output indices buffer when output var specs are not provided\n outputIndicesLengthInElements = 0\n }\n\n // Determine the number of elements in the lookup data and indices sections\n let lookupsLengthInElements: number\n let lookupIndicesLengthInElements: number\n if (options?.lookups !== undefined && options.lookups.length > 0) {\n // Resolve the `varSpec` for each `LookupDef`. If the variable can be resolved, this\n // will fill in the `varSpec` for the `LookupDef`, otherwise it will throw an error.\n for (const lookupDef of options.lookups) {\n resolveVarRef(this.listing, lookupDef.varRef, 'lookup')\n }\n\n // Compute the required lengths\n const encodedLengths = getEncodedLookupBufferLengths(options.lookups)\n lookupsLengthInElements = encodedLengths.lookupsLength\n lookupIndicesLengthInElements = encodedLengths.lookupIndicesLength\n } else {\n // Don't use the lookup data and indices buffers when lookup overrides are not provided\n lookupsLengthInElements = 0\n lookupIndicesLengthInElements = 0\n }\n\n // Compute the byte offset and byte length of each section\n let byteOffset = 0\n function section(kind: 'float64' | 'int32', lengthInElements: number): number {\n // Start at the current byte offset\n const sectionOffsetInBytes = byteOffset\n\n // Compute the section length. We round up to ensure 8 byte alignment, which is needed in order\n // for each section's start offset to be aligned correctly.\n const bytesPerElement = kind === 'float64' ? Float64Array.BYTES_PER_ELEMENT : Int32Array.BYTES_PER_ELEMENT\n const requiredSectionLengthInBytes = Math.round(lengthInElements * bytesPerElement)\n const alignedSectionLengthInBytes = Math.ceil(requiredSectionLengthInBytes / 8) * 8\n byteOffset += alignedSectionLengthInBytes\n return sectionOffsetInBytes\n }\n const headerOffsetInBytes = section('int32', headerLengthInElements)\n const extrasOffsetInBytes = section('float64', extrasLengthInElements)\n const inputsOffsetInBytes = section('float64', inputsLengthInElements)\n const outputsOffsetInBytes = section('float64', outputsLengthInElements)\n const outputIndicesOffsetInBytes = section('int32', outputIndicesLengthInElements)\n const lookupsOffsetInBytes = section('float64', lookupsLengthInElements)\n const lookupIndicesOffsetInBytes = section('int32', lookupIndicesLengthInElements)\n\n // Get the total byte length\n const requiredLengthInBytes = byteOffset\n\n // Create or grow the buffer, if needed\n if (this.encoded === undefined || this.encoded.byteLength < requiredLengthInBytes) {\n // Add some extra space at the end of the buffer to allow for sections to grow a bit without\n // having to reallocate the entire buffer\n const totalLengthInBytes = Math.ceil(requiredLengthInBytes * 1.2)\n this.encoded = new ArrayBuffer(totalLengthInBytes)\n\n // Recreate the header view when the buffer changes\n this.header.update(this.encoded, headerOffsetInBytes, headerLengthInElements)\n }\n\n // Update the header\n const headerView = this.header.view\n let headerIndex = 0\n headerView[headerIndex++] = extrasOffsetInBytes\n headerView[headerIndex++] = extrasLengthInElements\n headerView[headerIndex++] = inputsOffsetInBytes\n headerView[headerIndex++] = inputsLengthInElements\n headerView[headerIndex++] = outputsOffsetInBytes\n headerView[headerIndex++] = outputsLengthInElements\n headerView[headerIndex++] = outputIndicesOffsetInBytes\n headerView[headerIndex++] = outputIndicesLengthInElements\n headerView[headerIndex++] = lookupsOffsetInBytes\n headerView[headerIndex++] = lookupsLengthInElements\n headerView[headerIndex++] = lookupIndicesOffsetInBytes\n headerView[headerIndex++] = lookupIndicesLengthInElements\n\n // Update the views\n // TODO: We can avoid recreating the views every time if buffer and section offset/length\n // haven't changed\n this.inputs.update(this.encoded, inputsOffsetInBytes, inputsLengthInElements)\n this.extras.update(this.encoded, extrasOffsetInBytes, extrasLengthInElements)\n this.outputs.update(this.encoded, outputsOffsetInBytes, outputsLengthInElements)\n this.outputIndices.update(this.encoded, outputIndicesOffsetInBytes, outputIndicesLengthInElements)\n this.lookups.update(this.encoded, lookupsOffsetInBytes, lookupsLengthInElements)\n this.lookupIndices.update(this.encoded, lookupIndicesOffsetInBytes, lookupIndicesLengthInElements)\n\n // Copy the input values into the internal buffer\n // TODO: Throw an error if inputs.length is less than number of inputs declared\n // in the spec (only in the case where useInputIndices is false)\n const inputsView = this.inputs.view\n for (let i = 0; i < inputs.length; i++) {\n // XXX: The `inputs` array type used to be declared as `InputValue[]`, so some users\n // may be relying on that, but it has now been simplified to `number[]`. For the time\n // being, we will allow for either type and choose which one depending on the shape of\n // the array elements.\n const input = inputs[i]\n if (typeof input === 'number') {\n inputsView[i] = input\n } else {\n inputsView[i] = input.get()\n }\n }\n\n // Copy the the output indices into the internal buffer, if needed\n if (this.outputIndices.view) {\n encodeVarIndices(outputVarSpecs, this.outputIndices.view)\n }\n\n // Copy the lookup data and indices into the internal buffers, if needed\n if (lookupIndicesLengthInElements > 0) {\n encodeLookups(options.lookups, this.lookupIndices.view, this.lookups.view)\n }\n }\n\n /**\n * Update this instance using the values contained in the encoded buffer from another\n * `BufferedRunModelParams` instance.\n *\n * @param buffer An encoded buffer returned by `getEncodedBuffer`.\n */\n updateFromEncodedBuffer(buffer: ArrayBuffer): void {\n // Verify that the buffer is long enough to contain the header section\n const headerLengthInBytes = headerLengthInElements * Int32Array.BYTES_PER_ELEMENT\n if (buffer.byteLength < headerLengthInBytes) {\n throw new Error('Buffer must be long enough to contain header section')\n }\n\n // Set the buffer\n this.encoded = buffer\n\n // Rebuild the header\n const headerOffsetInBytes = 0\n this.header.update(this.encoded, headerOffsetInBytes, headerLengthInElements)\n\n // Get the section offsets and lengths from the header\n const headerView = this.header.view\n let headerIndex = 0\n const extrasOffsetInBytes = headerView[headerIndex++]\n const extrasLengthInElements = headerView[headerIndex++]\n const inputsOffsetInBytes = headerView[headerIndex++]\n const inputsLengthInElements = headerView[headerIndex++]\n const outputsOffsetInBytes = headerView[headerIndex++]\n const outputsLengthInElements = headerView[headerIndex++]\n const outputIndicesOffsetInBytes = headerView[headerIndex++]\n const outputIndicesLengthInElements = headerView[headerIndex++]\n const lookupsOffsetInBytes = headerView[headerIndex++]\n const lookupsLengthInElements = headerView[headerIndex++]\n const lookupIndicesOffsetInBytes = headerView[headerIndex++]\n const lookupIndicesLengthInElements = headerView[headerIndex++]\n\n // Verify that the buffer is long enough to contain all sections\n const extrasLengthInBytes = extrasLengthInElements * Float64Array.BYTES_PER_ELEMENT\n const inputsLengthInBytes = inputsLengthInElements * Float64Array.BYTES_PER_ELEMENT\n const outputsLengthInBytes = outputsLengthInElements * Float64Array.BYTES_PER_ELEMENT\n const outputIndicesLengthInBytes = outputIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT\n const lookupsLengthInBytes = lookupsLengthInElements * Float64Array.BYTES_PER_ELEMENT\n const lookupIndicesLengthInBytes = lookupIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT\n const requiredLengthInBytes =\n headerLengthInBytes +\n extrasLengthInBytes +\n inputsLengthInBytes +\n outputsLengthInBytes +\n outputIndicesLengthInBytes +\n lookupsLengthInBytes +\n lookupIndicesLengthInBytes\n if (buffer.byteLength < requiredLengthInBytes) {\n throw new Error('Buffer must be long enough to contain sections declared in header')\n }\n\n // Rebuild the sections according to the section offsets and lengths in the header\n this.extras.update(this.encoded, extrasOffsetInBytes, extrasLengthInElements)\n this.inputs.update(this.encoded, inputsOffsetInBytes, inputsLengthInElements)\n this.outputs.update(this.encoded, outputsOffsetInBytes, outputsLengthInElements)\n this.outputIndices.update(this.encoded, outputIndicesOffsetInBytes, outputIndicesLengthInElements)\n this.lookups.update(this.encoded, lookupsOffsetInBytes, lookupsLengthInElements)\n this.lookupIndices.update(this.encoded, lookupIndicesOffsetInBytes, lookupIndicesLengthInElements)\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport type { InputValue, LookupDef, Outputs } from '../_shared'\nimport { encodeVarIndices, getEncodedVarIndicesLength } from '../_shared'\nimport type { ModelListing } from '../model-listing'\nimport { resolveVarRef } from './resolve-var-ref'\nimport type { RunModelOptions } from './run-model-options'\nimport type { RunModelParams } from './run-model-params'\n\n/**\n * An implementation of `RunModelParams` that keeps references to the `inputs` and\n * `outputs` parameters that are passed to the `runModel` function. This implementation\n * is best used with a synchronous `ModelRunner`.\n *\n * @hidden This is not yet exposed in the public API; it is currently only used by\n * the implementations of the `RunnableModel` interface.\n */\nexport class ReferencedRunModelParams implements RunModelParams {\n private inputs: number[] | InputValue[]\n private outputs: Outputs\n private outputsLengthInElements = 0\n private outputIndicesLengthInElements = 0\n private lookups: LookupDef[]\n\n /**\n * @param listing The model listing that is used to locate a variable that is referenced by\n * name or identifier. If undefined, variables cannot be referenced by name or identifier,\n * and can only be referenced using a valid `VarSpec`.\n */\n constructor(private readonly listing?: ModelListing) {}\n\n // from RunModelParams interface\n getInputs(): Float64Array | undefined {\n // This implementation does not keep a buffer of inputs, so we return undefined here\n return undefined\n }\n\n // from RunModelParams interface\n copyInputs(array: Float64Array | undefined, create: (numElements: number) => Float64Array): void {\n // Allocate (or reallocate) an array, if needed\n const inputsLengthInElements = this.inputs.length\n if (array === undefined || array.length < inputsLengthInElements) {\n array = create(inputsLengthInElements)\n }\n\n // Copy the input values into the provided array\n for (let i = 0; i < this.inputs.length; i++) {\n // XXX: The `inputs` array type used to be declared as `InputValue[]`, so some users\n // may be relying on that, but it has now been simplified to `number[]`. For the time\n // being, we will allow for either type and choose which one depending on the shape of\n // the array elements.\n const input = this.inputs[i]\n if (typeof input === 'number') {\n array[i] = input\n } else {\n array[i] = input.get()\n }\n }\n }\n\n // from RunModelParams interface\n getOutputIndicesLength(): number {\n return this.outputIndicesLengthInElements\n }\n\n // from RunModelParams interface\n getOutputIndices(): Int32Array | undefined {\n // This implementation does not keep a buffer of indices, so we return undefined here\n return undefined\n }\n\n // from RunModelParams interface\n copyOutputIndices(array: Int32Array | undefined, create: (numElements: number) => Int32Array): void {\n if (this.outputIndicesLengthInElements === 0) {\n return\n }\n\n // Allocate (or reallocate) an array, if needed\n if (array === undefined || array.length < this.outputIndicesLengthInElements) {\n array = create(this.outputIndicesLengthInElements)\n }\n\n // Copy the output indices to the provided array\n encodeVarIndices(this.outputs.varSpecs, array)\n }\n\n // from RunModelParams interface\n getOutputsLength(): number {\n return this.outputsLengthInElements\n }\n\n // from RunModelParams interface\n getOutputs(): Float64Array | undefined {\n // This implementation does not keep a buffer of outputs, so we return undefined here\n return undefined\n }\n\n // from RunModelParams interface\n getOutputsObject(): Outputs | undefined {\n return this.outputs\n }\n\n // from RunModelParams interface\n storeOutputs(array: Float64Array): void {\n // Update the `Outputs` instance with the values from the given array\n if (this.outputs) {\n const result = this.outputs.updateFromBuffer(array, this.outputs.seriesLength)\n if (result.isErr()) {\n throw new Error(`Failed to store outputs: ${result.error}`)\n }\n }\n }\n\n // from RunModelParams interface\n getLookups(): LookupDef[] | undefined {\n if (this.lookups !== undefined && this.lookups.length > 0) {\n return this.lookups\n } else {\n return undefined\n }\n }\n\n // from RunModelParams interface\n getElapsedTime(): number {\n return this.outputs?.runTimeInMillis\n }\n\n // from RunModelParams interface\n storeElapsedTime(elapsed: number): void {\n // Store the elapsed time value in the `Outputs` instance\n if (this.outputs) {\n this.outputs.runTimeInMillis = elapsed\n }\n }\n\n /**\n * Update this instance using the parameters that are passed to a `runModel` call.\n *\n * @param inputs The model input values (must be in the same order as in the spec file).\n * @param outputs The structure into which the model outputs will be stored.\n * @param options Additional options that influence the model run.\n */\n updateFromParams(inputs: number[] | InputValue[], outputs: Outputs, options?: RunModelOptions): void {\n // Save the latest parameters; these values will be accessed by the `RunnableModel`\n // on demand (e.g., in the `copyInputs` method)\n this.inputs = inputs\n this.outputs = outputs\n this.outputsLengthInElements = outputs.varIds.length * outputs.seriesLength\n this.lookups = options?.lookups\n\n if (this.lookups) {\n // Resolve the `varSpec` for each `LookupDef`. If the variable can be resolved, this\n // will fill in the `varSpec` for the `LookupDef`, otherwise it will throw an error.\n for (const lookupDef of this.lookups) {\n resolveVarRef(this.listing, lookupDef.varRef, 'lookup')\n }\n }\n\n // See if the output indices are needed\n const outputVarSpecs = outputs.varSpecs\n if (outputVarSpecs !== undefined && outputVarSpecs.length > 0) {\n // Compute the required length of the output indices buffer\n this.outputIndicesLengthInElements = getEncodedVarIndicesLength(outputVarSpecs)\n } else {\n // Don't use the output indices buffer when output var specs are not provided\n this.outputIndicesLengthInElements = 0\n }\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\n// This matches Vensim's definition of `:NA:`. It is also defined\n// with the same value in the generated `JsModel`, so make sure\n// these two values are the same.\nexport const _NA_ = -Number.MAX_VALUE\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { _NA_ } from './js-model-constants'\n\nexport type JsModelLookupMode = 'interpolate' | 'forward' | 'backward'\n\n/**\n * @hidden This is not yet part of the public API; for internal use only.\n */\nexport class JsModelLookup {\n /** The original data passed to the constructor. */\n private readonly originalData: number[] | Float64Array | undefined\n\n /** The size (i.e., number of pairs) of the original data. */\n private readonly originalSize: number\n\n /**\n * The dynamic data array. This will be undefined initially, and the array\n * will be allocated (or grown) by `setData`.\n */\n private dynamicData: Float64Array | undefined\n\n /** The size (i.e., number of pairs) of the dynamic data. */\n private dynamicSize: number\n\n /**\n * The active data array. This will be the same as either `originalData`\n * or `dynamicData`, depending on whether the lookup data is overridden\n * at runtime using `setData`.\n */\n private activeData: number[] | Float64Array | undefined\n\n /** The size (i.e., number of pairs) of the active data. */\n private activeSize: number\n\n /**\n * The inverted version of the active data array. This is allocated on demand\n * only in the case of `LOOKUP INVERT` function calls.\n */\n private invertedData?: number[]\n\n /**\n * The input value for the last hit. This is cached for performance so that we\n * can reduce the amount of linear searching in the common case where `LOOKUP`\n * input values are monotonically increasing.\n */\n private lastInput: number\n\n /** The index for the last hit (see `lastInput`). */\n private lastHitIndex: number\n\n /**\n * @param size The number of (x,y) pairs in the lookup.\n * @param data The lookup data, as (x,y) pairs. The length of the array must be\n * >= 2*n. Note that the data will be stored by reference, so if there is a chance\n * that the array will be reused or modified by other code, be sure to pass in a\n * copy of the array.\n */\n constructor(size: number, data: number[] | Float64Array | undefined) {\n // Note that we reference the provided data without copying (assumed to be owned elsewhere)\n if (data && data.length < size * 2) {\n throw new Error(`Lookup data array length must be >= 2*size (length=${data.length} size=${size}`)\n }\n\n this.originalData = data\n this.originalSize = size\n\n this.dynamicData = undefined\n this.dynamicSize = 0\n\n this.activeData = this.originalData\n this.activeSize = this.originalSize\n\n this.lastInput = Number.MAX_VALUE\n this.lastHitIndex = 0\n }\n\n /**\n * Set new data for this lookup instance, or restore the original data.\n *\n * If `data` is undefined, the original data that was supplied to the constructor will\n * be restored as the \"active\" data. Otherwise, `data` will be copied to an internal\n * data buffer, which will be the \"active\" data. If `size` is greater than the size\n * passed to previous calls, the internal data buffer will be grown as needed.\n *\n * @param size The number of (x,y) pairs in the lookup.\n * @param data The lookup data, as (x,y) pairs. The length of the array must be\n * >= 2*n. Note that the data will be copied into an internal data buffer, so it\n * is not necessary to defensively copy data before calling this method.\n */\n public setData(size: number, data: Float64Array | undefined): void {\n if (data) {\n if (data.length < size * 2) {\n throw new Error(`Lookup data array length must be >= 2*size (length=${data.length} size=${size}`)\n }\n\n // Allocate or grow the internal buffer as needed\n const dataLengthInElems = size * 2\n if (this.dynamicData === undefined || dataLengthInElems > this.dynamicData.length) {\n this.dynamicData = new Float64Array(dataLengthInElems)\n }\n\n // Copy the given lookup data into the internally managed buffer\n this.dynamicSize = size\n if (size > 0) {\n const subarray = data.subarray(0, dataLengthInElems)\n this.dynamicData.set(subarray)\n }\n\n // Set the dynamic data as the \"active\" data\n this.activeData = this.dynamicData\n this.activeSize = this.dynamicSize\n } else {\n // Restore the original data as the \"active\" data\n this.activeData = this.originalData\n this.activeSize = this.originalSize\n }\n\n // Clear the cached inverted data\n this.invertedData = undefined\n\n // Reset the cached \"last\" values to the initial values\n this.lastInput = Number.MAX_VALUE\n this.lastHitIndex = 0\n }\n\n public getValueForX(x: number, mode: JsModelLookupMode): number {\n return this.getValue(x, false, mode)\n }\n\n public getValueForY(y: number): number {\n if (this.invertedData === undefined) {\n // Invert the matrix and cache it\n const numValues = this.activeSize * 2\n const normalData = this.activeData\n const invertedData = Array(numValues)\n for (let i = 0; i < numValues; i += 2) {\n invertedData[i] = normalData[i + 1]\n invertedData[i + 1] = normalData[i]\n }\n this.invertedData = invertedData\n }\n return this.getValue(y, true, 'interpolate')\n }\n\n /**\n * Interpolate the y value from the array of (x,y) pairs.\n * NOTE: The x values are assumed to be monotonically increasing.\n */\n private getValue(input: number, useInvertedData: boolean, mode: JsModelLookupMode): number {\n if (this.activeSize === 0) {\n return _NA_\n }\n\n const data = useInvertedData ? this.invertedData : this.activeData\n const max = this.activeSize * 2\n\n // Use the cached values for improved lookup performance, except in the case\n // of `LOOKUP INVERT` (since it may not be accurate if calls flip back and forth\n // between inverted and non-inverted data)\n const useCachedValues = !useInvertedData\n let startIndex: number\n if (useCachedValues && input >= this.lastInput) {\n startIndex = this.lastHitIndex\n } else {\n startIndex = 0\n }\n\n for (let xi = startIndex; xi < max; xi += 2) {\n const x = data[xi]\n if (x >= input) {\n // We went past the input, or hit it exactly\n if (useCachedValues) {\n this.lastInput = input\n this.lastHitIndex = xi\n }\n\n if (xi === 0 || x === input) {\n // The input is less than the first x, or this x equals the input; return the\n // associated y without interpolation\n return data[xi + 1]\n }\n\n // Calculate the y value depending on the lookup mode\n switch (mode) {\n default:\n case 'interpolate': {\n // Interpolate along the line from the last (x,y)\n const last_x = data[xi - 2]\n const last_y = data[xi - 1]\n const y = data[xi + 1]\n const dx = x - last_x\n const dy = y - last_y\n return last_y + (dy / dx) * (input - last_x)\n }\n case 'forward':\n // Return the next y value without interpolating\n return data[xi + 1]\n case 'backward':\n // Return the previous y value without interpolating\n return data[xi - 1]\n }\n }\n }\n\n // The input is greater than all the x values, so return the high end of the range\n if (useCachedValues) {\n this.lastInput = input\n this.lastHitIndex = max\n }\n return data[max - 1]\n }\n\n /**\n * Return the most appropriate y value from the array of (x,y) pairs when\n * this instance is used to provide inputs for the `GAME` function.\n *\n * NOTE: The x values are assumed to be monotonically increasing.\n *\n * This method is similar to `getValueForX` in concept, except that this one\n * returns the provided `defaultValue` if the `time` parameter is earlier than\n * the first data point in the lookup. Also, this method always uses the\n * `backward` interpolation mode, meaning that it holds the \"current\" value\n * constant instead of interpolating.\n *\n * @param time The time that is used to select the data point that has an\n * `x` value less than or equal to the provided time.\n * @param defaultValue The value that is returned if this lookup is empty (has\n * no points) or if the provided time is earlier than the first data point.\n */\n public getValueForGameTime(time: number, defaultValue: number): number {\n if (this.activeSize <= 0) {\n // The lookup is empty, so return the default value\n return defaultValue\n }\n\n const x0 = this.activeData[0]\n if (time < x0) {\n // The provided time is earlier than the first data point, so return the\n // default value\n return defaultValue\n }\n\n // For all other cases, we can use `getValue` with `backward` mode\n return this.getValue(time, false, 'backward')\n }\n\n /**\n * Interpolate the y value from the array of (x,y) pairs.\n * NOTE: The x values are assumed to be monotonically increasing.\n *\n * This method is similar to `getValue` in concept, but Vensim produces results for\n * the `GET DATA BETWEEN TIMES` function that differ in unexpected ways from normal\n * lookup behavior, so we implement it as a separate method here.\n */\n public getValueBetweenTimes(input: number, mode: JsModelLookupMode): number {\n if (this.activeSize === 0) {\n return _NA_\n }\n\n const data = this.activeData\n const max = this.activeSize * 2\n\n switch (mode) {\n case 'forward': {\n // Vensim appears to round non-integral input values down to a whole number\n // when mode is 1 (look forward), so we will do the same\n input = Math.floor(input)\n for (let xi = 0; xi < max; xi += 2) {\n const x = data[xi]\n if (x >= input) {\n return data[xi + 1]\n }\n }\n return data[max - 1]\n }\n case 'backward': {\n // Vensim appears to round non-integral input values down to a whole number\n // when mode is -1 (hold backward), so we will do the same\n input = Math.floor(input)\n for (let xi = 2; xi < max; xi += 2) {\n const x = data[xi]\n if (x >= input) {\n return data[xi - 1]\n }\n }\n if (max >= 4) {\n return data[max - 3]\n } else {\n return data[1]\n }\n }\n case 'interpolate':\n default: {\n // NOTE: This function produces results that match Vensim output for GET DATA BETWEEN TIMES with a\n // mode of 0 (interpolate), but only when the input values are integral (whole numbers). If the\n // input value is fractional, Vensim produces bizarre/unexpected interpolated values.\n // TODO: For now we throw an error, but ideally we would match the Vensim results exactly.\n if (input - Math.floor(input) > 0) {\n let msg = `GET DATA BETWEEN TIMES was called with an input value (${input}) that has a fractional part. `\n msg += 'When mode is 0 (interpolate) and the input value is not a whole number, Vensim produces unexpected '\n msg += 'results that may differ from those produced by SDEverywhere.'\n throw new Error(msg)\n }\n for (let xi = 2; xi < max; xi += 2) {\n const x = data[xi]\n if (x >= input) {\n const last_x = data[xi - 2]\n const last_y = data[xi - 1]\n const y = data[xi + 1]\n const dx = x - last_x\n const dy = y - last_y\n return last_y + (dy / dx) * (input - last_x)\n }\n }\n return data[max - 1]\n }\n }\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { _NA_ } from './js-model-constants'\nimport { JsModelLookup, type JsModelLookupMode } from './js-model-lookup'\n\n// See XIDZ documentation for an explanation of this value:\n// https://www.vensim.com/documentation/fn_xidz.html\nconst EPSILON = 1e-6\n\n/**\n * Provides access to the minimal set of control parameters that are used in the\n * implementation of certain model functions.\n *\n * @hidden This is not yet part of the public API; for internal use by generated\n * `JsModel` implementations.\n */\nexport interface JsModelFunctionContext {\n timeStep: number\n currentTime: number\n}\n\n/**\n * Exposes all the model function implementations that are called by a `JsModel` at runtime.\n *\n * @hidden This is not yet part of the public API; for internal use by generated\n * `JsModel` implementations.\n */\nexport interface JsModelFunctions {\n setContext(context: JsModelFunctionContext): void\n\n ABS(x: number): number\n ARCCOS(x: number): number\n ARCSIN(x: number): number\n ARCTAN(x: number): number\n COS(x: number): number\n EXP(x: number): number\n GAME(inputs: JsModelLookup, x: number): number\n // TODO\n // GAMMA_LN(x: number): number\n INTEG(value: number, rate: number): number\n INTEGER(x: number): number\n LN(x: number): number\n MAX(x: number, y: number): number\n MIN(x: number, y: number): number\n MODULO(x: number, y: number): number\n POW(x: number, y: number): number\n POWER(x: number, y: number): number\n PULSE(start: number, width: number): number\n PULSE_TRAIN(start: number, width: number, interval: number, end: number): number\n QUANTUM(x: number, y: number): number\n RAMP(slope: number, startTime: number, endTime: number): number\n SIN(x: number): number\n SQRT(x: number): number\n STEP(height: number, stepTime: number): number\n TAN(x: number): number\n VECTOR_SORT_ORDER(vector: number[], size: number, direction: number): number[]\n XIDZ(a: number, b: number, x: number): number\n ZIDZ(a: number, b: number): number\n\n createLookup(size: number, data: number[] | Float64Array): JsModelLookup\n LOOKUP(lookup: JsModelLookup, x: number): number\n LOOKUP_FORWARD(lookup: JsModelLookup, x: number): number\n LOOKUP_BACKWARD(lookup: JsModelLookup, x: number): number\n LOOKUP_INVERT(lookup: JsModelLookup, y: number): number\n WITH_LOOKUP(x: number, lookup: JsModelLookup): number\n GET_DATA_BETWEEN_TIMES(lookup: JsModelLookup, x: number, mode: number): number\n\n // TODO\n // createFixedDelay(delayTime: number, initialValue: number): FixedDelay\n // DELAY_FIXED(input: number, fixedDelay: FixedDelay): number\n\n // TODO\n // createDepreciation(dtime: number, initialValue: number): Depreciation\n // DEPRECIATE_STRAIGHTLINE(input: number, depreciation: Depreciation): number\n}\n\n/**\n * Returns a default implementation of the `JsModelFunctions` interface. If needed,\n * you can provide a custom implementation of any exposed function by overriding\n * (setting) a new function implementation on the returned instance.\n *\n * @hidden This is not yet part of the public API; for internal use by generated\n * `JsModel` implementations.\n */\nexport function getJsModelFunctions(): JsModelFunctions {\n let ctx: JsModelFunctionContext\n\n // The C implementation of `_VECTOR_SORT_ORDER` reuses an array, so we\n // will do the same for now (one reused array per size)\n const cachedVectors: Map<number, number[]> = new Map()\n const cachedSortVectors: Map<number, { x: number; ind: number }[]> = new Map()\n\n return {\n setContext(context: JsModelFunctionContext) {\n ctx = context\n },\n\n ABS(x: number): number {\n return Math.abs(x)\n },\n\n ARCCOS(x: number): number {\n return Math.acos(x)\n },\n\n ARCSIN(x: number): number {\n return Math.asin(x)\n },\n\n ARCTAN(x: number): number {\n return Math.atan(x)\n },\n\n COS(x: number): number {\n return Math.cos(x)\n },\n\n EXP(x: number): number {\n return Math.exp(x)\n },\n\n GAME(inputs: JsModelLookup, x: number): number {\n return inputs ? inputs.getValueForGameTime(ctx.currentTime, x) : x\n },\n\n // GAMMA_LN(): number {\n // throw new Error('GAMMA_LN function not yet implemented for JS target')\n // },\n\n INTEG(value: number, rate: number): number {\n return value + rate * ctx.timeStep\n },\n\n INTEGER(x: number): number {\n return Math.trunc(x)\n },\n\n LN(x: number): number {\n return Math.log(x)\n },\n\n MAX(x: number, y: number): number {\n return Math.max(x, y)\n },\n\n MIN(x: number, y: number): number {\n return Math.min(x, y)\n },\n\n MODULO(x: number, y: number): number {\n return x % y\n },\n\n POW(x: number, y: number): number {\n return Math.pow(x, y)\n },\n\n POWER(x: number, y: number): number {\n return Math.pow(x, y)\n },\n\n PULSE(start: number, width: number): number {\n return pulse(ctx, start, width)\n },\n\n PULSE_TRAIN(start: number, width: number, interval: number, end: number): number {\n const n = Math.floor((end - start) / interval)\n for (let k = 0; k <= n; k++) {\n if (ctx.currentTime <= end && pulse(ctx, start + k * interval, width)) {\n return 1.0\n }\n }\n return 0.0\n },\n\n QUANTUM(x: number, y: number): number {\n return y <= 0 ? x : y * Math.trunc(x / y)\n },\n\n RAMP(slope: number, startTime: number, endTime: number): number {\n // Return 0 until the start time is exceeded.\n // Interpolate from start time to end time.\n // Hold at the end time value.\n // Allow start time > end time.\n if (ctx.currentTime > startTime) {\n if (ctx.currentTime < endTime || startTime > endTime) {\n return slope * (ctx.currentTime - startTime)\n } else {\n return slope * (endTime - startTime)\n }\n } else {\n return 0.0\n }\n },\n\n SIN(x: number): number {\n return Math.sin(x)\n },\n\n SQRT(x: number): number {\n return Math.sqrt(x)\n },\n\n STEP(height: number, stepTime: number): number {\n return ctx.currentTime + ctx.timeStep / 2.0 > stepTime ? height : 0.0\n },\n\n TAN(x: number): number {\n return Math.tan(x)\n },\n\n VECTOR_SORT_ORDER(vector: number[], size: number, direction: number): number[] {\n // Validate arguments\n if (size > vector.length) {\n throw new Error(`VECTOR SORT ORDER input vector length (${vector.length}) must be >= size (${size})`)\n }\n\n // Get a cached sort vector\n let sortVector = cachedSortVectors.get(size)\n if (sortVector === undefined) {\n sortVector = Array(size)\n for (let i = 0; i < size; i++) {\n sortVector[i] = { x: 0, ind: 0 }\n }\n cachedSortVectors.set(size, sortVector)\n }\n\n // Get a cached output array\n let outArray = cachedVectors.get(size)\n if (outArray === undefined) {\n outArray = Array(size)\n cachedVectors.set(size, outArray)\n }\n\n // Prepare for sorting\n for (let i = 0; i < size; i++) {\n sortVector[i].x = vector[i]\n sortVector[i].ind = i\n }\n\n // Sort in place\n const sortOrder = direction > 0 ? 1 : -1\n sortVector.sort((a, b) => {\n let result: number\n if (a.x < b.x) {\n result = -1\n } else if (a.x > b.x) {\n result = 1\n } else {\n result = 0\n }\n return result * sortOrder\n })\n\n // Copy the sorted index values into the output array\n for (let i = 0; i < size; i++) {\n outArray[i] = sortVector[i].ind\n }\n\n return outArray\n },\n\n XIDZ(a: number, b: number, x: number): number {\n return Math.abs(b) < EPSILON ? x : a / b\n },\n\n ZIDZ(a: number, b: number): number {\n if (Math.abs(b) < EPSILON) {\n return 0.0\n } else {\n return a / b\n }\n },\n\n //\n // Lookup functions\n //\n\n createLookup(size: number, data: number[] | Float64Array): JsModelLookup {\n return new JsModelLookup(size, data)\n },\n\n LOOKUP(lookup: JsModelLookup, x: number): number {\n return lookup ? lookup.getValueForX(x, 'interpolate') : _NA_\n },\n\n LOOKUP_FORWARD(lookup: JsModelLookup, x: number): number {\n return lookup ? lookup.getValueForX(x, 'forward') : _NA_\n },\n\n LOOKUP_BACKWARD(lookup: JsModelLookup, x: number): number {\n return lookup ? lookup.getValueForX(x, 'backward') : _NA_\n },\n\n LOOKUP_INVERT(lookup: JsModelLookup, y: number): number {\n return lookup ? lookup.getValueForY(y) : _NA_\n },\n\n WITH_LOOKUP(x: number, lookup: JsModelLookup): number {\n return lookup ? lookup.getValueForX(x, 'interpolate') : _NA_\n },\n\n GET_DATA_BETWEEN_TIMES(lookup: JsModelLookup, x: number, mode: number): number {\n let lookupMode: JsModelLookupMode\n if (mode >= 1) {\n lookupMode = 'forward'\n } else if (mode <= -1) {\n lookupMode = 'backward'\n } else {\n lookupMode = 'interpolate'\n }\n return lookup ? lookup.getValueBetweenTimes(x, lookupMode) : _NA_\n }\n }\n}\n\nfunction pulse(ctx: JsModelFunctionContext, start: number, width: number): number {\n const timePlus = ctx.currentTime + ctx.timeStep / 2.0\n if (width === 0.0) {\n width = ctx.timeStep\n }\n return timePlus > start && timePlus < start + width ? 1.0 : 0.0\n}\n","// Copyright (c) 2021-2022 Climate Interactive / New Venture Fund\n\nlet isWeb: boolean\n\n/**\n * Return a timestamp that can be passed to `perfElapsed` for calculating the elapsed\n * time of an operation.\n *\n * @hidden This is not part of the public API; exposed only for use in performance testing.\n */\nexport function perfNow(): unknown {\n // Note that `self` resolves to the window (in browser context) or the worker global scope\n // (in a Web Worker context)\n if (isWeb === undefined) {\n isWeb = typeof self !== 'undefined' && self?.performance !== undefined\n }\n if (isWeb) {\n return self.performance.now()\n } else {\n // XXX: We only use `process` in two places; we bypass type checking instead of\n // setting up type declarations\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return process?.hrtime()\n }\n}\n\n/**\n * Return the elapsed time between the given timestamp (created by `perfNow`) and now.\n *\n * @hidden This is not part of the public API; exposed only for use in performance testing.\n */\nexport function perfElapsed(t0: unknown): number {\n if (isWeb) {\n const t1 = self.performance.now()\n return (t1 as number) - (t0 as number)\n } else {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const elapsed = process.hrtime(t0) as number[]\n // Convert from nanoseconds to milliseconds\n return (elapsed[0] * 1000000000 + elapsed[1]) / 1000000\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport type { LookupDef, OutputVarId } from '../_shared'\nimport type { ModelListing } from '../model-listing'\nimport { perfElapsed, perfNow } from '../perf'\nimport type { RunModelParams } from './run-model-params'\nimport type { RunnableModel } from './runnable-model'\n\n/**\n * @hidden This is not part of the public API; for internal use only.\n */\nexport type OnRunModelFunc = (\n inputs: Float64Array | undefined,\n outputs: Float64Array,\n options?: {\n outputIndices?: Int32Array\n lookups?: LookupDef[]\n }\n) => void\n\n/**\n * A base implementation of the `RunnableModel` interface that takes care\n * of managing internal buffers and copying values to/from the `RunModelParams`.\n *\n * The `onRunModel` function allows an implementation of the core model run loop\n * to deal with typed arrays only.\n *\n * @hidden This is not part of the public API; for internal use only.\n */\nexport class BaseRunnableModel implements RunnableModel {\n public readonly startTime: number\n public readonly endTime: number\n public readonly saveFreq: number\n public readonly numSavePoints: number\n public readonly outputVarIds: OutputVarId[]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public readonly modelListing?: /*ModelListingSpecs*/ any\n\n private readonly onRunModel: OnRunModelFunc\n\n private inputs: Float64Array\n private outputs: Float64Array\n private outputIndices: Int32Array\n\n constructor(options: {\n startTime: number\n endTime: number\n saveFreq: number\n numSavePoints: number\n outputVarIds: OutputVarId[]\n modelListing?: ModelListing\n onRunModel: OnRunModelFunc\n }) {\n this.startTime = options.startTime\n this.endTime = options.endTime\n this.saveFreq = options.saveFreq\n this.numSavePoints = options.numSavePoints\n this.outputVarIds = options.outputVarIds\n this.modelListing = options.modelListing\n this.onRunModel = options.onRunModel\n }\n\n // from RunnableModel interface\n runModel(params: RunModelParams): void {\n // Get a reference to the inputs array, or copy into a new one if needed\n let inputsArray = params.getInputs()\n if (inputsArray === undefined) {\n // The inputs are not accessible in an array, so copy into a new array that we control\n params.copyInputs(this.inputs, numElements => {\n this.inputs = new Float64Array(numElements)\n return this.inputs\n })\n inputsArray = this.inputs\n }\n\n // Get a reference to the output indices array, or copy into a new one if needed\n let outputIndicesArray = params.getOutputIndices()\n if (outputIndicesArray === undefined && params.getOutputIndicesLength() > 0) {\n // The indices are not accessible in an array, so copy into a new array that we control\n params.copyOutputIndices(this.outputIndices, numElements => {\n this.outputIndices = new Int32Array(numElements)\n return this.outputIndices\n })\n outputIndicesArray = this.outputIndices\n }\n\n // Allocate (or reallocate) the array that will receive the outputs\n // TODO: If `params.getOutputsObject` returns an `Outputs` instance, we can\n // write directly into that instead of creating a separate array\n const outputsLengthInElements = params.getOutputsLength()\n if (this.outputs === undefined || this.outputs.length < outputsLengthInElements) {\n this.outputs = new Float64Array(outputsLengthInElements)\n }\n const outputsArray = this.outputs\n\n // Run the model\n const t0 = perfNow()\n this.onRunModel?.(inputsArray, outputsArray, {\n outputIndices: outputIndicesArray,\n lookups: params.getLookups()\n })\n const elapsed = perfElapsed(t0)\n\n // Copy the outputs that were stored into our array back to the `RunModelParams`\n params.storeOutputs(outputsArray)\n\n // Store the elapsed time in the `RunModelParams`\n params.storeElapsedTime(elapsed)\n }\n\n // from RunnableModel interface\n terminate(): void {\n // No-op\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { type LookupDef, type VarSpec } from '../_shared'\nimport type { RunnableModel } from '../runnable-model'\nimport { BaseRunnableModel } from '../runnable-model/base-runnable-model'\n\nimport { getJsModelFunctions, type JsModelFunctionContext, type JsModelFunctions } from './js-model-functions'\n\n/**\n * An interface that exposes the functions of a JavaScript model generated by the\n * SDEverywhere transpiler. This allows for running the model with a given set of\n * input values, which will produce a set of output values.\n *\n * This is a low-level interface that most developers will not need to interact\n * with directly. Developers should instead use the `ModelRunner` interface to\n * interact with a generated model. Use `createSynchronousModelRunner` to create\n * a synchronous `ModelRunner`, or `spawnAsyncModelRunner` to create an asynchronous\n * `ModelRunner`.\n *\n * @beta NOTE: The properties and methods exposed in this interface are meant for\n * internal use only, and are subject to change in coordination with the code\n * generated by the `@sdeverywhere/compile` package.\n */\nexport interface JsModel {\n readonly kind: 'js'\n\n readonly outputVarIds: string[]\n readonly outputVarNames: string[]\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly modelListing?: /*ModelListingSpecs*/ any\n\n /** @hidden */\n getInitialTime(): number\n /** @hidden */\n getFinalTime(): number\n /** @hidden */\n getTimeStep(): number\n /** @hidden */\n getSaveFreq(): number\n\n /** @hidden */\n getModelFunctions(): JsModelFunctions\n /** @hidden */\n setModelFunctions(functions: JsModelFunctions): void\n\n /** @hidden */\n setTime(time: number): void\n /** @hidden */\n setInputs(inputValue: (index: number) => number): void\n\n /** @hidden */\n setLookup(varSpec: VarSpec, points: Float64Array | undefined): void\n\n /** @hidden */\n storeOutputs(storeValue: (value: number) => void): void\n /** @hidden */\n storeOutput(varSpec: VarSpec, storeValue: (value: number) => void): void\n\n /** @hidden */\n initConstants(): void\n /** @hidden */\n initLevels(): void\n /** @hidden */\n evalAux(): void\n /** @hidden */\n evalLevels(): void\n}\n\n/**\n * Create a `RunnableModel` from a given `JsModel` that was generated by the\n * SDEverywhere transpiler.\n *\n * @hidden This is not part of the public API; only the top-level `createRunnableModel`\n * function is exposed in the public API.\n */\nexport function initJsModel(model: JsModel): RunnableModel {\n // Install the default implementation of model functions if not already provided\n let fns = model.getModelFunctions()\n if (fns === undefined) {\n fns = getJsModelFunctions()\n model.setModelFunctions(fns)\n }\n\n // Get the control variable values. Once the first 4 control variables are known,\n // we can compute `numSavePoints` here.\n const initialTime = model.getInitialTime()\n const finalTime = model.getFinalTime()\n const timeStep = model.getTimeStep()\n const saveFreq = model.getSaveFreq()\n const numSavePoints = Math.round((finalTime - initialTime) / saveFreq) + 1\n\n return new BaseRunnableModel({\n startTime: initialTime,\n endTime: finalTime,\n saveFreq: saveFreq,\n numSavePoints,\n outputVarIds: model.outputVarIds,\n modelListing: model.modelListing,\n onRunModel: (inputs, outputs, options) => {\n runJsModel(\n model,\n initialTime,\n finalTime,\n timeStep,\n saveFreq,\n numSavePoints,\n inputs,\n outputs,\n options?.outputIndices,\n options?.lookups,\n undefined\n )\n }\n })\n}\n\nfunction runJsModel(\n model: JsModel,\n initialTime: number,\n finalTime: number,\n timeStep: number,\n saveFreq: number,\n numSavePoints: number,\n inputs: Float64Array | undefined,\n outputs: Float64Array,\n outputIndices: Int32Array | undefined,\n lookups: LookupDef[] | undefined,\n stopAfterTime: number | undefined\n): void {\n // Initialize time with the required `INITIAL TIME` control variable\n let time = initialTime\n model.setTime(time)\n\n // Configure the functions. The function context makes the control variable values\n // available to certain functions that depend on those values.\n const fnContext: JsModelFunctionContext = {\n timeStep,\n currentTime: time\n }\n model.getModelFunctions().setContext(fnContext)\n\n // Initialize constants to their default values\n model.initConstants()\n\n // Apply lookup overrides, if provided\n if (lookups !== undefined) {\n for (const lookupDef of lookups) {\n model.setLookup(lookupDef.varRef.varSpec, lookupDef.points)\n }\n }\n\n if (inputs?.length > 0) {\n // Set the user-defined input values. This needs to happen after `initConstants`\n // since the input values will override the default constant values.\n model.setInputs(index => inputs[index])\n }\n\n // Initialize level variables\n model.initLevels()\n\n // Set up a run loop using a fixed number of time steps\n // TODO: For now we run up to and including `finalTime` (even when `stopAfterTime`\n // is defined), storing undefined for values after passing the `stopAfterTime`.\n // We should change this to instead stop running the model after passing the\n // `stopAfterTime` and have a simpler loop that stores undefined values.\n const lastStep = Math.round((finalTime - initialTime) / timeStep)\n const stopTime = stopAfterTime !== undefined ? stopAfterTime : finalTime\n let step = 0\n let savePointIndex = 0\n let outputVarIndex = 0\n while (step <= lastStep) {\n // Evaluate aux variables\n model.evalAux()\n\n if (time % saveFreq < 1e-6) {\n outputVarIndex = 0\n const storeValue = (value: number) => {\n // Write each value into the preallocated buffer; each variable has a \"row\" that\n // contains `numSavePoints` values, one value for each save point\n const outputBufferIndex = outputVarIndex * numSavePoints + savePointIndex\n outputs[outputBufferIndex] = time <= stopTime ? value : undefined\n outputVarIndex++\n }\n if (outputIndices !== undefined) {\n // Store the outputs as specified in the current output indices buffer\n let indexBufferOffset = 0\n const outputCount = outputIndices[indexBufferOffset++]\n for (let i = 0; i < outputCount; i++) {\n const varIndex = outputIndices[indexBufferOffset++]\n const subCount = outputIndices[indexBufferOffset++]\n let subscriptIndices: Int32Array\n if (subCount > 0) {\n subscriptIndices = outputIndices.subarray(indexBufferOffset, indexBufferOffset + subCount)\n indexBufferOffset += subCount\n }\n const varSpec: VarSpec = {\n varIndex,\n subscriptIndices\n }\n model.storeOutput(varSpec, storeValue)\n }\n } else {\n // Store the normal outputs\n // TODO: In the case of a synchronous `ModelRunner`, we can access the `Outputs`\n // instance directly and write directly into that instead of into a typed array.\n // We can update `BaseRunnableModel` to expose the `Outputs` instance, and if it\n // is defined, we can use the following code to write into the `Outputs`.\n // if (outputsInstance) {\n // model.storeOutputs(value => {\n // // Write each value into the preallocated buffer; each variable has a \"row\" that\n // // contains `numSavePoints` values, one value for each save point\n // const series = outputsInstance.varSeries[outputVarIndex]\n // series.points[savePointIndex].y = value\n // outputVarIndex++\n // })\n // } else {\n model.storeOutputs(storeValue)\n // }\n }\n savePointIndex++\n }\n\n if (step === lastStep) {\n // This is the last step, so we are done\n break\n }\n\n // Propagate levels for the next time step\n model.evalLevels()\n\n // Advance time by one step\n time += timeStep\n model.setTime(time)\n fnContext.currentTime = time\n step++\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { Outputs } from '../_shared'\nimport { ReferencedRunModelParams } from '../runnable-model'\nimport { initJsModel, type JsModel } from './js-model'\n\n/**\n * Run the given model synchronously and log the output values to the console in\n * TSV (tab-separated values) format.\n *\n * @hidden This is mainly intended for use in implementing the `sde exec` command,\n * so isn't exposed in the public API at this time.\n *\n * @param jsModel A `JsModel` instance.\n */\nexport function execJsModel(jsModel: JsModel): void {\n // Create a `RunnableModel` from the given `JsModel`\n const runnableModel = initJsModel(jsModel)\n\n // For now we only support running the model with default parameters (no user-specified\n // inputs). By using an empty array here, the model will skip the `setInputs` step.\n const inputs: number[] = []\n\n // Create the `Outputs` instance into which the model outputs will be stored\n const outputVarIds = jsModel.outputVarIds\n const startTime = jsModel.getInitialTime()\n const endTime = jsModel.getFinalTime()\n const saveFreq = jsModel.getSaveFreq()\n const outputs = new Outputs(outputVarIds, startTime, endTime, saveFreq)\n\n // Run the model\n const params = new ReferencedRunModelParams()\n params.updateFromParams(inputs, outputs)\n runnableModel.runModel(params)\n\n // Write the header (escaping quotes as needed)\n const outputVarNames = jsModel.outputVarNames.map(name => name.replace(/\"/g, '\\\\\"'))\n const header = outputVarNames.join('\\t')\n console.log(header)\n\n // Write tab-delimited output data, one line per output time step\n for (let i = 0; i < outputs.seriesLength; i++) {\n const rowValues = []\n for (const series of outputs.varSeries) {\n rowValues.push(series.points[i].y)\n }\n console.log(rowValues.join('\\t'))\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport type { OutputVarId, VarId, VarSpec } from '../../_shared'\nimport { ModelListing } from '../../model-listing'\nimport type { JsModel } from '../js-model'\nimport type { JsModelFunctions } from '../js-model-functions'\nimport { JsModelLookup } from '../js-model-lookup'\n\n/**\n * @hidden This type is not part of the public API; it is exposed only for use in\n * tests in the runtime-async package.\n */\nexport type OnEvalAux = (vars: Map<VarId, number>, lookups: Map<VarId, JsModelLookup>) => void\n\n/**\n * @hidden This type is not part of the public API; it is exposed only for use in\n * tests in the runtime-async package.\n */\nexport class MockJsModel implements JsModel {\n // from JsModel interface\n public readonly kind = 'js'\n\n // from JsModel interface\n public readonly outputVarIds: OutputVarId[]\n\n // from JsModel interface\n public readonly outputVarNames: OutputVarId[]\n\n // from JsModel interface\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public readonly modelListing?: /*ModelListingSpecs*/ any\n private readonly internalListing?: ModelListing\n\n private readonly initialTime: number\n private readonly finalTime: number\n\n private readonly vars: Map<VarId, number> = new Map()\n private readonly lookups: Map<VarId, JsModelLookup> = new Map()\n private fns: JsModelFunctions\n\n public readonly onEvalAux: OnEvalAux\n\n constructor(options: {\n initialTime: number\n finalTime: number\n outputVarIds: OutputVarId[]\n listingJson?: string\n onEvalAux: OnEvalAux\n }) {\n this.outputVarIds = options.outputVarIds\n this.outputVarNames = options.outputVarIds\n this.initialTime = options.initialTime\n this.finalTime = options.finalTime\n this.outputVarIds = options.outputVarIds\n if (options.listingJson) {\n this.modelListing = JSON.parse(options.listingJson)\n this.internalListing = new ModelListing(this.modelListing)\n }\n this.onEvalAux = options.onEvalAux\n }\n\n varIdForSpec(varSpec: VarSpec): VarId {\n for (const [listingVarId, listingSpec] of this.internalListing.varSpecs) {\n // TODO: This doesn't compare subscripts yet\n if (listingSpec.varIndex === varSpec.varIndex) {\n return listingVarId\n }\n }\n return undefined\n }\n\n // from JsModel interface\n getInitialTime(): number {\n return this.initialTime\n }\n\n // from JsModel interface\n getFinalTime(): number {\n return this.finalTime\n }\n\n // from JsModel interface\n getTimeStep(): number {\n return 1\n }\n\n // from JsModel interface\n getSaveFreq(): number {\n return 1\n }\n\n // from JsModel interface\n getModelFunctions(): JsModelFunctions {\n return this.fns\n }\n\n // from JsModel interface\n setModelFunctions(fns: JsModelFunctions) {\n this.fns = fns\n }\n\n // from JsModel interface\n setTime(time: number): void {\n this.vars.set('_time', time)\n }\n\n // from JsModel interface\n setInputs(): void {\n // TODO\n }\n\n // from JsModel interface\n setLookup(varSpec: VarSpec, points: Float64Array | undefined): void {\n const varId = this.varIdForSpec(varSpec)\n if (varId === undefined) {\n throw new Error(`No lookup variable found for spec ${varSpec}`)\n }\n const numPoints = points ? points.length / 2 : 0\n this.lookups.set(varId, new JsModelLookup(numPoints, points))\n }\n\n // from JsModel interface\n storeOutputs(storeValue: (value: number) => void): void {\n for (const varId of this.outputVarIds) {\n storeValue(this.vars.get(varId))\n }\n }\n\n // from JsModel interface\n storeOutput(varSpec: VarSpec, storeValue: (value: number) => void): void {\n const varId = this.varIdForSpec(varSpec)\n if (varId === undefined) {\n throw new Error(`No output variable found for spec ${varSpec}`)\n }\n storeValue(this.vars.get(varId))\n }\n\n // from JsModel interface\n initConstants(): void {}\n\n // from JsModel interface\n initLevels(): void {}\n\n // from JsModel interface\n evalAux(): void {\n this.onEvalAux?.(this.vars, this.lookups)\n }\n\n // from JsModel interface\n evalLevels(): void {}\n}\n","// Copyright (c) 2020-2022 Climate Interactive / New Venture Fund\n\nimport type { WasmModule } from './wasm-module'\n\n/**\n * Wraps a `WebAssembly.Memory` buffer allocated on the wasm heap.\n *\n * When this is used synchronously (in the browser's normal JavaScript thread),\n * the client can use `getArrayView` to write directly into the underlying memory.\n *\n * Note, however, that `WebAssembly.Memory` buffers cannot be transferred to/from\n * a Web Worker. When using this class in a worker thread, create a separate\n * `Float64Array` that can be transferred between the worker and the client running\n * in the browser's normal JS thread, and then use `getArrayView` to copy into and\n * out of the wasm buffer.\n *\n * @hidden For internal use only.\n */\nexport class WasmBuffer<ArrType> {\n /**\n * @param wasmModule The `WasmModule` used to initialize the memory.\n * @param numElements The number of elements in the buffer.\n * @param byteOffset The byte offset within the wasm heap.\n * @param heapArray The array view on the underlying heap buffer.\n */\n constructor(\n private readonly wasmModule: WasmModule,\n public numElements: number,\n private byteOffset: number,\n private heapArray: ArrType\n ) {}\n\n /**\n * @return An `ArrType` view on the underlying heap buffer.\n */\n getArrayView(): ArrType {\n return this.heapArray\n }\n\n /**\n * @return The raw address of the underlying heap buffer.\n * @hidden This is intended for use by `WasmModel` only.\n */\n getAddress(): number {\n return this.byteOffset\n }\n\n /**\n * Dispose the buffer by freeing the allocated heap memory.\n */\n dispose(): void {\n if (this.heapArray) {\n this.wasmModule._free?.(this.byteOffset)\n this.numElements = undefined\n this.heapArray = undefined\n this.byteOffset = undefined\n }\n }\n}\n\n/**\n * Return a `WasmBuffer` that holds int32 elements.\n *\n * @hidden For internal use only.\n *\n * @param wasmModule The `WasmModule` used to initialize the memory.\n * @param numElements The number of elements in the buffer.\n */\nexport function createInt32WasmBuffer(wasmModule: WasmModule, numElements: number): WasmBuffer<Int32Array> {\n const elemSizeInBytes = 4\n const lengthInBytes = numElements * elemSizeInBytes\n const byteOffset = wasmModule._malloc(lengthInBytes)\n const elemOffset = byteOffset / elemSizeInBytes\n const heapArray = wasmModule.HEAP32.subarray(elemOffset, elemOffset + numElements)\n return new WasmBuffer<Int32Array>(wasmModule, numElements, byteOffset, heapArray)\n}\n\n/**\n * Return a `WasmBuffer` that holds float64 elements.\n *\n * @hidden For internal use only.\n *\n * @param wasmModule The `WasmModule` used to initialize the memory.\n * @param numElements The number of elements in the buffer.\n */\nexport function createFloat64WasmBuffer(wasmModule: WasmModule, numElements: number): WasmBuffer<Float64Array> {\n const elemSizeInBytes = 8\n const lengthInBytes = numElements * elemSizeInBytes\n const byteOffset = wasmModule._malloc(lengthInBytes)\n const elemOffset = byteOffset / elemSizeInBytes\n const heapArray = wasmModule.HEAPF64.subarray(elemOffset, elemOffset + numElements)\n return new WasmBuffer<Float64Array>(wasmModule, numElements, byteOffset, heapArray)\n}\n","// Copyright (c) 2020-2022 Climate Interactive / New Venture Fund\n\nimport type { OutputVarId } from '../_shared'\nimport type { RunModelParams, RunnableModel } from '../runnable-model'\nimport { perfElapsed, perfNow } from '../perf'\nimport { createFloat64WasmBuffer, createInt32WasmBuffer, type WasmBuffer } from './wasm-buffer'\nimport type { WasmModule } from './wasm-module'\n\n/**\n * A wrapper around a WebAssembly module generated by the SDEverywhere transpiler,\n * which allows for running the model with a given set of input values, producing\n * a set of output values.\n */\nclass WasmModel implements RunnableModel {\n // from RunnableModel interface\n public readonly startTime: number\n // from RunnableModel interface\n public readonly endTime: number\n // from RunnableModel interface\n public readonly saveFreq: number\n // from RunnableModel interface\n public readonly numSavePoints: number\n // from RunnableModel interface\n public readonly outputVarIds: OutputVarId[]\n // from RunnableModel interface\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public readonly modelListing?: any\n\n // Reuse the wasm buffers. These buffers are allocated on demand and grown\n // (reallocated) as needed.\n private inputsBuffer: WasmBuffer<Float64Array>\n private outputsBuffer: WasmBuffer<Float64Array>\n private outputIndicesBuffer: WasmBuffer<Int32Array>\n private lookupDataBuffer: WasmBuffer<Float64Array>\n private lookupSubIndicesBuffer: WasmBuffer<Int32Array>\n\n private readonly wasmSetLookup: (\n varIndex: number,\n subIndicesAddress: number,\n pointsAddress: number,\n numPoints: number\n ) => void\n private readonly wasmRunModel: (inputsAddress: number, outputsAddress: number, outputIndicesAddress: number) => void\n\n /**\n * @param wasmModule The `WasmModule` that provides access to the native functions.\n * @param outputVarIds The output variable IDs for this model.\n */\n constructor(private readonly wasmModule: WasmModule) {\n function getNumberValue(funcName: string): number {\n const wasmGetValue: () => number = wasmModule.cwrap(funcName, 'number', [])\n return wasmGetValue()\n }\n this.startTime = getNumberValue('getInitialTime')\n this.endTime = getNumberValue('getFinalTime')\n this.saveFreq = getNumberValue('getSaveper')\n\n // Each series will include one data point per \"save\", inclusive of the\n // start and end times\n this.numSavePoints = Math.round((this.endTime - this.startTime) / this.saveFreq) + 1\n this.outputVarIds = wasmModule.outputVarIds\n\n // Expose the model listing, if it was bundled with the generated module\n this.modelListing = wasmModule.modelListing\n\n // Make the native functions callable\n this.wasmSetLookup = wasmModule.cwrap('setLookup', null, ['number', 'number', 'number', 'number'])\n this.wasmRunModel = wasmModule.cwrap('runModelWithBuffers', null, ['number', 'number', 'number'])\n }\n\n // from RunnableModel interface\n runModel(params: RunModelParams): void {\n // Note that for wasm models, we always need to allocate `WasmBuffer` instances to\n // and copy data to/from them because only that kind of buffer can be passed to\n // the `wasmRunModel` function.\n\n // Apply lookup overrides, if provided\n const lookups = params.getLookups()\n if (lookups !== undefined) {\n for (const lookupDef of lookups) {\n // Copy the subscript index values to the `WasmBuffer`. If we don't have an\n // existing `WasmBuffer`, or the existing one is not big enough, allocate a new one.\n const varSpec = lookupDef.varRef.varSpec\n const numSubElements = varSpec.subscriptIndices?.length || 0\n let subIndicesAddress: number\n if (numSubElements > 0) {\n if (this.lookupSubIndicesBuffer === undefined || this.lookupSubIndicesBuffer.numElements < numSubElements) {\n this.lookupSubIndicesBuffer?.dispose()\n this.lookupSubIndicesBuffer = createInt32WasmBuffer(this.wasmModule, numSubElements)\n }\n this.lookupSubIndicesBuffer.getArrayView().set(varSpec.subscriptIndices)\n subIndicesAddress = this.lookupSubIndicesBuffer.getAddress()\n } else {\n subIndicesAddress = 0\n }\n\n let pointsAddress: number\n let numPoints: number\n if (lookupDef.points) {\n // Copy the lookup data to the `WasmBuffer`. If we don't have an existing `WasmBuffer`,\n // or the existing one is not big enough, allocate a new one.\n const numLookupElements = lookupDef.points.length\n if (this.lookupDataBuffer === undefined || this.lookupDataBuffer.numElements < numLookupElements) {\n this.lookupDataBuffer?.dispose()\n this.lookupDataBuffer = createFloat64WasmBuffer(this.wasmModule, numLookupElements)\n }\n this.lookupDataBuffer.getArrayView().set(lookupDef.points)\n pointsAddress = this.lookupDataBuffer.getAddress()\n\n // Note that the native `numPoints` argument is the number of (x,y) pairs, so divide\n // the length of the flat points array by two\n numPoints = numLookupElements / 2\n } else {\n // In the case where the points array is undefined, we pass 0 (NULL), which will reset\n // the lookup to its original data\n pointsAddress = 0\n numPoints = 0\n }\n\n // Call the native `setLookup` function\n const varIndex = varSpec.varIndex\n this.wasmSetLookup(varIndex, subIndicesAddress, pointsAddress, numPoints)\n }\n }\n\n // Copy the inputs to the `WasmBuffer`. If we don't have an existing `WasmBuffer`,\n // or the existing one is not big enough, the callback will allocate a new one.\n params.copyInputs(this.inputsBuffer?.getArrayView(), numElements => {\n this.inputsBuffer?.dispose()\n this.inputsBuffer = createFloat64WasmBuffer(this.wasmModule, numElements)\n return this.inputsBuffer.getArrayView()\n })\n\n let outputIndicesBuffer: WasmBuffer<Int32Array>\n if (params.getOutputIndicesLength() > 0) {\n // Copy the output indices (if needed) to the `WasmBuffer`. If we don't have an\n // existing `WasmBuffer`, or the existing one is not big enough, the callback\n // will allocate a new one.\n params.copyOutputIndices(this.outputIndicesBuffer?.getArrayView(), numElements => {\n this.outputIndicesBuffer?.dispose()\n this.outputIndicesBuffer = createInt32WasmBuffer(this.wasmModule, numElements)\n return this.outputIndicesBuffer.getArrayView()\n })\n outputIndicesBuffer = this.outputIndicesBuffer\n } else {\n // The output indices are not active\n outputIndicesBuffer = undefined\n }\n\n // Allocate (or reallocate) the `WasmBuffer` that will receive the outputs\n const outputsLengthInElements = params.getOutputsLength()\n if (this.outputsBuffer === undefined || this.outputsBuffer.numElements < outputsLengthInElements) {\n this.outputsBuffer?.dispose()\n this.outputsBuffer = createFloat64WasmBuffer(this.wasmModule, outputsLengthInElements)\n }\n\n // Run the model\n const t0 = perfNow()\n this.wasmRunModel(\n this.inputsBuffer?.getAddress() || 0,\n this.outputsBuffer.getAddress(),\n outputIndicesBuffer?.getAddress() || 0\n )\n const elapsed = perfElapsed(t0)\n\n // Copy the outputs that were stored into the `WasmBuffer` back to the `RunModelParams`\n params.storeOutputs(this.outputsBuffer.getArrayView())\n\n // Store the elapsed time in the `RunModelParams`\n params.storeElapsedTime(elapsed)\n }\n\n // from RunnableModel interface\n terminate(): void {\n this.inputsBuffer?.dispose()\n this.inputsBuffer = undefined\n\n this.outputsBuffer?.dispose()\n this.outputsBuffer = undefined\n\n this.outputIndicesBuffer?.dispose()\n this.outputIndicesBuffer = undefined\n\n // TODO: Dispose the `WasmModule` too?\n }\n}\n\n/**\n * Initialize the wasm model.\n *\n * @hidden This is not part of the public API; only the top-level `createRunnableModel`\n * function is exposed in the public API.\n *\n * @param wasmModule The `WasmModule` that wraps the `wasm` binary.\n * @return The initialized `WasmModel` instance.\n */\nexport function initWasmModel(wasmModule: WasmModule): RunnableModel {\n return new WasmModel(wasmModule)\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport type { OutputVarId, VarId, VarSpec } from '../../_shared'\nimport { JsModelLookup } from '../../js-model/js-model-lookup'\nimport { ModelListing } from '../../model-listing'\nimport type { WasmModule } from '../wasm-module'\n\n/**\n * @hidden This type is not part of the public API; it is exposed only for use in\n * tests in the runtime-async package.\n */\nexport type OnRunModel = (\n inputs: Float64Array,\n outputs: Float64Array,\n lookups: Map<VarId, JsModelLookup>,\n outputIndices?: Int32Array\n) => void\n\n/**\n * @hidden This type is not part of the public API; it is exposed only for use in\n * tests in the runtime-async package.\n */\nexport class MockWasmModule implements WasmModule {\n // from WasmModule interface\n public readonly kind = 'wasm'\n\n // from WasmModule interface\n public readonly outputVarIds: OutputVarId[]\n\n // from WasmModule interface\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public readonly modelListing?: any\n private readonly internalListing?: ModelListing\n\n private readonly initialTime: number\n private readonly finalTime: number\n\n private readonly heap: ArrayBuffer\n\n // from WasmModule interface\n public readonly HEAP32: Int32Array\n\n // from WasmModule interface\n public readonly HEAPF64: Float64Array\n\n // Start at 8 so that we can treat 0 as NULL\n private mallocOffset = 8\n private readonly allocs: Map<number, number> = new Map()\n\n private readonly lookups: Map<VarId, JsModelLookup> = new Map()\n\n public readonly onRunModel: OnRunModel\n\n constructor(options: {\n initialTime: number\n finalTime: number\n outputVarIds: string[]\n listingJson?: string\n onRunModel: OnRunModel\n }) {\n this.initialTime = options.initialTime\n this.finalTime = options.finalTime\n this.outputVarIds = options.outputVarIds\n if (options.listingJson) {\n this.modelListing = JSON.parse(options.listingJson)\n this.internalListing = new ModelListing(this.modelListing)\n }\n this.onRunModel = options.onRunModel\n\n this.heap = new ArrayBuffer(8192)\n this.HEAP32 = new Int32Array(this.heap)\n this.HEAPF64 = new Float64Array(this.heap)\n }\n\n varIdForSpec(varSpec: VarSpec): VarId {\n for (const [listingVarId, listingSpec] of this.internalListing.varSpecs) {\n // TODO: This doesn't compare subscripts yet\n if (listingSpec.varIndex === varSpec.varIndex) {\n return listingVarId\n }\n }\n return undefined\n }\n\n // from WasmModule interface\n cwrap(fname: string) {\n // Return a mock implementation of each wrapped C function\n switch (fname) {\n case 'getInitialTime':\n return () => this.initialTime\n case 'getFinalTime':\n return () => this.finalTime\n case 'getSaveper':\n return () => 1\n case 'setLookup':\n return (varIndex: number, _subIndicesAddress: number, pointsAddress: number, numPoints: number) => {\n // TODO: This doesn't check subIndices yet\n const varId = this.varIdForSpec({ varIndex })\n if (varId === undefined) {\n throw new Error(`No lookup variable found for var index ${varIndex}`)\n }\n // Note that we create a copy of the points array, since it may be reused\n const points = new Float64Array(this.getHeapView('float64', pointsAddress) as Float64Array)\n this.lookups.set(varId, new JsModelLookup(numPoints, points))\n }\n case 'runModelWithBuffers':\n return (inputsAddress: number, outputsAddress: number, outputIndicesAddress: number) => {\n const inputs = this.getHeapView('float64', inputsAddress) as Float64Array\n const outputs = this.getHeapView('float64', outputsAddress) as Float64Array\n const outputIndices = this.getHeapView('int32', outputIndicesAddress) as Int32Array\n this.onRunModel(inputs, outputs, this.lookups, outputIndices)\n }\n default:\n throw new Error(`Unhandled call to cwrap with function name '${fname}'`)\n }\n }\n\n // from WasmModule interface\n _malloc(lengthInBytes: number): number {\n const currentOffset = this.mallocOffset\n this.allocs.set(currentOffset, lengthInBytes)\n if (lengthInBytes > 0) {\n // Update the offset so that the next allocation starts after this one\n this.mallocOffset += lengthInBytes\n } else {\n // In the case where the length is zero, add a little padding so that\n // the next allocation is recorded at a different start address than\n // this one\n this.mallocOffset += 8\n }\n return currentOffset\n }\n\n // from WasmModule interface\n _free(): void {\n // This is not implemented; the heap will continue to grow, which is fine for the purposes of the tests\n }\n\n private getHeapView(kind: 'float64' | 'int32', address: number): Float64Array | Int32Array | undefined {\n if (address === 0) {\n return undefined\n }\n\n // Find the length\n const lengthInBytes = this.allocs.get(address)\n if (lengthInBytes === undefined) {\n throw new Error('Failed to locate heap allocation')\n }\n\n // The address value is in bytes, so convert to float64 or int32 offset\n if (kind === 'float64') {\n const offset = address / 8\n return this.HEAPF64.subarray(offset, offset + lengthInBytes / 8)\n } else {\n const offset = address / 4\n return this.HEAP32.subarray(offset, offset + lengthInBytes / 4)\n }\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { type InputValue, Outputs } from '../_shared'\n\nimport { type JsModel, initJsModel } from '../js-model'\nimport { type WasmModule, initWasmModel } from '../wasm-model'\nimport type { RunnableModel, RunModelOptions } from '../runnable-model'\nimport { ReferencedRunModelParams } from '../runnable-model'\n\nimport type { ModelRunner } from './model-runner'\nimport { ModelListing } from '../model-listing'\n\n/** Union of model types that are generated by the SDEverywhere transpiler/builder. */\nexport type GeneratedModel = JsModel | WasmModule\n\n/**\n * Create a `RunnableModel` from a given `JsModel` or `WasmModule` that was generated by the\n * SDEverywhere transpiler/builder.\n *\n * @hidden This is not yet part of the public API; it is only exposed for use by\n * the runtime-async package.\n */\nexport function createRunnableModel(generatedModel: GeneratedModel): RunnableModel {\n switch (generatedModel.kind) {\n case 'js':\n // Assume it's a `JsModel`\n return initJsModel(generatedModel)\n case 'wasm':\n // Assume it's a `WasmModule`\n return initWasmModel(generatedModel)\n default:\n throw new Error(`Unable to identify generated model kind`)\n }\n}\n\n/**\n * Create a `ModelRunner` that runs a generated model on the JS thread.\n *\n * @param generatedModel A `JsModel` or `WasmModule` generated by the SDEverywhere transpiler.\n */\nexport function createSynchronousModelRunner(generatedModel: GeneratedModel): ModelRunner {\n const runnableModel = createRunnableModel(generatedModel)\n return createRunnerFromRunnableModel(runnableModel)\n}\n\n/**\n * Create a `ModelRunner` that runs the given model on the JS thread.\n *\n * @param model The runnable model instance.\n */\nfunction createRunnerFromRunnableModel(model: RunnableModel): ModelRunner {\n // Maintain a `ReferencedRunModelParams` instance that holds the I/O parameters\n const listing = model.modelListing ? new ModelListing(model.modelListing) : undefined\n const params = new ReferencedRunModelParams(listing)\n\n // Disallow `runModel` after the runner has been terminated\n let terminated = false\n\n const runModelSync = (inputs: number[] | InputValue[], outputs: Outputs, options: RunModelOptions | undefined) => {\n // Update the I/O parameters\n params.updateFromParams(inputs, outputs, options)\n\n // Run the model synchronously using those parameters\n model.runModel(params)\n\n return outputs\n }\n\n return {\n createOutputs: () => {\n return new Outputs(model.outputVarIds, model.startTime, model.endTime, model.saveFreq)\n },\n\n runModel: (inputs, outputs, options) => {\n if (terminated) {\n return Promise.reject(new Error('Model runner has already been terminated'))\n }\n return Promise.resolve(runModelSync(inputs, outputs, options))\n },\n\n runModelSync: (inputs, outputs, options) => {\n if (terminated) {\n throw new Error('Model runner has already been terminated')\n }\n return runModelSync(inputs, outputs, options)\n },\n\n terminate: async () => {\n if (!terminated) {\n model.terminate()\n terminated = true\n }\n }\n }\n}\n","// Copyright (c) 2020-2022 Climate Interactive / New Venture Fund\n\nimport type { InputValue, InputVarId, Outputs } from '../_shared'\nimport type { ModelRunner } from '../model-runner'\n\n/**\n * A high-level interface that schedules the underlying `ModelRunner`.\n *\n * When one or more input values are changed, this class will schedule a model\n * run to be completed as soon as possible. When the model run has completed,\n * `onOutputsChanged` is called to notify that new output data is available.\n *\n * The `ModelRunner` is pluggable to allow for running the model synchronously\n * (on the main JavaScript thread) or asynchronously (in a Web Worker or Node.js\n * worker thread).\n */\nexport class ModelScheduler {\n /** The second array that holds a stable copy of the user inputs. */\n private readonly currentInputs: InputValue[]\n\n /** Whether a model run has been scheduled. */\n private runNeeded = false\n\n /** Whether a model run is in progress. */\n private runInProgress = false\n\n /** Called when `outputs` has been updated after a model run. */\n public onOutputsChanged?: (outputs: Outputs) => void\n\n /**\n * @param runner The model runner.\n * @param userInputs The input values, in the same order as in the spec file passed to `sde`.\n * @param outputs The structure into which the model outputs will be stored.\n */\n constructor(\n private readonly runner: ModelRunner,\n private readonly userInputs: InputValue[],\n private outputs: Outputs\n ) {\n // When any input has an updated value, schedule a model run on the next tick\n const afterSet = () => {\n this.runModelIfNeeded()\n }\n for (const userInput of userInputs) {\n userInput.callbacks.onSet = afterSet\n }\n\n // Create a second array to hold a stable copy of the user inputs during model runs\n this.currentInputs = []\n for (const userInput of userInputs) {\n this.currentInputs.push(createSimpleInputValue(userInput.varId))\n }\n }\n\n /**\n * Schedule a model run (if not already pending). When the run is\n * complete, save the outputs and call the `onOutputsChanged` callback.\n */\n private runModelIfNeeded(): void {\n // Set a flag indicating that a new run is needed (even if one is already\n // in progress)\n this.runNeeded = true\n\n if (this.runInProgress) {\n // A run is already in progress; let it finish first\n return\n } else {\n // A run is not already in progress, so schedule it now. We use\n // `setTimeout` so that if a lot of inputs are all changing at once\n // (like after a reset), we wait for all those `set` or `reset`\n // calls to finish before gathering the input values into an array\n // and initiating the run on the next tick.\n this.runInProgress = true\n setTimeout(() => {\n // Kick off the (possibly asynchronous) model run\n this.runModelNow()\n }, 0)\n }\n }\n\n /**\n * Run the model asynchronously using the current set of input values.\n */\n private async runModelNow(): Promise<void> {\n // Copy the current inputs into a separate array; this ensures that the\n // model run uses a stable set of inputs, even if the user continues to\n // change the inputs while the model is being run asynchronously\n for (let i = 0; i < this.userInputs.length; i++) {\n this.currentInputs[i].set(this.userInputs[i].get())\n }\n\n // Run the model with the current set of input values and save the outputs\n try {\n this.outputs = await this.runner.runModel(this.currentInputs, this.outputs)\n this.onOutputsChanged?.(this.outputs)\n } catch (e) {\n console.error(`ERROR: Failed to run model: ${e.message}`)\n }\n\n // See if another run is needed\n if (this.runNeeded) {\n // Keep `runInProgress` set, but clear the `runNeeded` flag\n this.runNeeded = false\n setTimeout(() => {\n this.runModelNow()\n }, 0)\n } else {\n // No run needed, so clear both flags\n this.runNeeded = false\n this.runInProgress = false\n }\n }\n}\n\n/**\n * Create an `InputValue` that is only used to hold a copy of another input (no callbacks).\n * @hidden\n */\nfunction createSimpleInputValue(varId: InputVarId): InputValue {\n let currentValue = 0\n const get = () => {\n return currentValue\n }\n const set = (newValue: number) => {\n currentValue = newValue\n }\n const reset = () => {\n set(0)\n }\n return { varId, get, set, reset, callbacks: {} }\n}\n","// Copyright (c) 2025 Climate Interactive / New Venture Fund\n\nimport type { DataMap, InputValue, Outputs, OutputVarId, Series, SourceName } from '../_shared'\nimport type { ModelRunner } from '../model-runner'\n\n/**\n * Defines a context that holds a distinct set of model inputs and outputs.\n * These inputs and outputs are kept separate from those in other contexts,\n * which allows an application to use the same underlying model instance\n * with multiple sets of inputs and outputs.\n */\nexport interface ModelContext {\n /**\n * Called when the outputs have been updated after a model run.\n */\n onOutputsChanged?: () => void\n\n /**\n * Return the series data for the given model output variable or external\n * dataset.\n *\n * @param varId The ID of the output variable associated with the data.\n * @param sourceName The external data source name (e.g. \"Ref\"), or\n * undefined to use the latest model output data from this context.\n */\n getSeriesForVar(varId: OutputVarId, sourceName?: SourceName): Series | undefined\n}\n\n/**\n * A high-level interface that schedules running of the underlying `ModelRunner`.\n *\n * This class is similar to the (single context) `ModelScheduler` class, except\n * this one supports multiple contexts, each with its own distinct set of\n * inputs and outputs. This is useful for running the same underlying model\n * instance with different sets of inputs and outputs. For example, you can\n * use this to show the outputs for multiple scenarios in a single graph, or\n * multiple scenarios across different graphs.\n *\n * When input values are changed in one or more contexts, this class will schedule\n * a model run for each changed context to be completed as soon as possible.\n * When the model run has completed, the context's `onOutputsChanged` function\n * is called to notify that new output data is available for that context.\n *\n * The `ModelRunner` is pluggable to allow for running the model synchronously\n * (on the main JavaScript thread) or asynchronously (in a Web Worker or Node.js\n * worker thread).\n */\nexport class MultiContextModelScheduler {\n /**\n * An optional `Outputs` instance that will be reused for the initial context. This will\n * be set to undefined after it is used for the first context.\n */\n private initialOutputs?: Outputs\n\n /** The second array that holds a stable copy of the user inputs. */\n private currentInputs: number[]\n\n /** The contexts that hold distinct sets of inputs and outputs. */\n private readonly contexts: ModelContextImpl[] = []\n\n /** Whether a model run has been scheduled. */\n private runNeeded = false\n\n /** Whether a model run is in progress. */\n private runInProgress = false\n\n /**\n * @param runner The model runner.\n * @param options Additional options for the scheduler.\n * @param options.initialOutputs An optional `Outputs` instance that will be reused\n * for the initial context. This is useful for saving memory when an `Outputs`\n * instance was already created for, e.g., a initial baseline/reference run.\n */\n constructor(private readonly runner: ModelRunner, options?: { initialOutputs?: Outputs }) {\n this.initialOutputs = options?.initialOutputs\n }\n\n /**\n * Return true if the scheduler has started any model runs.\n */\n public isStarted(): boolean {\n return this.initialOutputs === undefined\n }\n\n /**\n * Add a new context that holds a distinct set of model inputs and outputs.\n * These inputs and outputs are kept separate from those in other contexts,\n * which allows an application to use the same underlying model to run with\n * multiple I/O contexts.\n *\n * Note that the contexts created before the first scheduled model run\n * will inherit the data from `initialOutputs` passed to the constructor,\n * but contexts created after that will initially have output values set\n * to zero.\n *\n * @param inputs The input values, in the same order as in the spec file passed to `sde`.\n * @param options Additional options for the context.\n * @param options.externalData Additional data that is external to the model outputs.\n * For example, this can contain data that was captured from an initial reference\n * run, or other static data that is displayed in graphs alongside the model\n * output data in graphs.\n */\n public addContext(inputs: InputValue[], options?: { externalData?: DataMap }): ModelContext {\n // If we haven't yet performed the initial scheduled model run, the context\n // will inherit the data from `initialOutputs` (if defined), otherwise we\n // initialize a new instance with output values set to zero\n let outputs: Outputs\n if (this.initialOutputs !== undefined) {\n if (this.contexts.length === 0) {\n // For the first context, use the initial outputs by reference\n outputs = this.initialOutputs\n } else {\n // For all other contexts created before the initial scheduled model run,\n // create a copy of the initial outputs\n outputs = this.runner.createOutputs()\n for (const varId of outputs.varIds) {\n const series0 = this.initialOutputs.getSeriesForVar(varId)\n const series1 = outputs.getSeriesForVar(varId)\n for (let i = 0; i < series0.points.length; i++) {\n series1.points[i].y = series0.points[i].y\n }\n }\n }\n } else {\n // Otherwise, initialize a new instance (with values set to zero)\n outputs = this.runner.createOutputs()\n }\n\n // Create the context\n const context = new ModelContextImpl(inputs, outputs, options?.externalData)\n\n // When any input has an updated value, schedule a model run on the next tick\n const afterSet = () => {\n context.runNeeded = true\n this.runModelIfNeeded()\n }\n for (const input of inputs) {\n input.callbacks.onSet = afterSet\n }\n\n // Add to the set of contexts managed by the scheduler\n this.contexts.push(context)\n\n return context\n }\n\n /**\n * Remove the given context from the set of contexts managed by the scheduler.\n *\n * @param context The context to remove.\n */\n public removeContext(context: ModelContext): void {\n const index = this.contexts.findIndex(c => c === context)\n if (index >= 0) {\n this.contexts.splice(index, 1)\n }\n }\n\n /**\n * Schedule a model run (if not already pending). When the run is\n * complete, save the outputs and call the `onOutputsChanged` callback.\n */\n private runModelIfNeeded(): void {\n // Set a flag indicating that a new run is needed (even if one is already\n // in progress)\n this.runNeeded = true\n\n if (this.runInProgress) {\n // A run is already in progress; let it finish first\n return\n } else {\n // A run is not already in progress, so schedule it now. We use\n // `setTimeout` so that if a lot of inputs are all changing at once\n // (like after a reset), we wait for all those `set` or `reset`\n // calls to finish before gathering the input values into an array\n // and initiating the run on the next tick.\n this.runInProgress = true\n setTimeout(() => {\n // Kick off the (possibly asynchronous) model run\n this.runModelNow()\n }, 0)\n }\n }\n\n /**\n * Run the model asynchronously for all relevant contexts.\n */\n private async runModelNow(): Promise<void> {\n // Invalidate the initial outputs\n this.initialOutputs = undefined\n\n // Run the model for each context that requested a run\n for (const context of this.contexts) {\n if (context.runNeeded) {\n context.runNeeded = false\n await this.runModelNowForContext(context)\n }\n }\n\n // See if another run is needed\n if (this.runNeeded) {\n // Keep `runInProgress` set, but clear the `runNeeded` flag\n this.runNeeded = false\n setTimeout(() => {\n this.runModelNow()\n }, 0)\n } else {\n // No run needed, so clear both flags\n this.runNeeded = false\n this.runInProgress = false\n }\n }\n\n /**\n * Run the model asynchronously using the current set of input values in the given context.\n *\n * @param context The context to use for the model run.\n */\n private async runModelNowForContext(context: ModelContextImpl): Promise<void> {\n // If not already initialized, create a second array (that is shared for all\n // contexts) to hold a stable copy of the user inputs during model runs\n if (this.currentInputs === undefined) {\n this.currentInputs = Array(context.inputsArray.length)\n }\n\n // Copy the current inputs into a separate array; this ensures that the\n // following model runs all use the same inputs, even if the user continues\n // to change the inputs while the model is being run asynchronously\n for (let i = 0; i < context.inputsArray.length; i++) {\n this.currentInputs[i] = context.inputsArray[i].get()\n }\n\n // Run the model with the current set of input values and save the outputs\n try {\n // Perform the model run\n await this.runner.runModel(this.currentInputs, context.outputs)\n\n // Notify that the outputs have been updated\n context.onOutputsChanged?.()\n } catch (e) {\n console.error('ERROR: The scheduler encountered an error when running the model:', e)\n }\n }\n}\n\nclass ModelContextImpl implements ModelContext {\n /**\n * A copy of the `inputs` array that was passed to `addContext`.\n * @hidden This is intended for use by `MultiContextModelScheduler` only.\n */\n public readonly inputsArray: InputValue[]\n\n /**\n * The structure into which the model outputs will be stored.\n * @hidden This is intended for use by `MultiContextModelScheduler` only.\n */\n public readonly outputs: Outputs\n\n /**\n * Whether a model run is needed for this context.\n * @hidden This is intended for use by `MultiContextModelScheduler` only.\n */\n public runNeeded = false\n\n /**\n * Called when the outputs have been updated after a model run.\n */\n public onOutputsChanged?: () => void\n\n /**\n * @hidden This is intended for use by `MultiContextModelScheduler` only.\n *\n * @param inputs The input values, in the same order as in the spec file passed to `sde`.\n * @param outputs The structure into which the model outputs will be stored.\n * @param externalData Additional data that is external to the model outputs. For example, this can contain\n * data that was captured from an initial reference run, or other static data that is displayed in graphs\n * alongside the model output data in graphs.\n */\n constructor(inputs: InputValue[], outputs: Outputs, private readonly externalData: DataMap) {\n this.inputsArray = Array.from(inputs)\n this.outputs = outputs\n }\n\n /**\n * Return the series data for the given model output variable or external\n * dataset.\n *\n * @param varId The ID of the output variable associated with the data.\n * @param sourceName The external data source name (e.g. \"Ref\"), or\n * undefined to use the latest model output data from this context.\n */\n public getSeriesForVar(varId: OutputVarId, sourceName?: SourceName): Series | undefined {\n if (sourceName === undefined) {\n // Return the latest model output data for this context\n return this.outputs.getSeriesForVar(varId)\n } else {\n const dataForSource = this.externalData.get(sourceName)\n if (dataForSource !== undefined) {\n // Return the external data\n return dataForSource.get(varId)\n } else {\n // No data found for the given source name\n return undefined\n }\n }\n }\n}\n"],"mappings":"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","names":["dimensions","extrasLengthInElements","_a"]}
|
|
1
|
+
{"version":3,"sources":["../src/_shared/inputs.ts","../src/_shared/outputs.ts","../src/_shared/var-indices.ts","../src/_shared/constant-def.ts","../src/_shared/lookup-def.ts","../src/model-listing/model-listing.ts","../src/runnable-model/resolve-var-ref.ts","../src/runnable-model/buffered-run-model-params.ts","../src/runnable-model/referenced-run-model-params.ts","../src/js-model/js-model-constants.ts","../src/js-model/js-model-lookup.ts","../src/js-model/js-model-functions.ts","../src/perf/perf.ts","../src/runnable-model/base-runnable-model.ts","../src/js-model/js-model.ts","../src/js-model/exec-js-model.ts","../src/js-model/_mocks/mock-js-model.ts","../src/wasm-model/wasm-buffer.ts","../src/wasm-model/wasm-model.ts","../src/wasm-model/_mocks/mock-wasm-module.ts","../src/model-runner/synchronous-model-runner.ts","../src/model-scheduler/model-scheduler.ts","../src/model-scheduler/multi-context-model-scheduler.ts"],"sourcesContent":["// Copyright (c) 2020-2022 Climate Interactive / New Venture Fund\n\nimport type { InputVarId } from './types'\n\n/** Callback functions that are called when the input value is changed. */\nexport interface InputCallbacks {\n /** Called after a new value is set. */\n onSet?: () => void\n}\n\n/**\n * Represents a writable model input.\n */\nexport interface InputValue {\n /** The ID of the associated input variable, as used in SDEverywhere. */\n varId: InputVarId\n /** Get the current value of the input. */\n get: () => number\n /** Set the input to the given value. */\n set: (value: number) => void\n /** Reset the input to its default value. */\n reset: () => void\n /** Callback functions that are called when the input value is changed. */\n callbacks: InputCallbacks\n}\n\n/**\n * Create a basic `InputValue` instance that notifies when a new value is set.\n *\n * @param varId The input variable ID, as used in SDEverywhere.\n * @param defaultValue The default value of the input.\n * @param initialValue The inital value of the input; if undefined, will use `defaultValue`.\n */\nexport function createInputValue(varId: InputVarId, defaultValue: number, initialValue?: number): InputValue {\n let currentValue = initialValue !== undefined ? initialValue : defaultValue\n\n // The `onSet` callback is initially undefined but will be installed by `ModelScheduler`\n const callbacks: InputCallbacks = {}\n\n const get = () => {\n return currentValue\n }\n\n const set = (newValue: number) => {\n if (newValue !== currentValue) {\n currentValue = newValue\n callbacks.onSet?.()\n }\n }\n\n const reset = () => {\n set(defaultValue)\n }\n\n return { varId, get, set, reset, callbacks }\n}\n","// Copyright (c) 2020-2022 Climate Interactive / New Venture Fund\n\nimport type { Result } from 'neverthrow'\nimport { ok, err } from 'neverthrow'\n\nimport type { OutputVarId, Point, SourceName, VarSpec } from './types'\n\n/** Indicates the type of error encountered when parsing an outputs buffer. */\nexport type ParseError = 'invalid-point-count'\n\n/** Type alias for a map that holds a `Series` instance for each output (or static) variable ID. */\nexport type SeriesMap = Map<OutputVarId, Series>\n\n/** Type alias for a map that holds data for a given source name. */\nexport type DataMap = Map<SourceName, SeriesMap>\n\n/**\n * A time series of data points for an output variable.\n */\nexport class Series {\n /**\n * @param varId The ID for the output variable (as used by SDEverywhere).\n * @param points The data points for the variable, one point per time increment.\n */\n constructor(\n public readonly varId: OutputVarId,\n public readonly points: Point[]\n ) {}\n\n /**\n * Return the Y value at the given time. Note that this does not attempt to interpolate\n * if there is no data point defined for the given time and will return undefined in\n * that case.\n *\n * @param time The x (time) value.\n * @return The y value for the given time, or undefined if there is no data point defined\n * for the given time.\n */\n getValueAtTime(time: number): number | undefined {\n // TODO: Add option to allow interpolation if the given time value is in between points\n // TODO: Use binary search to make lookups faster\n return this.points.find(p => p.x === time)?.y\n }\n\n /**\n * Create a new `Series` instance that is a copy of this one.\n */\n copy(): Series {\n // Create a deep copy\n const pointsCopy = this.points.map(p => ({ ...p }))\n return new Series(this.varId, pointsCopy)\n }\n}\n\n/** Represents the outputs from a model run. */\nexport class Outputs {\n /** The number of data points in each series. */\n public readonly seriesLength: number\n /** The array of series, one for each output variable. */\n public readonly varSeries: Series[]\n\n /**\n * The latest model run time, in milliseconds.\n * @hidden This is not yet part of the public API; it is exposed here for use\n * in performance testing tools.\n */\n public runTimeInMillis: number\n\n /**\n * The optional set of specs that dictate which variables from the model will be\n * stored in this `Outputs` instance. If undefined, the default set of outputs\n * will be stored (as configured in `varIds`).\n * @hidden This is not yet part of the public API; it is exposed here for use\n * in experimental testing tools.\n */\n public varSpecs?: VarSpec[]\n\n /**\n * @param varIds The output variable identifiers.\n * @param startTime The start time for the model.\n * @param endTime The end time for the model.\n * @param saveFreq The frequency with which output values are saved (aka `SAVEPER`).\n */\n constructor(\n public readonly varIds: OutputVarId[],\n public readonly startTime: number,\n public readonly endTime: number,\n public readonly saveFreq = 1\n ) {\n // Each series will include one data point per \"save\", inclusive of the\n // start and end times\n this.seriesLength = Math.round((endTime - startTime) / saveFreq) + 1\n\n // Create an array of arrays, one for each output variable\n this.varSeries = new Array(varIds.length)\n\n // Populate the arrays, filling in the time for each point\n for (let i = 0; i < varIds.length; i++) {\n const points: Point[] = new Array(this.seriesLength)\n for (let j = 0; j < this.seriesLength; j++) {\n points[j] = { x: startTime + j * saveFreq, y: 0 }\n }\n const varId = varIds[i]\n this.varSeries[i] = new Series(varId, points)\n }\n }\n\n /**\n * The optional set of specs that dictate which variables from the model will be\n * stored in this `Outputs` instance. If undefined, the default set of outputs\n * will be stored (as configured in `varIds`).\n * @hidden This is not yet part of the public API; it is exposed here for use\n * in experimental testing tools.\n */\n setVarSpecs(varSpecs: VarSpec[]) {\n if (varSpecs.length !== this.varIds.length) {\n throw new Error('Length of output varSpecs must match that of varIds')\n }\n this.varSpecs = varSpecs\n }\n\n /**\n * Parse the given raw float buffer (produced by the model) and store the values\n * into this `Outputs` instance.\n *\n * Note that the length of `outputsBuffer` must be greater than or equal to\n * the capacity of this `Outputs` instance. The `Outputs` instance is allowed\n * to be smaller to support the case where you want to extract a subset of\n * the time range in the buffer produced by the model.\n *\n * @param outputsBuffer The raw outputs buffer produced by the model.\n * @param rowLength The number of elements per row (one element per save point).\n * @return An `ok` result if the buffer is valid, otherwise an `err` result.\n */\n updateFromBuffer(outputsBuffer: Float64Array, rowLength: number): Result<void, ParseError> {\n const result = parseOutputsBuffer(outputsBuffer, rowLength, this)\n if (result.isOk()) {\n return ok(undefined)\n } else {\n return err(result.error)\n }\n }\n\n /**\n * Return the series for the given output variable.\n *\n * @param varId The ID of the output variable (as used by SDEverywhere).\n */\n getSeriesForVar(varId: OutputVarId): Series | undefined {\n const seriesIndex = this.varIds.indexOf(varId)\n if (seriesIndex >= 0) {\n return this.varSeries[seriesIndex]\n } else {\n // TODO: Error\n return undefined\n }\n }\n}\n\n/**\n * Parse the raw buffer produced by the model and store the values in the\n * given (reused) `Outputs` object.\n *\n * @param outputsBuffer The raw outputs buffer produced by the model.\n * @param rowLength The number of elements per row (one element per year or save point).\n * @return An `ok` result if the buffer is valid, otherwise an `err` result.\n * @hidden\n */\nfunction parseOutputsBuffer(\n outputsBuffer: Float64Array,\n rowLength: number,\n outputs: Outputs\n): Result<Outputs, ParseError> {\n const varCount = outputs.varIds.length\n const seriesLength = outputs.seriesLength\n if (rowLength < seriesLength || outputsBuffer.length < varCount * seriesLength) {\n return err('invalid-point-count')\n }\n\n // The buffer populated by the C `runModelWithBuffers` function is already\n // transposed, so the first \"row\" contains the values for the first output\n // variable (from start time to end time), and so on.\n for (let outputVarIndex = 0; outputVarIndex < varCount; outputVarIndex++) {\n const series = outputs.varSeries[outputVarIndex]\n let sourceIndex = rowLength * outputVarIndex\n for (let valueIndex = 0; valueIndex < seriesLength; valueIndex++) {\n series.points[valueIndex].y = validateNumber(outputsBuffer[sourceIndex])\n sourceIndex++\n }\n }\n\n return ok(outputs)\n}\n\n/**\n * Return the given number if it is valid, or undefined if it is invalid.\n *\n * SDE converts Vensim's `:NA:` values to `-DBL_MAX`, so if we see a very large negative\n * value, convert it to `undefined`. This is preferable to including extreme values\n * because some charting libraries (e.g. Chart.js) appear to choke on these large values\n * in certain browsers (e.g. Safari), but `undefined` appears to be handled better and\n * does a better job of signaling that the data point is undefined.\n *\n * @hidden\n */\nfunction validateNumber(x: number): number | undefined {\n if (!isNaN(x) && x > -1e32) {\n return x\n } else {\n return undefined\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport type { ConstantDef } from './constant-def'\nimport type { LookupDef } from './lookup-def'\nimport type { VarSpec } from './types'\n\n/**\n * Return the length of the array that is required to store the variable\n * indices for the given `VarSpec` instances.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param varSpecs The `VarSpec` instances to encode.\n */\nexport function getEncodedVarIndicesLength(varSpecs: VarSpec[]): number {\n // The indices buffer has the following format:\n // variable count\n // varN index\n // varN subscript count\n // varN sub1 index\n // varN sub2 index\n // ...\n // varN subM index\n // ... (repeat for each var spec)\n\n // Start with one element for the total variable count\n let length = 1\n\n for (const varSpec of varSpecs) {\n // Include one element for the variable index and one for the subscript count\n length += 2\n\n // Include one element for each subscript\n const subCount = varSpec.subscriptIndices?.length || 0\n length += subCount\n }\n\n return length\n}\n\n/**\n * Encode variable indices to the given array.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param varSpecs The `VarSpec` instances to encode.\n */\nexport function encodeVarIndices(varSpecs: VarSpec[], indicesArray: Int32Array): void {\n // Write the variable count\n let offset = 0\n indicesArray[offset++] = varSpecs.length\n\n // Write the indices for each variable\n for (const varSpec of varSpecs) {\n // Write the variable index\n indicesArray[offset++] = varSpec.varIndex\n\n // Write the subscript count\n const subs = varSpec.subscriptIndices\n const subCount = subs?.length || 0\n indicesArray[offset++] = subCount\n\n // Write the subscript indices\n for (let i = 0; i < subCount; i++) {\n indicesArray[offset++] = subs[i]\n }\n }\n}\n\n/**\n * Return the lengths of the arrays that are required to store the constant values\n * and indices for the given `ConstantDef` instances.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param constantDefs The `ConstantDef` instances to encode.\n */\nexport function getEncodedConstantBufferLengths(constantDefs: ConstantDef[]): {\n constantIndicesLength: number\n constantsLength: number\n} {\n // The constants buffer includes all constant values for the provided constant overrides\n // (added sequentially, one value per constant). The constant indices buffer has the\n // following format:\n // constant count\n // constantN var index\n // constantN subscript count\n // constantN sub1 index\n // constantN sub2 index\n // ...\n // constantN subM index\n // ... (repeat for each constant)\n\n // Start with one element for the total constant variable count\n let constantIndicesLength = 1\n let constantsLength = 0\n\n for (const constantDef of constantDefs) {\n // Ensure that the var spec has already been resolved\n const varSpec = constantDef.varRef.varSpec\n if (varSpec === undefined) {\n throw new Error('Cannot compute constant buffer lengths until all constant var specs are defined')\n }\n\n // Include one element for the variable index and one for the subscript count\n constantIndicesLength += 2\n\n // Include one element for each subscript\n const subCount = varSpec.subscriptIndices?.length || 0\n constantIndicesLength += subCount\n\n // Add one element for the constant value\n constantsLength += 1\n }\n\n return {\n constantIndicesLength,\n constantsLength\n }\n}\n\n/**\n * Encode constant values and indices to the given arrays.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param constantDefs The `ConstantDef` instances to encode.\n * @param constantIndicesArray The view on the constant indices buffer.\n * @param constantsArray The view on the constant values buffer.\n */\nexport function encodeConstants(\n constantDefs: ConstantDef[],\n constantIndicesArray: Int32Array,\n constantsArray: Float64Array\n): void {\n // Write the constant variable count\n let ci = 0\n constantIndicesArray[ci++] = constantDefs.length\n\n // Write the indices and values for each constant\n let constantDataOffset = 0\n for (const constantDef of constantDefs) {\n // Write the constant variable index\n const varSpec = constantDef.varRef.varSpec\n constantIndicesArray[ci++] = varSpec.varIndex\n\n // Write the subscript count\n const subs = varSpec.subscriptIndices\n const subCount = subs?.length || 0\n constantIndicesArray[ci++] = subCount\n\n // Write the subscript indices\n for (let i = 0; i < subCount; i++) {\n constantIndicesArray[ci++] = subs[i]\n }\n\n // Write the constant value\n constantsArray[constantDataOffset++] = constantDef.value\n }\n}\n\n/**\n * Decode constant values and indices from the given buffer views and return the\n * reconstructed `ConstantDef` instances.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param constantIndicesArray The view on the constant indices buffer.\n * @param constantsArray The view on the constant values buffer.\n */\nexport function decodeConstants(constantIndicesArray: Int32Array, constantsArray: Float64Array): ConstantDef[] {\n const constantDefs: ConstantDef[] = []\n let ci = 0\n\n // Read the constant variable count\n const constantCount = constantIndicesArray[ci++]\n\n // Read the metadata for each variable from the constant indices buffer\n for (let i = 0; i < constantCount; i++) {\n // Read the constant variable index\n const varIndex = constantIndicesArray[ci++]\n\n // Read the subscript count\n const subCount = constantIndicesArray[ci++]\n\n // Read the subscript indices\n const subscriptIndices: number[] = subCount > 0 ? Array(subCount) : undefined\n for (let subIndex = 0; subIndex < subCount; subIndex++) {\n subscriptIndices[subIndex] = constantIndicesArray[ci++]\n }\n\n // Create a `VarSpec` for the variable\n const varSpec: VarSpec = {\n varIndex,\n subscriptIndices\n }\n\n // Read the constant value\n const value = constantsArray[i]\n\n constantDefs.push({\n varRef: {\n varSpec\n },\n value\n })\n }\n\n return constantDefs\n}\n\n/**\n * Return the lengths of the arrays that are required to store the lookup data\n * and indices for the given `LookupDef` instances.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param lookupDefs The `LookupDef` instances to encode.\n */\nexport function getEncodedLookupBufferLengths(lookupDefs: LookupDef[]): {\n lookupIndicesLength: number\n lookupsLength: number\n} {\n // The lookups buffer includes all data points for the provided lookup overrides\n // (added sequentially, with no padding between datasets). The lookup indices\n // buffer has the following format:\n // lookup count\n // lookupN var index\n // lookupN subscript count\n // lookupN sub1 index\n // lookupN sub2 index\n // ...\n // lookupN subM index\n // lookupN data offset (relative to the start of the lookups buffer, in float64 elements)\n // lookupN data length (in float64 elements)\n // ... (repeat for each lookup)\n\n // Start with one element for the total lookup variable count\n let lookupIndicesLength = 1\n let lookupsLength = 0\n\n for (const lookupDef of lookupDefs) {\n // Ensure that the var spec has already been resolved\n const varSpec = lookupDef.varRef.varSpec\n if (varSpec === undefined) {\n throw new Error('Cannot compute lookup buffer lengths until all lookup var specs are defined')\n }\n\n // Include one element for the variable index and one for the subscript count\n lookupIndicesLength += 2\n\n // Include one element for each subscript\n const subCount = varSpec.subscriptIndices?.length || 0\n lookupIndicesLength += subCount\n\n // Include one element for the data offset and one element for the data length\n lookupIndicesLength += 2\n\n // Add the length of the lookup points array\n lookupsLength += lookupDef.points?.length || 0\n }\n\n return {\n lookupIndicesLength,\n lookupsLength\n }\n}\n\n/**\n * Encode lookup data and indices to the given arrays.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param lookupDefs The `LookupDef` instances to encode.\n * @param lookupIndicesArray The view on the lookup indices buffer.\n * @param lookupsArray The view on the lookup data buffer. This can be undefined in\n * the case where the data for the lookup(s) is empty.\n */\nexport function encodeLookups(\n lookupDefs: LookupDef[],\n lookupIndicesArray: Int32Array,\n lookupsArray: Float64Array | undefined\n): void {\n // Write the lookup variable count\n let li = 0\n lookupIndicesArray[li++] = lookupDefs.length\n\n // Write the indices and data for each lookup\n let lookupDataOffset = 0\n for (const lookupDef of lookupDefs) {\n // Write the lookup variable index\n const varSpec = lookupDef.varRef.varSpec\n lookupIndicesArray[li++] = varSpec.varIndex\n\n // Write the subscript count\n const subs = varSpec.subscriptIndices\n const subCount = subs?.length || 0\n lookupIndicesArray[li++] = subCount\n\n // Write the subscript indices\n for (let i = 0; i < subCount; i++) {\n lookupIndicesArray[li++] = subs[i]\n }\n\n if (lookupDef.points !== undefined) {\n // Write the lookup data offset and length for this variable\n lookupIndicesArray[li++] = lookupDataOffset\n lookupIndicesArray[li++] = lookupDef.points.length\n\n // Write the lookup data. Note that `lookupsView` can be undefined in the case\n // where the lookup data is empty.\n lookupsArray?.set(lookupDef.points, lookupDataOffset)\n lookupDataOffset += lookupDef.points.length\n } else {\n // Note that the points array can be undefined, which is used to indicate\n // that the lookup should be reset to its original data. In this case,\n // we use -1 for the data offset, which will be translated to NULL/undefined\n // when passed to the `setLookup` call.\n lookupIndicesArray[li++] = -1\n lookupIndicesArray[li++] = 0\n }\n }\n}\n\n/**\n * Decode lookup data and indices from the given buffer views and return the\n * reconstructed `LookupDef` instances.\n *\n * @hidden This is not part of the public API; it is exposed here for use by\n * the synchronous and asynchronous model runner implementations.\n *\n * @param lookupIndicesArray The view on the lookup indices buffer.\n * @param lookupsArray The view on the lookup data buffer. This can be undefined in\n * the case where the data for the lookup(s) is empty.\n */\nexport function decodeLookups(lookupIndicesArray: Int32Array, lookupsArray: Float64Array | undefined): LookupDef[] {\n const lookupDefs: LookupDef[] = []\n let li = 0\n\n // Read the lookup variable count\n const lookupCount = lookupIndicesArray[li++]\n\n // Read the metadata for each variable from the lookup indices buffer\n for (let i = 0; i < lookupCount; i++) {\n // Read the lookup variable index\n const varIndex = lookupIndicesArray[li++]\n\n // Read the subscript count\n const subCount = lookupIndicesArray[li++]\n\n // Read the subscript indices\n const subscriptIndices: number[] = subCount > 0 ? Array(subCount) : undefined\n for (let subIndex = 0; subIndex < subCount; subIndex++) {\n subscriptIndices[subIndex] = lookupIndicesArray[li++]\n }\n\n // Read the lookup data offset and length for this variable\n const lookupDataOffset = lookupIndicesArray[li++]\n const lookupDataLength = lookupIndicesArray[li++]\n\n // Create a `VarSpec` for the variable\n const varSpec: VarSpec = {\n varIndex,\n subscriptIndices\n }\n\n let points: Float64Array\n if (lookupDataOffset >= 0) {\n // Copy the data from the lookup data buffer. Note that `lookupsArray` can be undefined\n // in the case where the lookup data is empty.\n // TODO: We can use `subarray` here instead of `slice` and let the model implementations\n // copy the data if needed on their side\n if (lookupsArray) {\n points = lookupsArray.slice(lookupDataOffset, lookupDataOffset + lookupDataLength)\n } else {\n points = new Float64Array(0)\n }\n } else {\n // A negative data offset value is used in the case where the points array is undefined,\n // which is used to indicate that the lookup should be reset to its original data\n points = undefined\n }\n lookupDefs.push({\n varRef: {\n varSpec\n },\n points\n })\n }\n\n return lookupDefs\n}\n","// Copyright (c) 2025 Climate Interactive / New Venture Fund\n\nimport type { VarRef } from './types'\n\n/**\n * Specifies the constant value that will be used to override a constant in a\n * generated model.\n */\nexport interface ConstantDef {\n /** The reference that identifies the constant variable to be modified. */\n varRef: VarRef\n\n /** The new constant value. */\n value: number\n}\n\n/**\n * Create a `ConstantDef` instance.\n *\n * @param varRef The reference to the constant variable to be modified.\n * @param value The new constant value.\n */\nexport function createConstantDef(varRef: VarRef, value: number): ConstantDef {\n return {\n varRef,\n value\n }\n}\n","// Copyright (c) 2020-2022 Climate Interactive / New Venture Fund\n\nimport type { Point, VarRef } from './types'\n\n/**\n * Specifies the data that will be used to set or override a lookup definition.\n */\nexport interface LookupDef {\n /** The reference that identifies the lookup or data variable to be modified. */\n varRef: VarRef\n\n /** The lookup data as a flat array of (x,y) pairs. */\n points?: Float64Array\n}\n\n/**\n * Create a `LookupDef` instance from the given array of `Point` objects.\n *\n * @param varRef The reference to the lookup or data variable to be modified.\n * @param points The lookup data as an array of `Point` objects. This can be\n * undefined, in which case the lookup data will be reset to the original data.\n */\nexport function createLookupDef(varRef: VarRef, points: Point[] | undefined): LookupDef {\n let flatPoints: Float64Array\n if (points) {\n flatPoints = new Float64Array(points.length * 2)\n let i = 0\n for (const p of points) {\n flatPoints[i++] = p.x\n flatPoints[i++] = p.y\n }\n }\n\n return {\n varRef,\n points: flatPoints\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport type { OutputVarId, VarId, VarName, VarSpec } from '../_shared'\nimport { Outputs } from '../_shared'\n\ntype SubscriptId = string\ntype DimensionId = string\n\n/**\n * Holds information about a subscript used in the model.\n */\ninterface Subscript {\n /** The subscript identifier, as used in SDE. */\n id: SubscriptId\n /* The zero-based index for the subscript within the dimension. */\n index: number\n}\n\n/**\n * Holds information about a dimension (subscript family) used in the model.\n */\ninterface Dimension {\n /** The dimension identifier, as used in SDE. */\n id: DimensionId\n /** The set of subscripts in this dimension. */\n subscripts: Subscript[]\n}\n\n/**\n * This matches the shape of the minimal model `listing_min.json` that is generated\n * by the `sde generate --list` command.\n *\n * @hidden This is not yet part of the public API; it is exposed here for\n * internal use only.\n */\nexport interface ModelListingSpecs {\n dimensions: {\n id: DimensionId\n subIds: SubscriptId[]\n }[]\n\n variables: {\n id: VarId\n index: number\n dimIds?: DimensionId[]\n }[]\n}\n\n/**\n * @hidden This is not yet part of the public API; it is exposed here for use\n * in experimental testing tools.\n */\nexport class ModelListing {\n public readonly varSpecs: Map<VarId, VarSpec> = new Map()\n\n constructor(listingObj: ModelListingSpecs) {\n // Put dimension info into a map for easier access\n const dimensions: Map<DimensionId, Dimension> = new Map()\n for (const dimInfo of listingObj.dimensions) {\n const dimId = dimInfo.id\n const subscripts: Subscript[] = []\n for (let i = 0; i < dimInfo.subIds.length; i++) {\n subscripts.push({\n id: dimInfo.subIds[i],\n index: i\n })\n }\n dimensions.set(dimId, {\n id: dimId,\n subscripts\n })\n }\n\n function dimensionForId(dimId: DimensionId): Dimension {\n const dim = dimensions.get(dimId)\n if (dim === undefined) {\n throw new Error(`No dimension info found for id=${dimId}`)\n }\n return dim\n }\n\n // Gather the set of unique variables (consolidating refs that have different\n // subscripts but refer to the same variable)\n const baseVarIds: Set<OutputVarId> = new Set()\n for (const v of listingObj.variables) {\n // Get the base name of the variable (without subscripts)\n const baseVarId = varIdWithoutSubscripts(v.id)\n\n if (!baseVarIds.has(baseVarId)) {\n // Look up dimensions from the map\n const dimIds: DimensionId[] = v.dimIds || []\n const dimensions = dimIds.map(dimensionForId)\n\n // Expand and add all combinations of subscripts\n if (dimensions.length > 0) {\n // The variable is subscripted\n const dimSubs: Subscript[][] = []\n for (const dim of dimensions) {\n // For each dimension, get the array of subscripts;\n // for example, if the dimension has 3 subscripts, push\n // an array like ['_a1', '_a2', '_a3']\n dimSubs.push(dim.subscripts)\n }\n const combos = cartesianProductOf(dimSubs)\n for (const combo of combos) {\n // Add a spec for this var+subscript(s)\n const subs = combo.map(sub => sub.id).join(',')\n const subIndices = combo.map(sub => sub.index)\n const fullVarId = `${baseVarId}[${subs}]`\n this.varSpecs.set(fullVarId, {\n varIndex: v.index,\n subscriptIndices: subIndices\n })\n }\n } else {\n // The variable is not subscripted\n this.varSpecs.set(baseVarId, {\n varIndex: v.index\n })\n }\n\n // Mark this variable as visited\n baseVarIds.add(baseVarId)\n }\n }\n }\n\n /**\n * Return the `VarSpec` for the given variable ID, or undefined if there is no spec defined\n * in the listing for that variable.\n */\n getSpecForVarId(varId: VarId): VarSpec | undefined {\n return this.varSpecs.get(varId)\n }\n\n /**\n * Return the `VarSpec` for the given variable name, or undefined if there is no spec defined\n * in the listing for that variable.\n */\n getSpecForVarName(varName: VarName): VarSpec | undefined {\n const varId = sdeVarIdForVensimVarName(varName)\n return this.varSpecs.get(varId)\n }\n\n /**\n * Create a new `Outputs` instance that uses the same start/end years as the given \"normal\"\n * `Outputs` instance but is prepared for reading the specified internal variables from the model.\n *\n * @param normalOutputs The `Outputs` that is used to access normal output variables from the model.\n * @param varIds The variable IDs to include with the new `Outputs` instance.\n */\n deriveOutputs(normalOutputs: Outputs, varIds: OutputVarId[]): Outputs {\n // Look up a `VarSpec` for each variable ID\n const varSpecs: VarSpec[] = []\n for (const varId of varIds) {\n const varSpec = this.varSpecs.get(varId)\n if (varSpec !== undefined) {\n varSpecs.push(varSpec)\n } else {\n // TODO: Throw error or just log warning?\n console.warn(`WARNING: No output var spec found for id=${varId}`)\n }\n }\n\n // Create a new `Outputs` instance that accepts the internal variables\n const newOutputs = new Outputs(varIds, normalOutputs.startTime, normalOutputs.endTime, normalOutputs.saveFreq)\n newOutputs.varSpecs = varSpecs\n return newOutputs\n }\n}\n\n/**\n * Helper function that returns the base name of a variable without the subscripts.\n */\nfunction varIdWithoutSubscripts(fullVarId: string): string {\n const bracketIndex = fullVarId.indexOf('[')\n if (bracketIndex >= 0) {\n return fullVarId.substring(0, bracketIndex)\n } else {\n return fullVarId\n }\n}\n\n/**\n * Return the cartesian product of the given array of arrays.\n *\n * For example, if we have an array that lists out two dimensions:\n * [ ['a1','a2'], ['b1','b2','b3'] ]\n * this function will return all the combinations, e.g.:\n * [ ['a1', 'b1'], ['a1', 'b2'], ['a1', 'b3'], ['a2', 'b1'], ... ]\n *\n * This can be used in place of nested for loops and has the benefit of working\n * for multi-dimensional inputs.\n */\nfunction cartesianProductOf<T>(arr: T[][]): T[][] {\n // Implementation based on: https://stackoverflow.com/a/36234242\n return arr.reduce(\n (a, b) => {\n return a.map(x => b.map(y => x.concat([y]))).reduce((v, w) => v.concat(w), [])\n },\n [[]]\n )\n}\n\n/**\n * Helper function that converts a Vensim variable or subscript name\n * into a valid C identifier as used by SDE.\n * TODO: Import helper function from `compile` package instead\n */\nfunction sdeVarIdForVensimName(name: string): string {\n return (\n '_' +\n name\n .trim()\n .replace(/\"/g, '_')\n .replace(/\\s+!$/g, '!')\n .replace(/\\s/g, '_')\n .replace(/,/g, '_')\n .replace(/-/g, '_')\n .replace(/\\./g, '_')\n .replace(/\\$/g, '_')\n .replace(/'/g, '_')\n .replace(/&/g, '_')\n .replace(/%/g, '_')\n .replace(/\\//g, '_')\n .replace(/\\|/g, '_')\n .toLowerCase()\n )\n}\n\n/**\n * Helper function that converts a Vensim variable name (possibly containing\n * subscripts) into a valid C identifier as used by SDE.\n * TODO: Import helper function from `compile` package instead\n */\nfunction sdeVarIdForVensimVarName(varName: string): string {\n const m = varName.match(/([^[]+)(?:\\[([^\\]]+)\\])?/)\n if (!m) {\n throw new Error(`Invalid Vensim name: ${varName}`)\n }\n let id = sdeVarIdForVensimName(m[1])\n if (m[2]) {\n const subscripts = m[2].split(',').map(x => sdeVarIdForVensimName(x))\n id += `[${subscripts.join(',')}]`\n }\n\n return id\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport type { VarRef, VarSpec } from '../_shared'\nimport type { ModelListing } from '../model-listing'\n\n/**\n * Resolve the provided variable reference using the `ModelListing` and variable name\n * or identifier.\n *\n * - If `varRef` has a defined `varSpec`, it is assumed to be valid.\n * - Otherwise, if `varRef` has a defined `varId`, it will be used to locate the\n * corresponding `varSpec` in the provided listing.\n * - Otherwise, if `varRef` has a defined `varName`, it will be used to locate the\n * corresponding `varSpec` in the provided listing.\n *\n * If the `varSpec` is found, this will set the `varSpec` property on the provided `varRef`.\n * Otherwise, this will throw an error.\n *\n * @hidden This is not part of the public API; it is exposed here for internal\n * use only.\n *\n * @param listing The model listing.\n * @param varRef The variable reference.\n * @param varKind The kind of variable (e.g., \"lookup\"), used to build an error message.\n */\nexport function resolveVarRef(listing: ModelListing | undefined, varRef: VarRef, varKind: string): VarSpec {\n if (varRef.varSpec) {\n // We assume the spec is valid\n // TODO: Should we validate the spec here?\n return\n }\n\n if (listing === undefined) {\n throw new Error(\n `Unable to resolve ${varKind} variable references by name or identifier when model listing is unavailable`\n )\n }\n\n if (varRef.varId) {\n const varSpec = listing?.getSpecForVarId(varRef.varId)\n if (varSpec) {\n varRef.varSpec = varSpec\n } else {\n throw new Error(`Failed to resolve ${varKind} variable reference for varId=${varRef.varId}`)\n }\n } else {\n const varSpec = listing?.getSpecForVarName(varRef.varName)\n if (varSpec) {\n varRef.varSpec = varSpec\n } else {\n throw new Error(`Failed to resolve ${varKind} variable reference for varName='${varRef.varId}'`)\n }\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport {\n decodeConstants,\n decodeLookups,\n encodeConstants,\n encodeLookups,\n encodeVarIndices,\n getEncodedConstantBufferLengths,\n getEncodedLookupBufferLengths,\n getEncodedVarIndicesLength\n} from '../_shared'\nimport type { ConstantDef, InputValue, LookupDef, Outputs } from '../_shared'\nimport type { ModelListing } from '../model-listing'\nimport { resolveVarRef } from './resolve-var-ref'\nimport type { RunModelOptions } from './run-model-options'\nimport type { RunModelParams } from './run-model-params'\n\nconst headerLengthInElements = 20\nconst extrasLengthInElements = 1\n\ninterface Section<ArrayType> {\n /** The view on the section of the `encoded` buffer, or undefined if the section is empty. */\n view?: ArrayType\n\n /** The byte offset of the section. */\n offsetInBytes: number\n\n /** The length (in elements) of the section. */\n lengthInElements: number\n\n /**\n * Update the view for this section.\n */\n update(encoded: ArrayBuffer, offsetInBytes: number, lengthInElements: number): void\n}\n\nclass Int32Section implements Section<Int32Array> {\n view?: Int32Array\n offsetInBytes = 0\n lengthInElements = 0\n update(encoded: ArrayBuffer, offsetInBytes: number, lengthInElements: number): void {\n this.view = lengthInElements > 0 ? new Int32Array(encoded, offsetInBytes, lengthInElements) : undefined\n this.offsetInBytes = offsetInBytes\n this.lengthInElements = lengthInElements\n }\n}\n\nclass Float64Section implements Section<Float64Array> {\n view?: Float64Array\n offsetInBytes = 0\n lengthInElements = 0\n update(encoded: ArrayBuffer, offsetInBytes: number, lengthInElements: number): void {\n this.view = lengthInElements > 0 ? new Float64Array(encoded, offsetInBytes, lengthInElements) : undefined\n this.offsetInBytes = offsetInBytes\n this.lengthInElements = lengthInElements\n }\n}\n\n/**\n * An implementation of `RunModelParams` that copies the input and output arrays into a single,\n * combined buffer. This implementation is designed to work with an asynchronous `ModelRunner`\n * implementation because the buffer can be transferred to/from a Web Worker or Node.js worker\n * thread without copying (if it is marked `Transferable`).\n *\n * @hidden This is not yet exposed in the public API; it is currently only used by\n * the implementations of the `RunnableModel` interface.\n */\nexport class BufferedRunModelParams implements RunModelParams {\n /**\n * The array that holds all input and output values. This is grown as needed. The memory\n * layout of the buffer is as follows:\n * header\n * extras (holds elapsed time, etc)\n * inputs\n * outputs\n * outputIndices\n * constants (values)\n * constantIndices\n * lookups (data)\n * lookupIndices\n */\n private encoded: ArrayBuffer\n\n /**\n * The header section of the `encoded` buffer. The header declares the byte offset and length\n * (in elements) of each section of the buffer.\n */\n private readonly header = new Int32Section()\n\n /** The extras section of the `encoded` buffer (holds elapsed time, etc). */\n private readonly extras = new Float64Section()\n\n /** The inputs section of the `encoded` buffer. */\n private readonly inputs = new Float64Section()\n\n /** The outputs section of the `encoded` buffer. */\n private readonly outputs = new Float64Section()\n\n /** The output indices section of the `encoded` buffer. */\n private readonly outputIndices = new Int32Section()\n\n /** The constant values section of the `encoded` buffer. */\n private readonly constants = new Float64Section()\n\n /** The constant indices section of the `encoded` buffer. */\n private readonly constantIndices = new Int32Section()\n\n /** The lookup data section of the `encoded` buffer. */\n private readonly lookups = new Float64Section()\n\n /** The lookup indices section of the `encoded` buffer. */\n private readonly lookupIndices = new Int32Section()\n\n /**\n * @param listing The model listing that is used to locate a variable that is referenced by\n * name or identifier. If undefined, variables cannot be referenced by name or identifier,\n * and can only be referenced using a valid `VarSpec`.\n */\n constructor(private readonly listing?: ModelListing) {}\n\n /**\n * Return the encoded buffer from this instance, which can be passed to `updateFromEncodedBuffer`.\n */\n getEncodedBuffer(): ArrayBuffer {\n return this.encoded\n }\n\n // from RunModelParams interface\n getInputs(): Float64Array | undefined {\n return this.inputs.view\n }\n\n // from RunModelParams interface\n copyInputs(array: Float64Array | undefined, create: (numElements: number) => Float64Array): void {\n if (this.inputs.lengthInElements === 0) {\n // Note that the inputs section will be empty if the inputs parameter is empty,\n // so we can skip copying in this case\n return\n }\n\n // Allocate (or reallocate) an array, if needed\n if (array === undefined || array.length < this.inputs.lengthInElements) {\n array = create(this.inputs.lengthInElements)\n }\n\n // Copy from the internal buffer to the array\n array.set(this.inputs.view)\n }\n\n // from RunModelParams interface\n getOutputIndicesLength(): number {\n return this.outputIndices.lengthInElements\n }\n\n // from RunModelParams interface\n getOutputIndices(): Int32Array | undefined {\n return this.outputIndices.view\n }\n\n // from RunModelParams interface\n copyOutputIndices(array: Int32Array | undefined, create: (numElements: number) => Int32Array): void {\n if (this.outputIndices.lengthInElements === 0) {\n // Note that the output indices section can be empty if the output indices are\n // not provided, so we can skip copying in this case\n return\n }\n\n // Allocate (or reallocate) an array, if needed\n if (array === undefined || array.length < this.outputIndices.lengthInElements) {\n array = create(this.outputIndices.lengthInElements)\n }\n\n // Copy from the internal buffer to the array\n array.set(this.outputIndices.view)\n }\n\n // from RunModelParams interface\n getOutputsLength(): number {\n return this.outputs.lengthInElements\n }\n\n // from RunModelParams interface\n getOutputs(): Float64Array | undefined {\n return this.outputs.view\n }\n\n // from RunModelParams interface\n getOutputsObject(): Outputs | undefined {\n // This implementation does not keep a reference to the original `Outputs` instance,\n // so we return undefined here\n return undefined\n }\n\n // from RunModelParams interface\n storeOutputs(array: Float64Array): void {\n if (this.outputs.view === undefined) {\n return\n }\n\n // Copy from the given array to the internal buffer. Note that the given array\n // can be longer than the internal buffer. This can happen in the case where the\n // model has an outputs buffer already allocated that was sized to accommodate a\n // certain amount of outputs, and then a later model run used a smaller amount of\n // outputs. In this case, the model may choose to keep the reuse the buffer\n // rather than reallocate/shrink the buffer, so we need to copy a subset here.\n if (array.length > this.outputs.view.length) {\n this.outputs.view.set(array.subarray(0, this.outputs.view.length))\n } else {\n this.outputs.view.set(array)\n }\n }\n\n // from RunModelParams interface\n getConstants(): ConstantDef[] | undefined {\n if (this.constantIndices.lengthInElements === 0) {\n return undefined\n }\n\n // Reconstruct the `ConstantDef` instances using the data from the constant values and\n // indices buffers\n return decodeConstants(this.constantIndices.view, this.constants.view)\n }\n\n // from RunModelParams interface\n getLookups(): LookupDef[] | undefined {\n if (this.lookupIndices.lengthInElements === 0) {\n return undefined\n }\n\n // Reconstruct the `LookupDef` instances using the data from the lookup data and\n // indices buffers\n return decodeLookups(this.lookupIndices.view, this.lookups.view)\n }\n\n // from RunModelParams interface\n getElapsedTime(): number {\n return this.extras.view[0]\n }\n\n // from RunModelParams interface\n storeElapsedTime(elapsed: number): void {\n // Store elapsed time in the extras section\n this.extras.view[0] = elapsed\n }\n\n /**\n * Copy the outputs buffer to the given `Outputs` instance. This should be called\n * after the `runModel` call has completed so that the output values are copied from\n * the internal buffer to the `Outputs` instance that was passed to `runModel`.\n *\n * @param outputs The `Outputs` instance into which the output values will be copied.\n */\n finalizeOutputs(outputs: Outputs): void {\n // Copy the output values to the `Outputs` instance\n if (this.outputs.view) {\n outputs.updateFromBuffer(this.outputs.view, outputs.seriesLength)\n }\n\n // Store the elapsed time value in the `Outputs` instance\n outputs.runTimeInMillis = this.getElapsedTime()\n }\n\n /**\n * Update this instance using the parameters that are passed to a `runModel` call.\n *\n * @param inputs The model input values (must be in the same order as in the spec file).\n * @param outputs The structure into which the model outputs will be stored.\n * @param options Additional options that influence the model run.\n */\n updateFromParams(inputs: number[] | InputValue[], outputs: Outputs, options?: RunModelOptions): void {\n // Determine the number of elements in the input and output sections\n const inputsLengthInElements = inputs.length\n const outputsLengthInElements = outputs.varIds.length * outputs.seriesLength\n\n // Determine the number of elements in the output indices section\n let outputIndicesLengthInElements: number\n const outputVarSpecs = outputs.varSpecs\n if (outputVarSpecs !== undefined && outputVarSpecs.length > 0) {\n // Compute the required length of the output indices buffer\n outputIndicesLengthInElements = getEncodedVarIndicesLength(outputVarSpecs)\n } else {\n // Don't use the output indices buffer when output var specs are not provided\n outputIndicesLengthInElements = 0\n }\n\n // Determine the number of elements in the constant values and indices sections\n let constantsLengthInElements: number\n let constantIndicesLengthInElements: number\n if (options?.constants !== undefined && options.constants.length > 0) {\n // Resolve the `varSpec` for each `ConstantDef`. If the variable can be resolved, this\n // will fill in the `varSpec` for the `ConstantDef`, otherwise it will throw an error.\n for (const constantDef of options.constants) {\n resolveVarRef(this.listing, constantDef.varRef, 'constant')\n }\n\n // Compute the required lengths\n const encodedLengths = getEncodedConstantBufferLengths(options.constants)\n constantsLengthInElements = encodedLengths.constantsLength\n constantIndicesLengthInElements = encodedLengths.constantIndicesLength\n } else {\n // Don't use the constant values and indices buffers when constant overrides are not provided\n constantsLengthInElements = 0\n constantIndicesLengthInElements = 0\n }\n\n // Determine the number of elements in the lookup data and indices sections\n let lookupsLengthInElements: number\n let lookupIndicesLengthInElements: number\n if (options?.lookups !== undefined && options.lookups.length > 0) {\n // Resolve the `varSpec` for each `LookupDef`. If the variable can be resolved, this\n // will fill in the `varSpec` for the `LookupDef`, otherwise it will throw an error.\n for (const lookupDef of options.lookups) {\n resolveVarRef(this.listing, lookupDef.varRef, 'lookup')\n }\n\n // Compute the required lengths\n const encodedLengths = getEncodedLookupBufferLengths(options.lookups)\n lookupsLengthInElements = encodedLengths.lookupsLength\n lookupIndicesLengthInElements = encodedLengths.lookupIndicesLength\n } else {\n // Don't use the lookup data and indices buffers when lookup overrides are not provided\n lookupsLengthInElements = 0\n lookupIndicesLengthInElements = 0\n }\n\n // Compute the byte offset and byte length of each section\n let byteOffset = 0\n function section(kind: 'float64' | 'int32', lengthInElements: number): number {\n // Start at the current byte offset\n const sectionOffsetInBytes = byteOffset\n\n // Compute the section length. We round up to ensure 8 byte alignment, which is needed in order\n // for each section's start offset to be aligned correctly.\n const bytesPerElement = kind === 'float64' ? Float64Array.BYTES_PER_ELEMENT : Int32Array.BYTES_PER_ELEMENT\n const requiredSectionLengthInBytes = Math.round(lengthInElements * bytesPerElement)\n const alignedSectionLengthInBytes = Math.ceil(requiredSectionLengthInBytes / 8) * 8\n byteOffset += alignedSectionLengthInBytes\n return sectionOffsetInBytes\n }\n const headerOffsetInBytes = section('int32', headerLengthInElements)\n const extrasOffsetInBytes = section('float64', extrasLengthInElements)\n const inputsOffsetInBytes = section('float64', inputsLengthInElements)\n const outputsOffsetInBytes = section('float64', outputsLengthInElements)\n const outputIndicesOffsetInBytes = section('int32', outputIndicesLengthInElements)\n const constantsOffsetInBytes = section('float64', constantsLengthInElements)\n const constantIndicesOffsetInBytes = section('int32', constantIndicesLengthInElements)\n const lookupsOffsetInBytes = section('float64', lookupsLengthInElements)\n const lookupIndicesOffsetInBytes = section('int32', lookupIndicesLengthInElements)\n\n // Get the total byte length\n const requiredLengthInBytes = byteOffset\n\n // Create or grow the buffer, if needed\n if (this.encoded === undefined || this.encoded.byteLength < requiredLengthInBytes) {\n // Add some extra space at the end of the buffer to allow for sections to grow a bit without\n // having to reallocate the entire buffer\n const totalLengthInBytes = Math.ceil(requiredLengthInBytes * 1.2)\n this.encoded = new ArrayBuffer(totalLengthInBytes)\n\n // Recreate the header view when the buffer changes\n this.header.update(this.encoded, headerOffsetInBytes, headerLengthInElements)\n }\n\n // Update the header\n const headerView = this.header.view\n let headerIndex = 0\n headerView[headerIndex++] = extrasOffsetInBytes\n headerView[headerIndex++] = extrasLengthInElements\n headerView[headerIndex++] = inputsOffsetInBytes\n headerView[headerIndex++] = inputsLengthInElements\n headerView[headerIndex++] = outputsOffsetInBytes\n headerView[headerIndex++] = outputsLengthInElements\n headerView[headerIndex++] = outputIndicesOffsetInBytes\n headerView[headerIndex++] = outputIndicesLengthInElements\n headerView[headerIndex++] = constantsOffsetInBytes\n headerView[headerIndex++] = constantsLengthInElements\n headerView[headerIndex++] = constantIndicesOffsetInBytes\n headerView[headerIndex++] = constantIndicesLengthInElements\n headerView[headerIndex++] = lookupsOffsetInBytes\n headerView[headerIndex++] = lookupsLengthInElements\n headerView[headerIndex++] = lookupIndicesOffsetInBytes\n headerView[headerIndex++] = lookupIndicesLengthInElements\n\n // Update the views\n // TODO: We can avoid recreating the views every time if buffer and section offset/length\n // haven't changed\n this.inputs.update(this.encoded, inputsOffsetInBytes, inputsLengthInElements)\n this.extras.update(this.encoded, extrasOffsetInBytes, extrasLengthInElements)\n this.outputs.update(this.encoded, outputsOffsetInBytes, outputsLengthInElements)\n this.outputIndices.update(this.encoded, outputIndicesOffsetInBytes, outputIndicesLengthInElements)\n this.constants.update(this.encoded, constantsOffsetInBytes, constantsLengthInElements)\n this.constantIndices.update(this.encoded, constantIndicesOffsetInBytes, constantIndicesLengthInElements)\n this.lookups.update(this.encoded, lookupsOffsetInBytes, lookupsLengthInElements)\n this.lookupIndices.update(this.encoded, lookupIndicesOffsetInBytes, lookupIndicesLengthInElements)\n\n // Copy the input values into the internal buffer\n // TODO: Throw an error if inputs.length is less than number of inputs declared\n // in the spec (only in the case where useInputIndices is false)\n const inputsView = this.inputs.view\n for (let i = 0; i < inputs.length; i++) {\n // XXX: The `inputs` array type used to be declared as `InputValue[]`, so some users\n // may be relying on that, but it has now been simplified to `number[]`. For the time\n // being, we will allow for either type and choose which one depending on the shape of\n // the array elements.\n const input = inputs[i]\n if (typeof input === 'number') {\n inputsView[i] = input\n } else {\n inputsView[i] = input.get()\n }\n }\n\n // Copy the the output indices into the internal buffer, if needed\n if (this.outputIndices.view) {\n encodeVarIndices(outputVarSpecs, this.outputIndices.view)\n }\n\n // Copy the constant values and indices into the internal buffers, if needed\n if (constantIndicesLengthInElements > 0) {\n encodeConstants(options.constants, this.constantIndices.view, this.constants.view)\n }\n\n // Copy the lookup data and indices into the internal buffers, if needed\n if (lookupIndicesLengthInElements > 0) {\n encodeLookups(options.lookups, this.lookupIndices.view, this.lookups.view)\n }\n }\n\n /**\n * Update this instance using the values contained in the encoded buffer from another\n * `BufferedRunModelParams` instance.\n *\n * @param buffer An encoded buffer returned by `getEncodedBuffer`.\n */\n updateFromEncodedBuffer(buffer: ArrayBuffer): void {\n // Verify that the buffer is long enough to contain the header section\n const headerLengthInBytes = headerLengthInElements * Int32Array.BYTES_PER_ELEMENT\n if (buffer.byteLength < headerLengthInBytes) {\n throw new Error('Buffer must be long enough to contain header section')\n }\n\n // Set the buffer\n this.encoded = buffer\n\n // Rebuild the header\n const headerOffsetInBytes = 0\n this.header.update(this.encoded, headerOffsetInBytes, headerLengthInElements)\n\n // Get the section offsets and lengths from the header\n const headerView = this.header.view\n let headerIndex = 0\n const extrasOffsetInBytes = headerView[headerIndex++]\n const extrasLengthInElements = headerView[headerIndex++]\n const inputsOffsetInBytes = headerView[headerIndex++]\n const inputsLengthInElements = headerView[headerIndex++]\n const outputsOffsetInBytes = headerView[headerIndex++]\n const outputsLengthInElements = headerView[headerIndex++]\n const outputIndicesOffsetInBytes = headerView[headerIndex++]\n const outputIndicesLengthInElements = headerView[headerIndex++]\n const constantsOffsetInBytes = headerView[headerIndex++]\n const constantsLengthInElements = headerView[headerIndex++]\n const constantIndicesOffsetInBytes = headerView[headerIndex++]\n const constantIndicesLengthInElements = headerView[headerIndex++]\n const lookupsOffsetInBytes = headerView[headerIndex++]\n const lookupsLengthInElements = headerView[headerIndex++]\n const lookupIndicesOffsetInBytes = headerView[headerIndex++]\n const lookupIndicesLengthInElements = headerView[headerIndex++]\n\n // Verify that the buffer is long enough to contain all sections\n const extrasLengthInBytes = extrasLengthInElements * Float64Array.BYTES_PER_ELEMENT\n const inputsLengthInBytes = inputsLengthInElements * Float64Array.BYTES_PER_ELEMENT\n const outputsLengthInBytes = outputsLengthInElements * Float64Array.BYTES_PER_ELEMENT\n const outputIndicesLengthInBytes = outputIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT\n const constantsLengthInBytes = constantsLengthInElements * Float64Array.BYTES_PER_ELEMENT\n const constantIndicesLengthInBytes = constantIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT\n const lookupsLengthInBytes = lookupsLengthInElements * Float64Array.BYTES_PER_ELEMENT\n const lookupIndicesLengthInBytes = lookupIndicesLengthInElements * Int32Array.BYTES_PER_ELEMENT\n const requiredLengthInBytes =\n headerLengthInBytes +\n extrasLengthInBytes +\n inputsLengthInBytes +\n outputsLengthInBytes +\n outputIndicesLengthInBytes +\n constantsLengthInBytes +\n constantIndicesLengthInBytes +\n lookupsLengthInBytes +\n lookupIndicesLengthInBytes\n if (buffer.byteLength < requiredLengthInBytes) {\n throw new Error('Buffer must be long enough to contain sections declared in header')\n }\n\n // Rebuild the sections according to the section offsets and lengths in the header\n this.extras.update(this.encoded, extrasOffsetInBytes, extrasLengthInElements)\n this.inputs.update(this.encoded, inputsOffsetInBytes, inputsLengthInElements)\n this.outputs.update(this.encoded, outputsOffsetInBytes, outputsLengthInElements)\n this.outputIndices.update(this.encoded, outputIndicesOffsetInBytes, outputIndicesLengthInElements)\n this.constants.update(this.encoded, constantsOffsetInBytes, constantsLengthInElements)\n this.constantIndices.update(this.encoded, constantIndicesOffsetInBytes, constantIndicesLengthInElements)\n this.lookups.update(this.encoded, lookupsOffsetInBytes, lookupsLengthInElements)\n this.lookupIndices.update(this.encoded, lookupIndicesOffsetInBytes, lookupIndicesLengthInElements)\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport type { ConstantDef, InputValue, LookupDef, Outputs } from '../_shared'\nimport { encodeVarIndices, getEncodedVarIndicesLength } from '../_shared'\nimport type { ModelListing } from '../model-listing'\nimport { resolveVarRef } from './resolve-var-ref'\nimport type { RunModelOptions } from './run-model-options'\nimport type { RunModelParams } from './run-model-params'\n\n/**\n * An implementation of `RunModelParams` that keeps references to the `inputs` and\n * `outputs` parameters that are passed to the `runModel` function. This implementation\n * is best used with a synchronous `ModelRunner`.\n *\n * @hidden This is not yet exposed in the public API; it is currently only used by\n * the implementations of the `RunnableModel` interface.\n */\nexport class ReferencedRunModelParams implements RunModelParams {\n private inputs: number[] | InputValue[]\n private outputs: Outputs\n private outputsLengthInElements = 0\n private outputIndicesLengthInElements = 0\n private constants: ConstantDef[]\n private lookups: LookupDef[]\n\n /**\n * @param listing The model listing that is used to locate a variable that is referenced by\n * name or identifier. If undefined, variables cannot be referenced by name or identifier,\n * and can only be referenced using a valid `VarSpec`.\n */\n constructor(private readonly listing?: ModelListing) {}\n\n // from RunModelParams interface\n getInputs(): Float64Array | undefined {\n // This implementation does not keep a buffer of inputs, so we return undefined here\n return undefined\n }\n\n // from RunModelParams interface\n copyInputs(array: Float64Array | undefined, create: (numElements: number) => Float64Array): void {\n // Allocate (or reallocate) an array, if needed\n const inputsLengthInElements = this.inputs.length\n if (array === undefined || array.length < inputsLengthInElements) {\n array = create(inputsLengthInElements)\n }\n\n // Copy the input values into the provided array\n for (let i = 0; i < this.inputs.length; i++) {\n // XXX: The `inputs` array type used to be declared as `InputValue[]`, so some users\n // may be relying on that, but it has now been simplified to `number[]`. For the time\n // being, we will allow for either type and choose which one depending on the shape of\n // the array elements.\n const input = this.inputs[i]\n if (typeof input === 'number') {\n array[i] = input\n } else {\n array[i] = input.get()\n }\n }\n }\n\n // from RunModelParams interface\n getOutputIndicesLength(): number {\n return this.outputIndicesLengthInElements\n }\n\n // from RunModelParams interface\n getOutputIndices(): Int32Array | undefined {\n // This implementation does not keep a buffer of indices, so we return undefined here\n return undefined\n }\n\n // from RunModelParams interface\n copyOutputIndices(array: Int32Array | undefined, create: (numElements: number) => Int32Array): void {\n if (this.outputIndicesLengthInElements === 0) {\n return\n }\n\n // Allocate (or reallocate) an array, if needed\n if (array === undefined || array.length < this.outputIndicesLengthInElements) {\n array = create(this.outputIndicesLengthInElements)\n }\n\n // Copy the output indices to the provided array\n encodeVarIndices(this.outputs.varSpecs, array)\n }\n\n // from RunModelParams interface\n getOutputsLength(): number {\n return this.outputsLengthInElements\n }\n\n // from RunModelParams interface\n getOutputs(): Float64Array | undefined {\n // This implementation does not keep a buffer of outputs, so we return undefined here\n return undefined\n }\n\n // from RunModelParams interface\n getOutputsObject(): Outputs | undefined {\n return this.outputs\n }\n\n // from RunModelParams interface\n storeOutputs(array: Float64Array): void {\n // Update the `Outputs` instance with the values from the given array\n if (this.outputs) {\n const result = this.outputs.updateFromBuffer(array, this.outputs.seriesLength)\n if (result.isErr()) {\n throw new Error(`Failed to store outputs: ${result.error}`)\n }\n }\n }\n\n // from RunModelParams interface\n getConstants(): ConstantDef[] | undefined {\n if (this.constants !== undefined && this.constants.length > 0) {\n return this.constants\n } else {\n return undefined\n }\n }\n\n // from RunModelParams interface\n getLookups(): LookupDef[] | undefined {\n if (this.lookups !== undefined && this.lookups.length > 0) {\n return this.lookups\n } else {\n return undefined\n }\n }\n\n // from RunModelParams interface\n getElapsedTime(): number {\n return this.outputs?.runTimeInMillis\n }\n\n // from RunModelParams interface\n storeElapsedTime(elapsed: number): void {\n // Store the elapsed time value in the `Outputs` instance\n if (this.outputs) {\n this.outputs.runTimeInMillis = elapsed\n }\n }\n\n /**\n * Update this instance using the parameters that are passed to a `runModel` call.\n *\n * @param inputs The model input values (must be in the same order as in the spec file).\n * @param outputs The structure into which the model outputs will be stored.\n * @param options Additional options that influence the model run.\n */\n updateFromParams(inputs: number[] | InputValue[], outputs: Outputs, options?: RunModelOptions): void {\n // Save the latest parameters; these values will be accessed by the `RunnableModel`\n // on demand (e.g., in the `copyInputs` method)\n this.inputs = inputs\n this.outputs = outputs\n this.outputsLengthInElements = outputs.varIds.length * outputs.seriesLength\n this.constants = options?.constants\n this.lookups = options?.lookups\n\n if (this.constants) {\n // Resolve the `varSpec` for each `ConstantDef`. If the variable can be resolved, this\n // will fill in the `varSpec` for the `ConstantDef`, otherwise it will throw an error.\n for (const constantDef of this.constants) {\n resolveVarRef(this.listing, constantDef.varRef, 'constant')\n }\n }\n\n if (this.lookups) {\n // Resolve the `varSpec` for each `LookupDef`. If the variable can be resolved, this\n // will fill in the `varSpec` for the `LookupDef`, otherwise it will throw an error.\n for (const lookupDef of this.lookups) {\n resolveVarRef(this.listing, lookupDef.varRef, 'lookup')\n }\n }\n\n // See if the output indices are needed\n const outputVarSpecs = outputs.varSpecs\n if (outputVarSpecs !== undefined && outputVarSpecs.length > 0) {\n // Compute the required length of the output indices buffer\n this.outputIndicesLengthInElements = getEncodedVarIndicesLength(outputVarSpecs)\n } else {\n // Don't use the output indices buffer when output var specs are not provided\n this.outputIndicesLengthInElements = 0\n }\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\n// This matches Vensim's definition of `:NA:`. It is also defined\n// with the same value in the generated `JsModel`, so make sure\n// these two values are the same.\nexport const _NA_ = -Number.MAX_VALUE\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { _NA_ } from './js-model-constants'\n\nexport type JsModelLookupMode = 'interpolate' | 'forward' | 'backward'\n\n/**\n * @hidden This is not yet part of the public API; for internal use only.\n */\nexport class JsModelLookup {\n /** The original data passed to the constructor. */\n private readonly originalData: number[] | Float64Array | undefined\n\n /** The size (i.e., number of pairs) of the original data. */\n private readonly originalSize: number\n\n /**\n * The dynamic data array. This will be undefined initially, and the array\n * will be allocated (or grown) by `setData`.\n */\n private dynamicData: Float64Array | undefined\n\n /** The size (i.e., number of pairs) of the dynamic data. */\n private dynamicSize: number\n\n /**\n * The active data array. This will be the same as either `originalData`\n * or `dynamicData`, depending on whether the lookup data is overridden\n * at runtime using `setData`.\n */\n private activeData: number[] | Float64Array | undefined\n\n /** The size (i.e., number of pairs) of the active data. */\n private activeSize: number\n\n /**\n * The inverted version of the active data array. This is allocated on demand\n * only in the case of `LOOKUP INVERT` function calls.\n */\n private invertedData?: number[]\n\n /**\n * The input value for the last hit. This is cached for performance so that we\n * can reduce the amount of linear searching in the common case where `LOOKUP`\n * input values are monotonically increasing.\n */\n private lastInput: number\n\n /** The index for the last hit (see `lastInput`). */\n private lastHitIndex: number\n\n /**\n * @param size The number of (x,y) pairs in the lookup.\n * @param data The lookup data, as (x,y) pairs. The length of the array must be\n * >= 2*n. Note that the data will be stored by reference, so if there is a chance\n * that the array will be reused or modified by other code, be sure to pass in a\n * copy of the array.\n */\n constructor(size: number, data: number[] | Float64Array | undefined) {\n // Note that we reference the provided data without copying (assumed to be owned elsewhere)\n if (data && data.length < size * 2) {\n throw new Error(`Lookup data array length must be >= 2*size (length=${data.length} size=${size}`)\n }\n\n this.originalData = data\n this.originalSize = size\n\n this.dynamicData = undefined\n this.dynamicSize = 0\n\n this.activeData = this.originalData\n this.activeSize = this.originalSize\n\n this.lastInput = Number.MAX_VALUE\n this.lastHitIndex = 0\n }\n\n /**\n * Set new data for this lookup instance, or restore the original data.\n *\n * If `data` is undefined, the original data that was supplied to the constructor will\n * be restored as the \"active\" data. Otherwise, `data` will be copied to an internal\n * data buffer, which will be the \"active\" data. If `size` is greater than the size\n * passed to previous calls, the internal data buffer will be grown as needed.\n *\n * @param size The number of (x,y) pairs in the lookup.\n * @param data The lookup data, as (x,y) pairs. The length of the array must be\n * >= 2*n. Note that the data will be copied into an internal data buffer, so it\n * is not necessary to defensively copy data before calling this method.\n */\n public setData(size: number, data: Float64Array | undefined): void {\n if (data) {\n if (data.length < size * 2) {\n throw new Error(`Lookup data array length must be >= 2*size (length=${data.length} size=${size}`)\n }\n\n // Allocate or grow the internal buffer as needed\n const dataLengthInElems = size * 2\n if (this.dynamicData === undefined || dataLengthInElems > this.dynamicData.length) {\n this.dynamicData = new Float64Array(dataLengthInElems)\n }\n\n // Copy the given lookup data into the internally managed buffer\n this.dynamicSize = size\n if (size > 0) {\n const subarray = data.subarray(0, dataLengthInElems)\n this.dynamicData.set(subarray)\n }\n\n // Set the dynamic data as the \"active\" data\n this.activeData = this.dynamicData\n this.activeSize = this.dynamicSize\n } else {\n // Restore the original data as the \"active\" data\n this.activeData = this.originalData\n this.activeSize = this.originalSize\n }\n\n // Clear the cached inverted data\n this.invertedData = undefined\n\n // Reset the cached \"last\" values to the initial values\n this.lastInput = Number.MAX_VALUE\n this.lastHitIndex = 0\n }\n\n public getValueForX(x: number, mode: JsModelLookupMode): number {\n return this.getValue(x, false, mode)\n }\n\n public getValueForY(y: number): number {\n if (this.invertedData === undefined) {\n // Invert the matrix and cache it\n const numValues = this.activeSize * 2\n const normalData = this.activeData\n const invertedData = Array(numValues)\n for (let i = 0; i < numValues; i += 2) {\n invertedData[i] = normalData[i + 1]\n invertedData[i + 1] = normalData[i]\n }\n this.invertedData = invertedData\n }\n return this.getValue(y, true, 'interpolate')\n }\n\n /**\n * Interpolate the y value from the array of (x,y) pairs.\n * NOTE: The x values are assumed to be monotonically increasing.\n */\n private getValue(input: number, useInvertedData: boolean, mode: JsModelLookupMode): number {\n if (this.activeSize === 0) {\n return _NA_\n }\n\n const data = useInvertedData ? this.invertedData : this.activeData\n const max = this.activeSize * 2\n\n // Use the cached values for improved lookup performance, except in the case\n // of `LOOKUP INVERT` (since it may not be accurate if calls flip back and forth\n // between inverted and non-inverted data)\n const useCachedValues = !useInvertedData\n let startIndex: number\n if (useCachedValues && input >= this.lastInput) {\n startIndex = this.lastHitIndex\n } else {\n startIndex = 0\n }\n\n for (let xi = startIndex; xi < max; xi += 2) {\n const x = data[xi]\n if (x >= input) {\n // We went past the input, or hit it exactly\n if (useCachedValues) {\n this.lastInput = input\n this.lastHitIndex = xi\n }\n\n if (xi === 0 || x === input) {\n // The input is less than the first x, or this x equals the input; return the\n // associated y without interpolation\n return data[xi + 1]\n }\n\n // Calculate the y value depending on the lookup mode\n switch (mode) {\n default:\n case 'interpolate': {\n // Interpolate along the line from the last (x,y)\n const last_x = data[xi - 2]\n const last_y = data[xi - 1]\n const y = data[xi + 1]\n const dx = x - last_x\n const dy = y - last_y\n return last_y + (dy / dx) * (input - last_x)\n }\n case 'forward':\n // Return the next y value without interpolating\n return data[xi + 1]\n case 'backward':\n // Return the previous y value without interpolating\n return data[xi - 1]\n }\n }\n }\n\n // The input is greater than all the x values, so return the high end of the range\n if (useCachedValues) {\n this.lastInput = input\n this.lastHitIndex = max\n }\n return data[max - 1]\n }\n\n /**\n * Return the most appropriate y value from the array of (x,y) pairs when\n * this instance is used to provide inputs for the `GAME` function.\n *\n * NOTE: The x values are assumed to be monotonically increasing.\n *\n * This method is similar to `getValueForX` in concept, except that this one\n * returns the provided `defaultValue` if the `time` parameter is earlier than\n * the first data point in the lookup. Also, this method always uses the\n * `backward` interpolation mode, meaning that it holds the \"current\" value\n * constant instead of interpolating.\n *\n * @param time The time that is used to select the data point that has an\n * `x` value less than or equal to the provided time.\n * @param defaultValue The value that is returned if this lookup is empty (has\n * no points) or if the provided time is earlier than the first data point.\n */\n public getValueForGameTime(time: number, defaultValue: number): number {\n if (this.activeSize <= 0) {\n // The lookup is empty, so return the default value\n return defaultValue\n }\n\n const x0 = this.activeData[0]\n if (time < x0) {\n // The provided time is earlier than the first data point, so return the\n // default value\n return defaultValue\n }\n\n // For all other cases, we can use `getValue` with `backward` mode\n return this.getValue(time, false, 'backward')\n }\n\n /**\n * Interpolate the y value from the array of (x,y) pairs.\n * NOTE: The x values are assumed to be monotonically increasing.\n *\n * This method is similar to `getValue` in concept, but Vensim produces results for\n * the `GET DATA BETWEEN TIMES` function that differ in unexpected ways from normal\n * lookup behavior, so we implement it as a separate method here.\n */\n public getValueBetweenTimes(input: number, mode: JsModelLookupMode): number {\n if (this.activeSize === 0) {\n return _NA_\n }\n\n const data = this.activeData\n const max = this.activeSize * 2\n\n switch (mode) {\n case 'forward': {\n // Vensim appears to round non-integral input values down to a whole number\n // when mode is 1 (look forward), so we will do the same\n input = Math.floor(input)\n for (let xi = 0; xi < max; xi += 2) {\n const x = data[xi]\n if (x >= input) {\n return data[xi + 1]\n }\n }\n return data[max - 1]\n }\n case 'backward': {\n // Vensim appears to round non-integral input values down to a whole number\n // when mode is -1 (hold backward), so we will do the same\n input = Math.floor(input)\n for (let xi = 2; xi < max; xi += 2) {\n const x = data[xi]\n if (x >= input) {\n return data[xi - 1]\n }\n }\n if (max >= 4) {\n return data[max - 3]\n } else {\n return data[1]\n }\n }\n case 'interpolate':\n default: {\n // NOTE: This function produces results that match Vensim output for GET DATA BETWEEN TIMES with a\n // mode of 0 (interpolate), but only when the input values are integral (whole numbers). If the\n // input value is fractional, Vensim produces bizarre/unexpected interpolated values.\n // TODO: For now we throw an error, but ideally we would match the Vensim results exactly.\n if (input - Math.floor(input) > 0) {\n let msg = `GET DATA BETWEEN TIMES was called with an input value (${input}) that has a fractional part. `\n msg += 'When mode is 0 (interpolate) and the input value is not a whole number, Vensim produces unexpected '\n msg += 'results that may differ from those produced by SDEverywhere.'\n throw new Error(msg)\n }\n for (let xi = 2; xi < max; xi += 2) {\n const x = data[xi]\n if (x >= input) {\n const last_x = data[xi - 2]\n const last_y = data[xi - 1]\n const y = data[xi + 1]\n const dx = x - last_x\n const dy = y - last_y\n return last_y + (dy / dx) * (input - last_x)\n }\n }\n return data[max - 1]\n }\n }\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { _NA_ } from './js-model-constants'\nimport { JsModelLookup, type JsModelLookupMode } from './js-model-lookup'\n\n// See XIDZ documentation for an explanation of this value:\n// https://www.vensim.com/documentation/fn_xidz.html\nconst EPSILON = 1e-6\n\n/**\n * Provides access to the minimal set of control parameters that are used in the\n * implementation of certain model functions.\n *\n * @hidden This is not yet part of the public API; for internal use by generated\n * `JsModel` implementations.\n */\nexport interface JsModelFunctionContext {\n timeStep: number\n currentTime: number\n}\n\n/**\n * Exposes all the model function implementations that are called by a `JsModel` at runtime.\n *\n * @hidden This is not yet part of the public API; for internal use by generated\n * `JsModel` implementations.\n */\nexport interface JsModelFunctions {\n setContext(context: JsModelFunctionContext): void\n\n ABS(x: number): number\n ARCCOS(x: number): number\n ARCSIN(x: number): number\n ARCTAN(x: number): number\n COS(x: number): number\n EXP(x: number): number\n GAME(inputs: JsModelLookup, x: number): number\n // TODO\n // GAMMA_LN(x: number): number\n INTEG(value: number, rate: number): number\n INTEGER(x: number): number\n LN(x: number): number\n MAX(x: number, y: number): number\n MIN(x: number, y: number): number\n MODULO(x: number, y: number): number\n POW(x: number, y: number): number\n POWER(x: number, y: number): number\n PULSE(start: number, width: number): number\n PULSE_TRAIN(start: number, width: number, interval: number, end: number): number\n QUANTUM(x: number, y: number): number\n RAMP(slope: number, startTime: number, endTime: number): number\n SIN(x: number): number\n SQRT(x: number): number\n STEP(height: number, stepTime: number): number\n TAN(x: number): number\n VECTOR_SORT_ORDER(vector: number[], size: number, direction: number): number[]\n XIDZ(a: number, b: number, x: number): number\n ZIDZ(a: number, b: number): number\n\n createLookup(size: number, data: number[] | Float64Array): JsModelLookup\n LOOKUP(lookup: JsModelLookup, x: number): number\n LOOKUP_FORWARD(lookup: JsModelLookup, x: number): number\n LOOKUP_BACKWARD(lookup: JsModelLookup, x: number): number\n LOOKUP_INVERT(lookup: JsModelLookup, y: number): number\n WITH_LOOKUP(x: number, lookup: JsModelLookup): number\n GET_DATA_BETWEEN_TIMES(lookup: JsModelLookup, x: number, mode: number): number\n\n // TODO\n // createFixedDelay(delayTime: number, initialValue: number): FixedDelay\n // DELAY_FIXED(input: number, fixedDelay: FixedDelay): number\n\n // TODO\n // createDepreciation(dtime: number, initialValue: number): Depreciation\n // DEPRECIATE_STRAIGHTLINE(input: number, depreciation: Depreciation): number\n}\n\n/**\n * Returns a default implementation of the `JsModelFunctions` interface. If needed,\n * you can provide a custom implementation of any exposed function by overriding\n * (setting) a new function implementation on the returned instance.\n *\n * @hidden This is not yet part of the public API; for internal use by generated\n * `JsModel` implementations.\n */\nexport function getJsModelFunctions(): JsModelFunctions {\n let ctx: JsModelFunctionContext\n\n // The C implementation of `_VECTOR_SORT_ORDER` reuses an array, so we\n // will do the same for now (one reused array per size)\n const cachedVectors: Map<number, number[]> = new Map()\n const cachedSortVectors: Map<number, { x: number; ind: number }[]> = new Map()\n\n return {\n setContext(context: JsModelFunctionContext) {\n ctx = context\n },\n\n ABS(x: number): number {\n return Math.abs(x)\n },\n\n ARCCOS(x: number): number {\n return Math.acos(x)\n },\n\n ARCSIN(x: number): number {\n return Math.asin(x)\n },\n\n ARCTAN(x: number): number {\n return Math.atan(x)\n },\n\n COS(x: number): number {\n return Math.cos(x)\n },\n\n EXP(x: number): number {\n return Math.exp(x)\n },\n\n GAME(inputs: JsModelLookup, x: number): number {\n return inputs ? inputs.getValueForGameTime(ctx.currentTime, x) : x\n },\n\n // GAMMA_LN(): number {\n // throw new Error('GAMMA_LN function not yet implemented for JS target')\n // },\n\n INTEG(value: number, rate: number): number {\n return value + rate * ctx.timeStep\n },\n\n INTEGER(x: number): number {\n return Math.trunc(x)\n },\n\n LN(x: number): number {\n return Math.log(x)\n },\n\n MAX(x: number, y: number): number {\n return Math.max(x, y)\n },\n\n MIN(x: number, y: number): number {\n return Math.min(x, y)\n },\n\n MODULO(x: number, y: number): number {\n return x % y\n },\n\n POW(x: number, y: number): number {\n return Math.pow(x, y)\n },\n\n POWER(x: number, y: number): number {\n return Math.pow(x, y)\n },\n\n PULSE(start: number, width: number): number {\n return pulse(ctx, start, width)\n },\n\n PULSE_TRAIN(start: number, width: number, interval: number, end: number): number {\n const n = Math.floor((end - start) / interval)\n for (let k = 0; k <= n; k++) {\n if (ctx.currentTime <= end && pulse(ctx, start + k * interval, width)) {\n return 1.0\n }\n }\n return 0.0\n },\n\n QUANTUM(x: number, y: number): number {\n return y <= 0 ? x : y * Math.trunc(x / y)\n },\n\n RAMP(slope: number, startTime: number, endTime: number): number {\n // Return 0 until the start time is exceeded.\n // Interpolate from start time to end time.\n // Hold at the end time value.\n // Allow start time > end time.\n if (ctx.currentTime > startTime) {\n if (ctx.currentTime < endTime || startTime > endTime) {\n return slope * (ctx.currentTime - startTime)\n } else {\n return slope * (endTime - startTime)\n }\n } else {\n return 0.0\n }\n },\n\n SIN(x: number): number {\n return Math.sin(x)\n },\n\n SQRT(x: number): number {\n return Math.sqrt(x)\n },\n\n STEP(height: number, stepTime: number): number {\n return ctx.currentTime + ctx.timeStep / 2.0 > stepTime ? height : 0.0\n },\n\n TAN(x: number): number {\n return Math.tan(x)\n },\n\n VECTOR_SORT_ORDER(vector: number[], size: number, direction: number): number[] {\n // Validate arguments\n if (size > vector.length) {\n throw new Error(`VECTOR SORT ORDER input vector length (${vector.length}) must be >= size (${size})`)\n }\n\n // Get a cached sort vector\n let sortVector = cachedSortVectors.get(size)\n if (sortVector === undefined) {\n sortVector = Array(size)\n for (let i = 0; i < size; i++) {\n sortVector[i] = { x: 0, ind: 0 }\n }\n cachedSortVectors.set(size, sortVector)\n }\n\n // Get a cached output array\n let outArray = cachedVectors.get(size)\n if (outArray === undefined) {\n outArray = Array(size)\n cachedVectors.set(size, outArray)\n }\n\n // Prepare for sorting\n for (let i = 0; i < size; i++) {\n sortVector[i].x = vector[i]\n sortVector[i].ind = i\n }\n\n // Sort in place\n const sortOrder = direction > 0 ? 1 : -1\n sortVector.sort((a, b) => {\n let result: number\n if (a.x < b.x) {\n result = -1\n } else if (a.x > b.x) {\n result = 1\n } else {\n result = 0\n }\n return result * sortOrder\n })\n\n // Copy the sorted index values into the output array\n for (let i = 0; i < size; i++) {\n outArray[i] = sortVector[i].ind\n }\n\n return outArray\n },\n\n XIDZ(a: number, b: number, x: number): number {\n return Math.abs(b) < EPSILON ? x : a / b\n },\n\n ZIDZ(a: number, b: number): number {\n if (Math.abs(b) < EPSILON) {\n return 0.0\n } else {\n return a / b\n }\n },\n\n //\n // Lookup functions\n //\n\n createLookup(size: number, data: number[] | Float64Array): JsModelLookup {\n return new JsModelLookup(size, data)\n },\n\n LOOKUP(lookup: JsModelLookup, x: number): number {\n return lookup ? lookup.getValueForX(x, 'interpolate') : _NA_\n },\n\n LOOKUP_FORWARD(lookup: JsModelLookup, x: number): number {\n return lookup ? lookup.getValueForX(x, 'forward') : _NA_\n },\n\n LOOKUP_BACKWARD(lookup: JsModelLookup, x: number): number {\n return lookup ? lookup.getValueForX(x, 'backward') : _NA_\n },\n\n LOOKUP_INVERT(lookup: JsModelLookup, y: number): number {\n return lookup ? lookup.getValueForY(y) : _NA_\n },\n\n WITH_LOOKUP(x: number, lookup: JsModelLookup): number {\n return lookup ? lookup.getValueForX(x, 'interpolate') : _NA_\n },\n\n GET_DATA_BETWEEN_TIMES(lookup: JsModelLookup, x: number, mode: number): number {\n let lookupMode: JsModelLookupMode\n if (mode >= 1) {\n lookupMode = 'forward'\n } else if (mode <= -1) {\n lookupMode = 'backward'\n } else {\n lookupMode = 'interpolate'\n }\n return lookup ? lookup.getValueBetweenTimes(x, lookupMode) : _NA_\n }\n }\n}\n\nfunction pulse(ctx: JsModelFunctionContext, start: number, width: number): number {\n const timePlus = ctx.currentTime + ctx.timeStep / 2.0\n if (width === 0.0) {\n width = ctx.timeStep\n }\n return timePlus > start && timePlus < start + width ? 1.0 : 0.0\n}\n","// Copyright (c) 2021-2022 Climate Interactive / New Venture Fund\n\nlet isWeb: boolean\n\n/**\n * Return a timestamp that can be passed to `perfElapsed` for calculating the elapsed\n * time of an operation.\n *\n * @hidden This is not part of the public API; exposed only for use in performance testing.\n */\nexport function perfNow(): unknown {\n // Note that `self` resolves to the window (in browser context) or the worker global scope\n // (in a Web Worker context)\n if (isWeb === undefined) {\n isWeb = typeof self !== 'undefined' && self?.performance !== undefined\n }\n if (isWeb) {\n return self.performance.now()\n } else {\n // XXX: We only use `process` in two places; we bypass type checking instead of\n // setting up type declarations\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return process?.hrtime()\n }\n}\n\n/**\n * Return the elapsed time between the given timestamp (created by `perfNow`) and now.\n *\n * @hidden This is not part of the public API; exposed only for use in performance testing.\n */\nexport function perfElapsed(t0: unknown): number {\n if (isWeb) {\n const t1 = self.performance.now()\n return (t1 as number) - (t0 as number)\n } else {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const elapsed = process.hrtime(t0) as number[]\n // Convert from nanoseconds to milliseconds\n return (elapsed[0] * 1000000000 + elapsed[1]) / 1000000\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport type { ConstantDef, LookupDef, OutputVarId } from '../_shared'\nimport type { ModelListing } from '../model-listing'\nimport { perfElapsed, perfNow } from '../perf'\nimport type { RunModelParams } from './run-model-params'\nimport type { RunnableModel } from './runnable-model'\n\n/**\n * @hidden This is not part of the public API; for internal use only.\n */\nexport type OnRunModelFunc = (\n inputs: Float64Array | undefined,\n outputs: Float64Array,\n options?: {\n outputIndices?: Int32Array\n constants?: ConstantDef[]\n lookups?: LookupDef[]\n }\n) => void\n\n/**\n * A base implementation of the `RunnableModel` interface that takes care\n * of managing internal buffers and copying values to/from the `RunModelParams`.\n *\n * The `onRunModel` function allows an implementation of the core model run loop\n * to deal with typed arrays only.\n *\n * @hidden This is not part of the public API; for internal use only.\n */\nexport class BaseRunnableModel implements RunnableModel {\n public readonly startTime: number\n public readonly endTime: number\n public readonly saveFreq: number\n public readonly numSavePoints: number\n public readonly outputVarIds: OutputVarId[]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public readonly modelListing?: /*ModelListingSpecs*/ any\n\n private readonly onRunModel: OnRunModelFunc\n\n private inputs: Float64Array\n private outputs: Float64Array\n private outputIndices: Int32Array\n\n constructor(options: {\n startTime: number\n endTime: number\n saveFreq: number\n numSavePoints: number\n outputVarIds: OutputVarId[]\n modelListing?: ModelListing\n onRunModel: OnRunModelFunc\n }) {\n this.startTime = options.startTime\n this.endTime = options.endTime\n this.saveFreq = options.saveFreq\n this.numSavePoints = options.numSavePoints\n this.outputVarIds = options.outputVarIds\n this.modelListing = options.modelListing\n this.onRunModel = options.onRunModel\n }\n\n // from RunnableModel interface\n runModel(params: RunModelParams): void {\n // Get a reference to the inputs array, or copy into a new one if needed\n let inputsArray = params.getInputs()\n if (inputsArray === undefined) {\n // The inputs are not accessible in an array, so copy into a new array that we control\n params.copyInputs(this.inputs, numElements => {\n this.inputs = new Float64Array(numElements)\n return this.inputs\n })\n inputsArray = this.inputs\n }\n\n // Get a reference to the output indices array, or copy into a new one if needed\n let outputIndicesArray = params.getOutputIndices()\n if (outputIndicesArray === undefined && params.getOutputIndicesLength() > 0) {\n // The indices are not accessible in an array, so copy into a new array that we control\n params.copyOutputIndices(this.outputIndices, numElements => {\n this.outputIndices = new Int32Array(numElements)\n return this.outputIndices\n })\n outputIndicesArray = this.outputIndices\n }\n\n // Allocate (or reallocate) the array that will receive the outputs\n // TODO: If `params.getOutputsObject` returns an `Outputs` instance, we can\n // write directly into that instead of creating a separate array\n const outputsLengthInElements = params.getOutputsLength()\n if (this.outputs === undefined || this.outputs.length < outputsLengthInElements) {\n this.outputs = new Float64Array(outputsLengthInElements)\n }\n const outputsArray = this.outputs\n\n // Run the model\n const t0 = perfNow()\n this.onRunModel?.(inputsArray, outputsArray, {\n outputIndices: outputIndicesArray,\n constants: params.getConstants(),\n lookups: params.getLookups()\n })\n const elapsed = perfElapsed(t0)\n\n // Copy the outputs that were stored into our array back to the `RunModelParams`\n params.storeOutputs(outputsArray)\n\n // Store the elapsed time in the `RunModelParams`\n params.storeElapsedTime(elapsed)\n }\n\n // from RunnableModel interface\n terminate(): void {\n // No-op\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { type ConstantDef, type LookupDef, type VarSpec } from '../_shared'\nimport type { RunnableModel } from '../runnable-model'\nimport { BaseRunnableModel } from '../runnable-model/base-runnable-model'\n\nimport { getJsModelFunctions, type JsModelFunctionContext, type JsModelFunctions } from './js-model-functions'\n\n/**\n * An interface that exposes the functions of a JavaScript model generated by the\n * SDEverywhere transpiler. This allows for running the model with a given set of\n * input values, which will produce a set of output values.\n *\n * This is a low-level interface that most developers will not need to interact\n * with directly. Developers should instead use the `ModelRunner` interface to\n * interact with a generated model. Use `createSynchronousModelRunner` to create\n * a synchronous `ModelRunner`, or `spawnAsyncModelRunner` to create an asynchronous\n * `ModelRunner`.\n *\n * @beta NOTE: The properties and methods exposed in this interface are meant for\n * internal use only, and are subject to change in coordination with the code\n * generated by the `@sdeverywhere/compile` package.\n */\nexport interface JsModel {\n readonly kind: 'js'\n\n readonly outputVarIds: string[]\n readonly outputVarNames: string[]\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly modelListing?: /*ModelListingSpecs*/ any\n\n /** @hidden */\n getInitialTime(): number\n /** @hidden */\n getFinalTime(): number\n /** @hidden */\n getTimeStep(): number\n /** @hidden */\n getSaveFreq(): number\n\n /** @hidden */\n getModelFunctions(): JsModelFunctions\n /** @hidden */\n setModelFunctions(functions: JsModelFunctions): void\n\n /** @hidden */\n setTime(time: number): void\n /** @hidden */\n setInputs(inputValue: (index: number) => number): void\n\n /** @hidden */\n setConstant(varSpec: VarSpec, value: number): void\n\n /** @hidden */\n setLookup(varSpec: VarSpec, points: Float64Array | undefined): void\n\n /** @hidden */\n storeOutputs(storeValue: (value: number) => void): void\n /** @hidden */\n storeOutput(varSpec: VarSpec, storeValue: (value: number) => void): void\n\n /** @hidden */\n initConstants(): void\n /** @hidden */\n initLevels(): void\n /** @hidden */\n evalAux(): void\n /** @hidden */\n evalLevels(): void\n}\n\n/**\n * Create a `RunnableModel` from a given `JsModel` that was generated by the\n * SDEverywhere transpiler.\n *\n * @hidden This is not part of the public API; only the top-level `createRunnableModel`\n * function is exposed in the public API.\n */\nexport function initJsModel(model: JsModel): RunnableModel {\n // Install the default implementation of model functions if not already provided\n let fns = model.getModelFunctions()\n if (fns === undefined) {\n fns = getJsModelFunctions()\n model.setModelFunctions(fns)\n }\n\n // Get the control variable values. Once the first 4 control variables are known,\n // we can compute `numSavePoints` here.\n const initialTime = model.getInitialTime()\n const finalTime = model.getFinalTime()\n const timeStep = model.getTimeStep()\n const saveFreq = model.getSaveFreq()\n const numSavePoints = Math.round((finalTime - initialTime) / saveFreq) + 1\n\n return new BaseRunnableModel({\n startTime: initialTime,\n endTime: finalTime,\n saveFreq: saveFreq,\n numSavePoints,\n outputVarIds: model.outputVarIds,\n modelListing: model.modelListing,\n onRunModel: (inputs, outputs, options) => {\n runJsModel(\n model,\n initialTime,\n finalTime,\n timeStep,\n saveFreq,\n numSavePoints,\n inputs,\n outputs,\n options?.outputIndices,\n options?.constants,\n options?.lookups,\n undefined\n )\n }\n })\n}\n\nfunction runJsModel(\n model: JsModel,\n initialTime: number,\n finalTime: number,\n timeStep: number,\n saveFreq: number,\n numSavePoints: number,\n inputs: Float64Array | undefined,\n outputs: Float64Array,\n outputIndices: Int32Array | undefined,\n constants: ConstantDef[] | undefined,\n lookups: LookupDef[] | undefined,\n stopAfterTime: number | undefined\n): void {\n // Initialize time with the required `INITIAL TIME` control variable\n let time = initialTime\n model.setTime(time)\n\n // Configure the functions. The function context makes the control variable values\n // available to certain functions that depend on those values.\n const fnContext: JsModelFunctionContext = {\n timeStep,\n currentTime: time\n }\n model.getModelFunctions().setContext(fnContext)\n\n // Initialize constants to their default values\n model.initConstants()\n\n // Apply constant overrides, if provided\n if (constants !== undefined) {\n for (const constantDef of constants) {\n model.setConstant(constantDef.varRef.varSpec, constantDef.value)\n }\n }\n\n // Apply lookup overrides, if provided\n if (lookups !== undefined) {\n for (const lookupDef of lookups) {\n model.setLookup(lookupDef.varRef.varSpec, lookupDef.points)\n }\n }\n\n if (inputs?.length > 0) {\n // Set the user-defined input values. This needs to happen after `initConstants`\n // and the `setConstant` override calls, since the input values will override\n // the default and custom constant values.\n model.setInputs(index => inputs[index])\n }\n\n // Initialize level variables\n model.initLevels()\n\n // Set up a run loop using a fixed number of time steps\n // TODO: For now we run up to and including `finalTime` (even when `stopAfterTime`\n // is defined), storing undefined for values after passing the `stopAfterTime`.\n // We should change this to instead stop running the model after passing the\n // `stopAfterTime` and have a simpler loop that stores undefined values.\n const lastStep = Math.round((finalTime - initialTime) / timeStep)\n const stopTime = stopAfterTime !== undefined ? stopAfterTime : finalTime\n let step = 0\n let savePointIndex = 0\n let outputVarIndex = 0\n while (step <= lastStep) {\n // Evaluate aux variables\n model.evalAux()\n\n if (time % saveFreq < 1e-6) {\n outputVarIndex = 0\n const storeValue = (value: number) => {\n // Write each value into the preallocated buffer; each variable has a \"row\" that\n // contains `numSavePoints` values, one value for each save point\n const outputBufferIndex = outputVarIndex * numSavePoints + savePointIndex\n outputs[outputBufferIndex] = time <= stopTime ? value : undefined\n outputVarIndex++\n }\n if (outputIndices !== undefined) {\n // Store the outputs as specified in the current output indices buffer\n let indexBufferOffset = 0\n const outputCount = outputIndices[indexBufferOffset++]\n for (let i = 0; i < outputCount; i++) {\n const varIndex = outputIndices[indexBufferOffset++]\n const subCount = outputIndices[indexBufferOffset++]\n let subscriptIndices: Int32Array\n if (subCount > 0) {\n subscriptIndices = outputIndices.subarray(indexBufferOffset, indexBufferOffset + subCount)\n indexBufferOffset += subCount\n }\n const varSpec: VarSpec = {\n varIndex,\n subscriptIndices\n }\n model.storeOutput(varSpec, storeValue)\n }\n } else {\n // Store the normal outputs\n // TODO: In the case of a synchronous `ModelRunner`, we can access the `Outputs`\n // instance directly and write directly into that instead of into a typed array.\n // We can update `BaseRunnableModel` to expose the `Outputs` instance, and if it\n // is defined, we can use the following code to write into the `Outputs`.\n // if (outputsInstance) {\n // model.storeOutputs(value => {\n // // Write each value into the preallocated buffer; each variable has a \"row\" that\n // // contains `numSavePoints` values, one value for each save point\n // const series = outputsInstance.varSeries[outputVarIndex]\n // series.points[savePointIndex].y = value\n // outputVarIndex++\n // })\n // } else {\n model.storeOutputs(storeValue)\n // }\n }\n savePointIndex++\n }\n\n if (step === lastStep) {\n // This is the last step, so we are done\n break\n }\n\n // Propagate levels for the next time step\n model.evalLevels()\n\n // Advance time by one step\n time += timeStep\n model.setTime(time)\n fnContext.currentTime = time\n step++\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { Outputs } from '../_shared'\nimport { ReferencedRunModelParams } from '../runnable-model'\nimport { initJsModel, type JsModel } from './js-model'\n\n/**\n * Run the given model synchronously and log the output values to the console in\n * TSV (tab-separated values) format.\n *\n * @hidden This is mainly intended for use in implementing the `sde exec` command,\n * so isn't exposed in the public API at this time.\n *\n * @param jsModel A `JsModel` instance.\n */\nexport function execJsModel(jsModel: JsModel): void {\n // Create a `RunnableModel` from the given `JsModel`\n const runnableModel = initJsModel(jsModel)\n\n // For now we only support running the model with default parameters (no user-specified\n // inputs). By using an empty array here, the model will skip the `setInputs` step.\n const inputs: number[] = []\n\n // Create the `Outputs` instance into which the model outputs will be stored\n const outputVarIds = jsModel.outputVarIds\n const startTime = jsModel.getInitialTime()\n const endTime = jsModel.getFinalTime()\n const saveFreq = jsModel.getSaveFreq()\n const outputs = new Outputs(outputVarIds, startTime, endTime, saveFreq)\n\n // Run the model\n const params = new ReferencedRunModelParams()\n params.updateFromParams(inputs, outputs)\n runnableModel.runModel(params)\n\n // Write the header (escaping quotes as needed)\n const outputVarNames = jsModel.outputVarNames.map(name => name.replace(/\"/g, '\\\\\"'))\n const header = outputVarNames.join('\\t')\n console.log(header)\n\n // Write tab-delimited output data, one line per output time step\n for (let i = 0; i < outputs.seriesLength; i++) {\n const rowValues = []\n for (const series of outputs.varSeries) {\n rowValues.push(series.points[i].y)\n }\n console.log(rowValues.join('\\t'))\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport type { OutputVarId, VarId, VarSpec } from '../../_shared'\nimport { ModelListing } from '../../model-listing'\nimport type { JsModel } from '../js-model'\nimport type { JsModelFunctions } from '../js-model-functions'\nimport { JsModelLookup } from '../js-model-lookup'\n\n/**\n * @hidden This type is not part of the public API; it is exposed only for use in\n * tests in the runtime-async package.\n */\nexport type OnEvalAux = (\n vars: Map<VarId, number>,\n constants: Map<VarId, number> | undefined,\n lookups: Map<VarId, JsModelLookup>\n) => void\n\n/**\n * @hidden This type is not part of the public API; it is exposed only for use in\n * tests in the runtime-async package.\n */\nexport class MockJsModel implements JsModel {\n // from JsModel interface\n public readonly kind = 'js'\n\n // from JsModel interface\n public readonly outputVarIds: OutputVarId[]\n\n // from JsModel interface\n public readonly outputVarNames: OutputVarId[]\n\n // from JsModel interface\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public readonly modelListing?: /*ModelListingSpecs*/ any\n private readonly internalListing?: ModelListing\n\n private readonly initialTime: number\n private readonly finalTime: number\n\n private readonly vars: Map<VarId, number> = new Map()\n private readonly constants: Map<VarId, number> = new Map()\n private readonly lookups: Map<VarId, JsModelLookup> = new Map()\n private fns: JsModelFunctions\n\n public readonly onEvalAux: OnEvalAux\n\n constructor(options: {\n initialTime: number\n finalTime: number\n outputVarIds: OutputVarId[]\n listingJson?: string\n onEvalAux: OnEvalAux\n }) {\n this.outputVarIds = options.outputVarIds\n this.outputVarNames = options.outputVarIds\n this.initialTime = options.initialTime\n this.finalTime = options.finalTime\n this.outputVarIds = options.outputVarIds\n if (options.listingJson) {\n this.modelListing = JSON.parse(options.listingJson)\n this.internalListing = new ModelListing(this.modelListing)\n }\n this.onEvalAux = options.onEvalAux\n }\n\n varIdForSpec(varSpec: VarSpec): VarId {\n for (const [listingVarId, listingSpec] of this.internalListing.varSpecs) {\n // TODO: This doesn't compare subscripts yet\n if (listingSpec.varIndex === varSpec.varIndex) {\n return listingVarId\n }\n }\n return undefined\n }\n\n // from JsModel interface\n getInitialTime(): number {\n return this.initialTime\n }\n\n // from JsModel interface\n getFinalTime(): number {\n return this.finalTime\n }\n\n // from JsModel interface\n getTimeStep(): number {\n return 1\n }\n\n // from JsModel interface\n getSaveFreq(): number {\n return 1\n }\n\n // from JsModel interface\n getModelFunctions(): JsModelFunctions {\n return this.fns\n }\n\n // from JsModel interface\n setModelFunctions(fns: JsModelFunctions) {\n this.fns = fns\n }\n\n // from JsModel interface\n setTime(time: number): void {\n this.vars.set('_time', time)\n }\n\n // from JsModel interface\n setInputs(): void {\n // TODO\n }\n\n // from JsModel interface\n setConstant(varSpec: VarSpec, value: number): void {\n const varId = this.varIdForSpec(varSpec)\n if (varId === undefined) {\n throw new Error(`No constant variable found for spec ${varSpec}`)\n }\n this.constants.set(varId, value)\n }\n\n // from JsModel interface\n setLookup(varSpec: VarSpec, points: Float64Array | undefined): void {\n const varId = this.varIdForSpec(varSpec)\n if (varId === undefined) {\n throw new Error(`No lookup variable found for spec ${varSpec}`)\n }\n const numPoints = points ? points.length / 2 : 0\n this.lookups.set(varId, new JsModelLookup(numPoints, points))\n }\n\n // from JsModel interface\n storeOutputs(storeValue: (value: number) => void): void {\n for (const varId of this.outputVarIds) {\n storeValue(this.vars.get(varId))\n }\n }\n\n // from JsModel interface\n storeOutput(varSpec: VarSpec, storeValue: (value: number) => void): void {\n const varId = this.varIdForSpec(varSpec)\n if (varId === undefined) {\n throw new Error(`No output variable found for spec ${varSpec}`)\n }\n storeValue(this.vars.get(varId))\n }\n\n // from JsModel interface\n initConstants(): void {\n // Clear all constant overrides (they don't persist across runs)\n this.constants.clear()\n }\n\n // from JsModel interface\n initLevels(): void {}\n\n // from JsModel interface\n evalAux(): void {\n this.onEvalAux?.(this.vars, this.constants.size > 0 ? this.constants : undefined, this.lookups)\n }\n\n // from JsModel interface\n evalLevels(): void {}\n}\n","// Copyright (c) 2020-2022 Climate Interactive / New Venture Fund\n\nimport type { WasmModule } from './wasm-module'\n\n/**\n * Wraps a `WebAssembly.Memory` buffer allocated on the wasm heap.\n *\n * When this is used synchronously (in the browser's normal JavaScript thread),\n * the client can use `getArrayView` to write directly into the underlying memory.\n *\n * Note, however, that `WebAssembly.Memory` buffers cannot be transferred to/from\n * a Web Worker. When using this class in a worker thread, create a separate\n * `Float64Array` that can be transferred between the worker and the client running\n * in the browser's normal JS thread, and then use `getArrayView` to copy into and\n * out of the wasm buffer.\n *\n * @hidden For internal use only.\n */\nexport class WasmBuffer<ArrType> {\n /**\n * @param wasmModule The `WasmModule` used to initialize the memory.\n * @param numElements The number of elements in the buffer.\n * @param byteOffset The byte offset within the wasm heap.\n * @param heapArray The array view on the underlying heap buffer.\n */\n constructor(\n private readonly wasmModule: WasmModule,\n public numElements: number,\n private byteOffset: number,\n private heapArray: ArrType\n ) {}\n\n /**\n * @return An `ArrType` view on the underlying heap buffer.\n */\n getArrayView(): ArrType {\n return this.heapArray\n }\n\n /**\n * @return The raw address of the underlying heap buffer.\n * @hidden This is intended for use by `WasmModel` only.\n */\n getAddress(): number {\n return this.byteOffset\n }\n\n /**\n * Dispose the buffer by freeing the allocated heap memory.\n */\n dispose(): void {\n if (this.heapArray) {\n this.wasmModule._free?.(this.byteOffset)\n this.numElements = undefined\n this.heapArray = undefined\n this.byteOffset = undefined\n }\n }\n}\n\n/**\n * Return a `WasmBuffer` that holds int32 elements.\n *\n * @hidden For internal use only.\n *\n * @param wasmModule The `WasmModule` used to initialize the memory.\n * @param numElements The number of elements in the buffer.\n */\nexport function createInt32WasmBuffer(wasmModule: WasmModule, numElements: number): WasmBuffer<Int32Array> {\n const elemSizeInBytes = 4\n const lengthInBytes = numElements * elemSizeInBytes\n const byteOffset = wasmModule._malloc(lengthInBytes)\n const elemOffset = byteOffset / elemSizeInBytes\n const heapArray = wasmModule.HEAP32.subarray(elemOffset, elemOffset + numElements)\n return new WasmBuffer<Int32Array>(wasmModule, numElements, byteOffset, heapArray)\n}\n\n/**\n * Return a `WasmBuffer` that holds float64 elements.\n *\n * @hidden For internal use only.\n *\n * @param wasmModule The `WasmModule` used to initialize the memory.\n * @param numElements The number of elements in the buffer.\n */\nexport function createFloat64WasmBuffer(wasmModule: WasmModule, numElements: number): WasmBuffer<Float64Array> {\n const elemSizeInBytes = 8\n const lengthInBytes = numElements * elemSizeInBytes\n const byteOffset = wasmModule._malloc(lengthInBytes)\n const elemOffset = byteOffset / elemSizeInBytes\n const heapArray = wasmModule.HEAPF64.subarray(elemOffset, elemOffset + numElements)\n return new WasmBuffer<Float64Array>(wasmModule, numElements, byteOffset, heapArray)\n}\n","// Copyright (c) 2020-2022 Climate Interactive / New Venture Fund\n\nimport type { OutputVarId } from '../_shared'\nimport type { RunModelParams, RunnableModel } from '../runnable-model'\nimport { perfElapsed, perfNow } from '../perf'\nimport { createFloat64WasmBuffer, createInt32WasmBuffer, type WasmBuffer } from './wasm-buffer'\nimport type { WasmModule } from './wasm-module'\n\n/**\n * A wrapper around a WebAssembly module generated by the SDEverywhere transpiler,\n * which allows for running the model with a given set of input values, producing\n * a set of output values.\n */\nclass WasmModel implements RunnableModel {\n // from RunnableModel interface\n public readonly startTime: number\n // from RunnableModel interface\n public readonly endTime: number\n // from RunnableModel interface\n public readonly saveFreq: number\n // from RunnableModel interface\n public readonly numSavePoints: number\n // from RunnableModel interface\n public readonly outputVarIds: OutputVarId[]\n // from RunnableModel interface\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public readonly modelListing?: any\n\n // Reuse the wasm buffers. These buffers are allocated on demand and grown\n // (reallocated) as needed.\n private inputsBuffer: WasmBuffer<Float64Array>\n private outputsBuffer: WasmBuffer<Float64Array>\n private outputIndicesBuffer: WasmBuffer<Int32Array>\n private lookupDataBuffer: WasmBuffer<Float64Array>\n private lookupSubIndicesBuffer: WasmBuffer<Int32Array>\n private constantValuesBuffer: WasmBuffer<Float64Array>\n private constantIndicesBuffer: WasmBuffer<Int32Array>\n\n private readonly wasmSetLookup: (\n varIndex: number,\n subIndicesAddress: number,\n pointsAddress: number,\n numPoints: number\n ) => void\n private readonly wasmRunModel: (\n inputsAddress: number,\n inputIndicesAddress: number,\n outputsAddress: number,\n outputIndicesAddress: number,\n constantValuesAddress: number,\n constantIndicesAddress: number\n ) => void\n\n /**\n * @param wasmModule The `WasmModule` that provides access to the native functions.\n * @param outputVarIds The output variable IDs for this model.\n */\n constructor(private readonly wasmModule: WasmModule) {\n function getNumberValue(funcName: string): number {\n const wasmGetValue: () => number = wasmModule.cwrap(funcName, 'number', [])\n return wasmGetValue()\n }\n this.startTime = getNumberValue('getInitialTime')\n this.endTime = getNumberValue('getFinalTime')\n this.saveFreq = getNumberValue('getSaveper')\n\n // Each series will include one data point per \"save\", inclusive of the\n // start and end times\n this.numSavePoints = Math.round((this.endTime - this.startTime) / this.saveFreq) + 1\n this.outputVarIds = wasmModule.outputVarIds\n\n // Expose the model listing, if it was bundled with the generated module\n this.modelListing = wasmModule.modelListing\n\n // Make the native functions callable\n this.wasmSetLookup = wasmModule.cwrap('setLookup', null, ['number', 'number', 'number', 'number'])\n this.wasmRunModel = wasmModule.cwrap('runModelWithBuffers', null, [\n 'number',\n 'number',\n 'number',\n 'number',\n 'number',\n 'number'\n ])\n }\n\n // from RunnableModel interface\n runModel(params: RunModelParams): void {\n // Note that for wasm models, we always need to allocate `WasmBuffer` instances to\n // and copy data to/from them because only that kind of buffer can be passed to\n // the `wasmRunModel` function.\n\n // Apply lookup overrides, if provided\n const lookups = params.getLookups()\n if (lookups !== undefined) {\n for (const lookupDef of lookups) {\n // Copy the subscript index values to the `WasmBuffer`. If we don't have an\n // existing `WasmBuffer`, or the existing one is not big enough, allocate a new one.\n const varSpec = lookupDef.varRef.varSpec\n const numSubElements = varSpec.subscriptIndices?.length || 0\n let subIndicesAddress: number\n if (numSubElements > 0) {\n if (this.lookupSubIndicesBuffer === undefined || this.lookupSubIndicesBuffer.numElements < numSubElements) {\n this.lookupSubIndicesBuffer?.dispose()\n this.lookupSubIndicesBuffer = createInt32WasmBuffer(this.wasmModule, numSubElements)\n }\n this.lookupSubIndicesBuffer.getArrayView().set(varSpec.subscriptIndices)\n subIndicesAddress = this.lookupSubIndicesBuffer.getAddress()\n } else {\n subIndicesAddress = 0\n }\n\n let pointsAddress: number\n let numPoints: number\n if (lookupDef.points) {\n // Copy the lookup data to the `WasmBuffer`. If we don't have an existing `WasmBuffer`,\n // or the existing one is not big enough, allocate a new one.\n const numLookupElements = lookupDef.points.length\n if (this.lookupDataBuffer === undefined || this.lookupDataBuffer.numElements < numLookupElements) {\n this.lookupDataBuffer?.dispose()\n this.lookupDataBuffer = createFloat64WasmBuffer(this.wasmModule, numLookupElements)\n }\n this.lookupDataBuffer.getArrayView().set(lookupDef.points)\n pointsAddress = this.lookupDataBuffer.getAddress()\n\n // Note that the native `numPoints` argument is the number of (x,y) pairs, so divide\n // the length of the flat points array by two\n numPoints = numLookupElements / 2\n } else {\n // In the case where the points array is undefined, we pass 0 (NULL), which will reset\n // the lookup to its original data\n pointsAddress = 0\n numPoints = 0\n }\n\n // Call the native `setLookup` function\n const varIndex = varSpec.varIndex\n this.wasmSetLookup(varIndex, subIndicesAddress, pointsAddress, numPoints)\n }\n }\n\n // Prepare constant overrides buffer, if provided\n let constantIndicesBuffer: WasmBuffer<Int32Array>\n let constantValuesBuffer: WasmBuffer<Float64Array>\n const constants = params.getConstants()\n if (constants !== undefined && constants.length > 0) {\n // Calculate the size needed for the constantIndices buffer:\n // count (1) + for each constant: varIndex (1) + subCount (1) + subIndices (variable)\n let totalIndicesSize = 1 // for count\n for (const constantDef of constants) {\n const numSubElements = constantDef.varRef.varSpec.subscriptIndices?.length || 0\n totalIndicesSize += 2 + numSubElements // varIndex + subCount + subIndices\n }\n\n // Allocate the constantIndices buffer\n if (this.constantIndicesBuffer === undefined || this.constantIndicesBuffer.numElements < totalIndicesSize) {\n this.constantIndicesBuffer?.dispose()\n this.constantIndicesBuffer = createInt32WasmBuffer(this.wasmModule, totalIndicesSize)\n }\n\n // Allocate the constantValues buffer (one value per constant)\n const numConstants = constants.length\n if (this.constantValuesBuffer === undefined || this.constantValuesBuffer.numElements < numConstants) {\n this.constantValuesBuffer?.dispose()\n this.constantValuesBuffer = createFloat64WasmBuffer(this.wasmModule, numConstants)\n }\n\n // Build the constantIndices and constantValues buffers\n const indicesView = this.constantIndicesBuffer.getArrayView()\n const valuesView = this.constantValuesBuffer.getArrayView()\n let indicesOffset = 0\n let valuesOffset = 0\n\n // Write count\n indicesView[indicesOffset++] = numConstants\n\n // Write each constant's data\n for (const constantDef of constants) {\n const varSpec = constantDef.varRef.varSpec\n const numSubElements = varSpec.subscriptIndices?.length || 0\n\n // Write varIndex\n indicesView[indicesOffset++] = varSpec.varIndex\n\n // Write subCount\n indicesView[indicesOffset++] = numSubElements\n\n // Write subIndices\n if (numSubElements > 0) {\n for (let i = 0; i < numSubElements; i++) {\n indicesView[indicesOffset++] = varSpec.subscriptIndices[i]\n }\n }\n\n // Write value\n valuesView[valuesOffset++] = constantDef.value\n }\n\n constantIndicesBuffer = this.constantIndicesBuffer\n constantValuesBuffer = this.constantValuesBuffer\n } else {\n constantIndicesBuffer = undefined\n constantValuesBuffer = undefined\n }\n\n // Copy the inputs to the `WasmBuffer`. If we don't have an existing `WasmBuffer`,\n // or the existing one is not big enough, the callback will allocate a new one.\n params.copyInputs(this.inputsBuffer?.getArrayView(), numElements => {\n this.inputsBuffer?.dispose()\n this.inputsBuffer = createFloat64WasmBuffer(this.wasmModule, numElements)\n return this.inputsBuffer.getArrayView()\n })\n\n let outputIndicesBuffer: WasmBuffer<Int32Array>\n if (params.getOutputIndicesLength() > 0) {\n // Copy the output indices (if needed) to the `WasmBuffer`. If we don't have an\n // existing `WasmBuffer`, or the existing one is not big enough, the callback\n // will allocate a new one.\n params.copyOutputIndices(this.outputIndicesBuffer?.getArrayView(), numElements => {\n this.outputIndicesBuffer?.dispose()\n this.outputIndicesBuffer = createInt32WasmBuffer(this.wasmModule, numElements)\n return this.outputIndicesBuffer.getArrayView()\n })\n outputIndicesBuffer = this.outputIndicesBuffer\n } else {\n // The output indices are not active\n outputIndicesBuffer = undefined\n }\n\n // Allocate (or reallocate) the `WasmBuffer` that will receive the outputs\n const outputsLengthInElements = params.getOutputsLength()\n if (this.outputsBuffer === undefined || this.outputsBuffer.numElements < outputsLengthInElements) {\n this.outputsBuffer?.dispose()\n this.outputsBuffer = createFloat64WasmBuffer(this.wasmModule, outputsLengthInElements)\n }\n\n // Run the model\n const t0 = perfNow()\n this.wasmRunModel(\n this.inputsBuffer?.getAddress() || 0,\n // Always pass 0 (NULL) for input indices, since we assume that all input values are\n // provided and are in the same order as the input variables defined in the model spec\n 0,\n this.outputsBuffer.getAddress(),\n outputIndicesBuffer?.getAddress() || 0,\n constantValuesBuffer?.getAddress() || 0,\n constantIndicesBuffer?.getAddress() || 0\n )\n const elapsed = perfElapsed(t0)\n\n // Copy the outputs that were stored into the `WasmBuffer` back to the `RunModelParams`\n params.storeOutputs(this.outputsBuffer.getArrayView())\n\n // Store the elapsed time in the `RunModelParams`\n params.storeElapsedTime(elapsed)\n }\n\n // from RunnableModel interface\n terminate(): void {\n this.inputsBuffer?.dispose()\n this.inputsBuffer = undefined\n\n this.outputsBuffer?.dispose()\n this.outputsBuffer = undefined\n\n this.outputIndicesBuffer?.dispose()\n this.outputIndicesBuffer = undefined\n\n this.constantValuesBuffer?.dispose()\n this.constantValuesBuffer = undefined\n\n this.constantIndicesBuffer?.dispose()\n this.constantIndicesBuffer = undefined\n\n // TODO: Dispose the `WasmModule` too?\n }\n}\n\n/**\n * Initialize the wasm model.\n *\n * @hidden This is not part of the public API; only the top-level `createRunnableModel`\n * function is exposed in the public API.\n *\n * @param wasmModule The `WasmModule` that wraps the `wasm` binary.\n * @return The initialized `WasmModel` instance.\n */\nexport function initWasmModel(wasmModule: WasmModule): RunnableModel {\n return new WasmModel(wasmModule)\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport type { OutputVarId, VarId, VarSpec } from '../../_shared'\nimport { JsModelLookup } from '../../js-model/js-model-lookup'\nimport { ModelListing } from '../../model-listing'\nimport type { WasmModule } from '../wasm-module'\n\n/**\n * @hidden This type is not part of the public API; it is exposed only for use in\n * tests in the runtime-async package.\n */\nexport type OnRunModel = (\n inputs: Float64Array,\n outputs: Float64Array,\n constants: Map<VarId, number> | undefined,\n lookups: Map<VarId, JsModelLookup>,\n outputIndices?: Int32Array\n) => void\n\n/**\n * @hidden This type is not part of the public API; it is exposed only for use in\n * tests in the runtime-async package.\n */\nexport class MockWasmModule implements WasmModule {\n // from WasmModule interface\n public readonly kind = 'wasm'\n\n // from WasmModule interface\n public readonly outputVarIds: OutputVarId[]\n\n // from WasmModule interface\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public readonly modelListing?: any\n private readonly internalListing?: ModelListing\n\n private readonly initialTime: number\n private readonly finalTime: number\n\n private readonly heap: ArrayBuffer\n\n // from WasmModule interface\n public readonly HEAP32: Int32Array\n\n // from WasmModule interface\n public readonly HEAPF64: Float64Array\n\n // Start at 8 so that we can treat 0 as NULL\n private mallocOffset = 8\n private readonly allocs: Map<number, number> = new Map()\n\n private readonly lookups: Map<VarId, JsModelLookup> = new Map()\n private readonly constants: Map<VarId, number> = new Map()\n\n public readonly onRunModel: OnRunModel\n\n constructor(options: {\n initialTime: number\n finalTime: number\n outputVarIds: string[]\n listingJson?: string\n onRunModel: OnRunModel\n }) {\n this.initialTime = options.initialTime\n this.finalTime = options.finalTime\n this.outputVarIds = options.outputVarIds\n if (options.listingJson) {\n this.modelListing = JSON.parse(options.listingJson)\n this.internalListing = new ModelListing(this.modelListing)\n }\n this.onRunModel = options.onRunModel\n\n this.heap = new ArrayBuffer(8192)\n this.HEAP32 = new Int32Array(this.heap)\n this.HEAPF64 = new Float64Array(this.heap)\n }\n\n varIdForSpec(varSpec: VarSpec): VarId {\n for (const [listingVarId, listingSpec] of this.internalListing.varSpecs) {\n // TODO: This doesn't compare subscripts yet\n if (listingSpec.varIndex === varSpec.varIndex) {\n return listingVarId\n }\n }\n return undefined\n }\n\n // from WasmModule interface\n cwrap(fname: string) {\n // Return a mock implementation of each wrapped C function\n switch (fname) {\n case 'getInitialTime':\n return () => this.initialTime\n case 'getFinalTime':\n return () => this.finalTime\n case 'getSaveper':\n return () => 1\n case 'setLookup':\n return (varIndex: number, _subIndicesAddress: number, pointsAddress: number, numPoints: number) => {\n // TODO: This doesn't check subIndices yet\n const varId = this.varIdForSpec({ varIndex })\n if (varId === undefined) {\n throw new Error(`No lookup variable found for var index ${varIndex}`)\n }\n // Note that we create a copy of the points array, since it may be reused\n const points = new Float64Array(this.getHeapView('float64', pointsAddress) as Float64Array)\n this.lookups.set(varId, new JsModelLookup(numPoints, points))\n }\n case 'runModelWithBuffers':\n return (\n inputsAddress: number,\n _inputIndicesAddress: number,\n outputsAddress: number,\n outputIndicesAddress: number,\n constantValuesAddress: number,\n constantIndicesAddress: number\n ) => {\n const inputs = this.getHeapView('float64', inputsAddress) as Float64Array\n const outputs = this.getHeapView('float64', outputsAddress) as Float64Array\n const outputIndices = this.getHeapView('int32', outputIndicesAddress) as Int32Array\n\n // Decode constant buffers if provided\n this.constants.clear()\n if (constantValuesAddress !== 0 && constantIndicesAddress !== 0) {\n const constantValues = this.getHeapView('float64', constantValuesAddress) as Float64Array\n const constantIndices = this.getHeapView('int32', constantIndicesAddress) as Int32Array\n\n // Read count\n const numConstants = constantIndices[0]\n let indicesOffset = 1\n let valuesOffset = 0\n\n // Decode each constant\n for (let i = 0; i < numConstants; i++) {\n const varIndex = constantIndices[indicesOffset++]\n const subCount = constantIndices[indicesOffset++]\n // TODO: We skip subscript indices for now, but we should test them here too\n indicesOffset += subCount\n\n const varId = this.varIdForSpec({ varIndex })\n if (varId) {\n this.constants.set(varId, constantValues[valuesOffset++])\n }\n }\n }\n\n // Run the model\n this.onRunModel(\n inputs,\n outputs,\n this.constants.size > 0 ? this.constants : undefined,\n this.lookups,\n outputIndices\n )\n\n // Clear constants after the run (they don't persist)\n this.constants.clear()\n }\n default:\n throw new Error(`Unhandled call to cwrap with function name '${fname}'`)\n }\n }\n\n // from WasmModule interface\n _malloc(lengthInBytes: number): number {\n const currentOffset = this.mallocOffset\n this.allocs.set(currentOffset, lengthInBytes)\n if (lengthInBytes > 0) {\n // Update the offset so that the next allocation starts after this one\n this.mallocOffset += lengthInBytes\n } else {\n // In the case where the length is zero, add a little padding so that\n // the next allocation is recorded at a different start address than\n // this one\n this.mallocOffset += 8\n }\n return currentOffset\n }\n\n // from WasmModule interface\n _free(): void {\n // This is not implemented; the heap will continue to grow, which is fine for the purposes of the tests\n }\n\n private getHeapView(kind: 'float64' | 'int32', address: number): Float64Array | Int32Array | undefined {\n if (address === 0) {\n return undefined\n }\n\n // Find the length\n const lengthInBytes = this.allocs.get(address)\n if (lengthInBytes === undefined) {\n throw new Error('Failed to locate heap allocation')\n }\n\n // The address value is in bytes, so convert to float64 or int32 offset\n if (kind === 'float64') {\n const offset = address / 8\n return this.HEAPF64.subarray(offset, offset + lengthInBytes / 8)\n } else {\n const offset = address / 4\n return this.HEAP32.subarray(offset, offset + lengthInBytes / 4)\n }\n }\n}\n","// Copyright (c) 2024 Climate Interactive / New Venture Fund\n\nimport { type InputValue, Outputs } from '../_shared'\n\nimport { type JsModel, initJsModel } from '../js-model'\nimport { type WasmModule, initWasmModel } from '../wasm-model'\nimport type { RunnableModel, RunModelOptions } from '../runnable-model'\nimport { ReferencedRunModelParams } from '../runnable-model'\n\nimport type { ModelRunner } from './model-runner'\nimport { ModelListing } from '../model-listing'\n\n/** Union of model types that are generated by the SDEverywhere transpiler/builder. */\nexport type GeneratedModel = JsModel | WasmModule\n\n/**\n * Create a `RunnableModel` from a given `JsModel` or `WasmModule` that was generated by the\n * SDEverywhere transpiler/builder.\n *\n * @hidden This is not yet part of the public API; it is only exposed for use by\n * the runtime-async package.\n */\nexport function createRunnableModel(generatedModel: GeneratedModel): RunnableModel {\n switch (generatedModel.kind) {\n case 'js':\n // Assume it's a `JsModel`\n return initJsModel(generatedModel)\n case 'wasm':\n // Assume it's a `WasmModule`\n return initWasmModel(generatedModel)\n default:\n throw new Error(`Unable to identify generated model kind`)\n }\n}\n\n/**\n * Create a `ModelRunner` that runs a generated model on the JS thread.\n *\n * @param generatedModel A `JsModel` or `WasmModule` generated by the SDEverywhere transpiler.\n */\nexport function createSynchronousModelRunner(generatedModel: GeneratedModel): ModelRunner {\n const runnableModel = createRunnableModel(generatedModel)\n return createRunnerFromRunnableModel(runnableModel)\n}\n\n/**\n * Create a `ModelRunner` that runs the given model on the JS thread.\n *\n * @param model The runnable model instance.\n */\nfunction createRunnerFromRunnableModel(model: RunnableModel): ModelRunner {\n // Maintain a `ReferencedRunModelParams` instance that holds the I/O parameters\n const listing = model.modelListing ? new ModelListing(model.modelListing) : undefined\n const params = new ReferencedRunModelParams(listing)\n\n // Disallow `runModel` after the runner has been terminated\n let terminated = false\n\n const runModelSync = (inputs: number[] | InputValue[], outputs: Outputs, options: RunModelOptions | undefined) => {\n // Update the I/O parameters\n params.updateFromParams(inputs, outputs, options)\n\n // Run the model synchronously using those parameters\n model.runModel(params)\n\n return outputs\n }\n\n return {\n createOutputs: () => {\n return new Outputs(model.outputVarIds, model.startTime, model.endTime, model.saveFreq)\n },\n\n runModel: (inputs, outputs, options) => {\n if (terminated) {\n return Promise.reject(new Error('Model runner has already been terminated'))\n }\n return Promise.resolve(runModelSync(inputs, outputs, options))\n },\n\n runModelSync: (inputs, outputs, options) => {\n if (terminated) {\n throw new Error('Model runner has already been terminated')\n }\n return runModelSync(inputs, outputs, options)\n },\n\n terminate: async () => {\n if (!terminated) {\n model.terminate()\n terminated = true\n }\n }\n }\n}\n","// Copyright (c) 2020-2022 Climate Interactive / New Venture Fund\n\nimport type { InputValue, InputVarId, Outputs } from '../_shared'\nimport type { ModelRunner } from '../model-runner'\n\n/**\n * A high-level interface that schedules the underlying `ModelRunner`.\n *\n * When one or more input values are changed, this class will schedule a model\n * run to be completed as soon as possible. When the model run has completed,\n * `onOutputsChanged` is called to notify that new output data is available.\n *\n * The `ModelRunner` is pluggable to allow for running the model synchronously\n * (on the main JavaScript thread) or asynchronously (in a Web Worker or Node.js\n * worker thread).\n */\nexport class ModelScheduler {\n /** The second array that holds a stable copy of the user inputs. */\n private readonly currentInputs: InputValue[]\n\n /** Whether a model run has been scheduled. */\n private runNeeded = false\n\n /** Whether a model run is in progress. */\n private runInProgress = false\n\n /** Called when `outputs` has been updated after a model run. */\n public onOutputsChanged?: (outputs: Outputs) => void\n\n /**\n * @param runner The model runner.\n * @param userInputs The input values, in the same order as in the spec file passed to `sde`.\n * @param outputs The structure into which the model outputs will be stored.\n */\n constructor(\n private readonly runner: ModelRunner,\n private readonly userInputs: InputValue[],\n private outputs: Outputs\n ) {\n // When any input has an updated value, schedule a model run on the next tick\n const afterSet = () => {\n this.runModelIfNeeded()\n }\n for (const userInput of userInputs) {\n userInput.callbacks.onSet = afterSet\n }\n\n // Create a second array to hold a stable copy of the user inputs during model runs\n this.currentInputs = []\n for (const userInput of userInputs) {\n this.currentInputs.push(createSimpleInputValue(userInput.varId))\n }\n }\n\n /**\n * Schedule a model run (if not already pending). When the run is\n * complete, save the outputs and call the `onOutputsChanged` callback.\n */\n private runModelIfNeeded(): void {\n // Set a flag indicating that a new run is needed (even if one is already\n // in progress)\n this.runNeeded = true\n\n if (this.runInProgress) {\n // A run is already in progress; let it finish first\n return\n } else {\n // A run is not already in progress, so schedule it now. We use\n // `setTimeout` so that if a lot of inputs are all changing at once\n // (like after a reset), we wait for all those `set` or `reset`\n // calls to finish before gathering the input values into an array\n // and initiating the run on the next tick.\n this.runInProgress = true\n setTimeout(() => {\n // Kick off the (possibly asynchronous) model run\n this.runModelNow()\n }, 0)\n }\n }\n\n /**\n * Run the model asynchronously using the current set of input values.\n */\n private async runModelNow(): Promise<void> {\n // Copy the current inputs into a separate array; this ensures that the\n // model run uses a stable set of inputs, even if the user continues to\n // change the inputs while the model is being run asynchronously\n for (let i = 0; i < this.userInputs.length; i++) {\n this.currentInputs[i].set(this.userInputs[i].get())\n }\n\n // Run the model with the current set of input values and save the outputs\n try {\n this.outputs = await this.runner.runModel(this.currentInputs, this.outputs)\n this.onOutputsChanged?.(this.outputs)\n } catch (e) {\n console.error(`ERROR: Failed to run model: ${e.message}`)\n }\n\n // See if another run is needed\n if (this.runNeeded) {\n // Keep `runInProgress` set, but clear the `runNeeded` flag\n this.runNeeded = false\n setTimeout(() => {\n this.runModelNow()\n }, 0)\n } else {\n // No run needed, so clear both flags\n this.runNeeded = false\n this.runInProgress = false\n }\n }\n}\n\n/**\n * Create an `InputValue` that is only used to hold a copy of another input (no callbacks).\n * @hidden\n */\nfunction createSimpleInputValue(varId: InputVarId): InputValue {\n let currentValue = 0\n const get = () => {\n return currentValue\n }\n const set = (newValue: number) => {\n currentValue = newValue\n }\n const reset = () => {\n set(0)\n }\n return { varId, get, set, reset, callbacks: {} }\n}\n","// Copyright (c) 2025 Climate Interactive / New Venture Fund\n\nimport type { DataMap, InputValue, Outputs, OutputVarId, Series, SourceName } from '../_shared'\nimport type { ModelRunner } from '../model-runner'\n\n/**\n * Defines a context that holds a distinct set of model inputs and outputs.\n * These inputs and outputs are kept separate from those in other contexts,\n * which allows an application to use the same underlying model instance\n * with multiple sets of inputs and outputs.\n */\nexport interface ModelContext {\n /**\n * Called when the outputs have been updated after a model run.\n */\n onOutputsChanged?: () => void\n\n /**\n * Return the series data for the given model output variable or external\n * dataset.\n *\n * @param varId The ID of the output variable associated with the data.\n * @param sourceName The external data source name (e.g. \"Ref\"), or\n * undefined to use the latest model output data from this context.\n */\n getSeriesForVar(varId: OutputVarId, sourceName?: SourceName): Series | undefined\n}\n\n/**\n * A high-level interface that schedules running of the underlying `ModelRunner`.\n *\n * This class is similar to the (single context) `ModelScheduler` class, except\n * this one supports multiple contexts, each with its own distinct set of\n * inputs and outputs. This is useful for running the same underlying model\n * instance with different sets of inputs and outputs. For example, you can\n * use this to show the outputs for multiple scenarios in a single graph, or\n * multiple scenarios across different graphs.\n *\n * When input values are changed in one or more contexts, this class will schedule\n * a model run for each changed context to be completed as soon as possible.\n * When the model run has completed, the context's `onOutputsChanged` function\n * is called to notify that new output data is available for that context.\n *\n * The `ModelRunner` is pluggable to allow for running the model synchronously\n * (on the main JavaScript thread) or asynchronously (in a Web Worker or Node.js\n * worker thread).\n */\nexport class MultiContextModelScheduler {\n /**\n * An optional `Outputs` instance that will be reused for the initial context. This will\n * be set to undefined after it is used for the first context.\n */\n private initialOutputs?: Outputs\n\n /** The second array that holds a stable copy of the user inputs. */\n private currentInputs: number[]\n\n /** The contexts that hold distinct sets of inputs and outputs. */\n private readonly contexts: ModelContextImpl[] = []\n\n /** Whether a model run has been scheduled. */\n private runNeeded = false\n\n /** Whether a model run is in progress. */\n private runInProgress = false\n\n /**\n * @param runner The model runner.\n * @param options Additional options for the scheduler.\n * @param options.initialOutputs An optional `Outputs` instance that will be reused\n * for the initial context. This is useful for saving memory when an `Outputs`\n * instance was already created for, e.g., a initial baseline/reference run.\n */\n constructor(\n private readonly runner: ModelRunner,\n options?: { initialOutputs?: Outputs }\n ) {\n this.initialOutputs = options?.initialOutputs\n }\n\n /**\n * Return true if the scheduler has started any model runs.\n */\n public isStarted(): boolean {\n return this.initialOutputs === undefined\n }\n\n /**\n * Add a new context that holds a distinct set of model inputs and outputs.\n * These inputs and outputs are kept separate from those in other contexts,\n * which allows an application to use the same underlying model to run with\n * multiple I/O contexts.\n *\n * Note that the contexts created before the first scheduled model run\n * will inherit the data from `initialOutputs` passed to the constructor,\n * but contexts created after that will initially have output values set\n * to zero.\n *\n * @param inputs The input values, in the same order as in the spec file passed to `sde`.\n * @param options Additional options for the context.\n * @param options.externalData Additional data that is external to the model outputs.\n * For example, this can contain data that was captured from an initial reference\n * run, or other static data that is displayed in graphs alongside the model\n * output data in graphs.\n */\n public addContext(inputs: InputValue[], options?: { externalData?: DataMap }): ModelContext {\n // If we haven't yet performed the initial scheduled model run, the context\n // will inherit the data from `initialOutputs` (if defined), otherwise we\n // initialize a new instance with output values set to zero\n let outputs: Outputs\n if (this.initialOutputs !== undefined) {\n if (this.contexts.length === 0) {\n // For the first context, use the initial outputs by reference\n outputs = this.initialOutputs\n } else {\n // For all other contexts created before the initial scheduled model run,\n // create a copy of the initial outputs\n outputs = this.runner.createOutputs()\n for (const varId of outputs.varIds) {\n const series0 = this.initialOutputs.getSeriesForVar(varId)\n const series1 = outputs.getSeriesForVar(varId)\n for (let i = 0; i < series0.points.length; i++) {\n series1.points[i].y = series0.points[i].y\n }\n }\n }\n } else {\n // Otherwise, initialize a new instance (with values set to zero)\n outputs = this.runner.createOutputs()\n }\n\n // Create the context\n const context = new ModelContextImpl(inputs, outputs, options?.externalData)\n\n // When any input has an updated value, schedule a model run on the next tick\n const afterSet = () => {\n context.runNeeded = true\n this.runModelIfNeeded()\n }\n for (const input of inputs) {\n input.callbacks.onSet = afterSet\n }\n\n // Add to the set of contexts managed by the scheduler\n this.contexts.push(context)\n\n return context\n }\n\n /**\n * Remove the given context from the set of contexts managed by the scheduler.\n *\n * @param context The context to remove.\n */\n public removeContext(context: ModelContext): void {\n const index = this.contexts.findIndex(c => c === context)\n if (index >= 0) {\n this.contexts.splice(index, 1)\n }\n }\n\n /**\n * Schedule a model run (if not already pending). When the run is\n * complete, save the outputs and call the `onOutputsChanged` callback.\n */\n private runModelIfNeeded(): void {\n // Set a flag indicating that a new run is needed (even if one is already\n // in progress)\n this.runNeeded = true\n\n if (this.runInProgress) {\n // A run is already in progress; let it finish first\n return\n } else {\n // A run is not already in progress, so schedule it now. We use\n // `setTimeout` so that if a lot of inputs are all changing at once\n // (like after a reset), we wait for all those `set` or `reset`\n // calls to finish before gathering the input values into an array\n // and initiating the run on the next tick.\n this.runInProgress = true\n setTimeout(() => {\n // Kick off the (possibly asynchronous) model run\n this.runModelNow()\n }, 0)\n }\n }\n\n /**\n * Run the model asynchronously for all relevant contexts.\n */\n private async runModelNow(): Promise<void> {\n // Invalidate the initial outputs\n this.initialOutputs = undefined\n\n // Run the model for each context that requested a run\n for (const context of this.contexts) {\n if (context.runNeeded) {\n context.runNeeded = false\n await this.runModelNowForContext(context)\n }\n }\n\n // See if another run is needed\n if (this.runNeeded) {\n // Keep `runInProgress` set, but clear the `runNeeded` flag\n this.runNeeded = false\n setTimeout(() => {\n this.runModelNow()\n }, 0)\n } else {\n // No run needed, so clear both flags\n this.runNeeded = false\n this.runInProgress = false\n }\n }\n\n /**\n * Run the model asynchronously using the current set of input values in the given context.\n *\n * @param context The context to use for the model run.\n */\n private async runModelNowForContext(context: ModelContextImpl): Promise<void> {\n // If not already initialized, create a second array (that is shared for all\n // contexts) to hold a stable copy of the user inputs during model runs\n if (this.currentInputs === undefined) {\n this.currentInputs = Array(context.inputsArray.length)\n }\n\n // Copy the current inputs into a separate array; this ensures that the\n // following model runs all use the same inputs, even if the user continues\n // to change the inputs while the model is being run asynchronously\n for (let i = 0; i < context.inputsArray.length; i++) {\n this.currentInputs[i] = context.inputsArray[i].get()\n }\n\n // Run the model with the current set of input values and save the outputs\n try {\n // Perform the model run\n await this.runner.runModel(this.currentInputs, context.outputs)\n\n // Notify that the outputs have been updated\n context.onOutputsChanged?.()\n } catch (e) {\n console.error('ERROR: The scheduler encountered an error when running the model:', e)\n }\n }\n}\n\nclass ModelContextImpl implements ModelContext {\n /**\n * A copy of the `inputs` array that was passed to `addContext`.\n * @hidden This is intended for use by `MultiContextModelScheduler` only.\n */\n public readonly inputsArray: InputValue[]\n\n /**\n * The structure into which the model outputs will be stored.\n * @hidden This is intended for use by `MultiContextModelScheduler` only.\n */\n public readonly outputs: Outputs\n\n /**\n * Whether a model run is needed for this context.\n * @hidden This is intended for use by `MultiContextModelScheduler` only.\n */\n public runNeeded = false\n\n /**\n * Called when the outputs have been updated after a model run.\n */\n public onOutputsChanged?: () => void\n\n /**\n * @hidden This is intended for use by `MultiContextModelScheduler` only.\n *\n * @param inputs The input values, in the same order as in the spec file passed to `sde`.\n * @param outputs The structure into which the model outputs will be stored.\n * @param externalData Additional data that is external to the model outputs. For example, this can contain\n * data that was captured from an initial reference run, or other static data that is displayed in graphs\n * alongside the model output data in graphs.\n */\n constructor(\n inputs: InputValue[],\n outputs: Outputs,\n private readonly externalData: DataMap\n ) {\n this.inputsArray = Array.from(inputs)\n this.outputs = outputs\n }\n\n /**\n * Return the series data for the given model output variable or external\n * dataset.\n *\n * @param varId The ID of the output variable associated with the data.\n * @param sourceName The external data source name (e.g. \"Ref\"), or\n * undefined to use the latest model output data from this context.\n */\n public getSeriesForVar(varId: OutputVarId, sourceName?: SourceName): Series | undefined {\n if (sourceName === undefined) {\n // Return the latest model output data for this context\n return this.outputs.getSeriesForVar(varId)\n } else {\n const dataForSource = this.externalData.get(sourceName)\n if (dataForSource !== undefined) {\n // Return the external data\n return dataForSource.get(varId)\n } else {\n // No data found for the given source name\n return undefined\n }\n }\n }\n}\n"],"mappings":"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","names":["dimensions","extrasLengthInElements","_a"]}
|