npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@sdeverywhere/runtime

v0.2.5

Published

This package provides a simplified runtime API around a System Dynamics model as generated by the [SDEverywhere](https://github.com/climateinteractive/SDEverywhere) transpiler.

Downloads

79

Readme

@sdeverywhere/runtime

This package provides a simplified runtime API around a System Dynamics model as generated by the SDEverywhere transpiler.

Note that the SDEverywhere transpiler can be configured to generate model code in different formats:

  • JavaScript code, which can be used directly without an extra compilation step, or
  • C code, which can be compiled to a more optimized WebAssembly (Wasm) module (this requires an extra tool called Emscripten; see the @sdeverywhere/plugin-wasm package for more details)

The @sdeverywhere/runtime package presents a format-agnostic API that can be used to run your model, regardless of whether you generate a pure JavaScript model or a WebAssembly model.

Quick Start

The best way to get started with SDEverywhere is to follow the Quick Start instructions. If you follow those instructions, the @sdeverywhere/runtime package will be added to your project automatically, in which case you can skip the next section and jump straight to the "Usage" section below.

Install

# npm
npm install @sdeverywhere/runtime

# pnpm
pnpm add @sdeverywhere/runtime

# yarn
yarn add @sdeverywhere/runtime

Usage

NOTE: If you followed the "Quick Start" instructions and/or used the @sdeverywhere/create package to generate your project, the initialization steps listed below are already implemented for you in the generated core package, and you can work directly with a ModelRunner and/or ModelScheduler instance.

1. Import your generated model

In your application, import the model file that was generated by the SDEverywhere transpiler. Depending on how you configured your project (for example, if you set a different prepDir), the generated model file may be in a different location than what is shown in this example, but the approach will generally be the same.

import loadGeneratedModel from './sde-prep/generated-model.js'

2. Initialize a ModelRunner

The next step is to create a ModelRunner instance, which simplifies the process of running a WasmModel with a given set of inputs and parsing the outputs. The ModelRunner produces an Outputs instance that provides easy access to time series data for each output variable in the model.

Note that SDEverywhere offers two implementations of the ModelRunner interface:

  • The createSynchronousModelRunner function creates a ModelRunner that runs your generated model on the main JavaScript thread. This is the simplest option and is sufficient for small models, but for larger models that take longer to run, it may block the JavaScript thread and cause your application to appear unresponsive.
  • The spawnAsyncModelRunner function (in the separate @sdeverywhere/runtime-async package) provides an alternative implementation of ModelRunner that runs your generated model in a Web Worker or Node.js worker thread. This requires an extra build-time step (see the @sdeverywhere/plugin-worker package), but the benefit of an asynchronous runner is that the model can run in a separate thread, which frees up the main thread for user interface work and other computation.

The following example demonstrates the use of the createSynchronousModelRunner function:

import { createSynchronousModelRunner } from '@sdeverywhere/runtime'
import loadGeneratedModel from './sde-prep/generated-model.js'

async function main() {
  // Initialize the `ModelRunner`
  const generatedModel = await loadGeneratedModel()
  const modelRunner = createSynchronousModelRunner(generatedModel)

  // Create an array that holds the model input values; these must be in the same order
  // as the inputs that are specified in your `sde.config.js` or `spec.json` file
  const inputs = [2, 10] // etc

  // Create an `Outputs` instance to hold the model outputs
  let outputs = modelRunner.createOutputs()

  // Run the model with those inputs
  outputs = await modelRunner.runModel(inputs, outputs)

  // Get the time series data and/or a specific value for a given output variable
  const series = outputs.getSeriesForVar('_temperature_change_from_1850')
  const tempChangeIn2100 = series.getValueAtTime(2100)
  console.log(`Temperature change in 2100: ${tempChangeIn2100}`)

3. Initialize a ModelScheduler (optional)

If you build a more complex application with a user interface around a model (especially with a responsive web framework such as Svelte, Vue, React, etc), the ModelScheduler class takes care of automatically scheduling and running the model whenever there are changes to input variables:

import { createInputValue, createSynchronousModelRunner, ModelScheduler } from '@sdeverywhere/runtime'
import loadGeneratedModel from './sde-prep/generated-model.js'

async function initModel() {
  // Initialize the `ModelRunner`
  const generatedModel = await loadGeneratedModel()
  const modelRunner = createSynchronousModelRunner(generatedModel)

  // Create an array of reactive `InputValue` instances; these must be in the same order
  // as the inputs that are specified in your `sde.config.js` or `spec.json` file
  const inputs = [createInputValue('_input1', 2), createInputValue('_input2', 0)] // etc

  // Create a `ModelScheduler`
  const outputs = modelRunner.createOutputs()
  const modelScheduler = new ModelScheduler(modelRunner, inputs, outputs)

  // Get notified when new output data is available
  modelScheduler.onOutputsChanged = newOutputs => {
    // Update the user interface to reflect the new output data, etc
  }

  // When you change the value of an input, the scheduler will automatically
  // run the model and call `onOutputsChanged` when new outputs are ready
  inputs[0].set(3)
}

Emscripten Notes

If you use the @sdeverywhere/plugin-wasm package to build a WebAssembly version of your model, the following steps are already handled for you. The notes below are only needed if you want more low-level control over how the C model is compiled into a WebAssembly module.

The @sdeverywhere/runtime package assumes you have created <mymodel>.wasm and <mymodel>.js files with Emscripten. The emcc command line options should be similar to the following:

$ emcc \
build/<mymodel>.c build/macros.c build/model.c build/vensim.c \
-Ibuild -o ./output/<mymodel>.js -Wall -Os \
-s STRICT=1 -s MALLOC=emmalloc -s FILESYSTEM=0 -s MODULARIZE=1 \
-s EXPORTED_FUNCTIONS="['_malloc','_free','_getInitialTime','_getFinalTime','_getSaveper','_setLookup','_runModelWithBuffers']" \
-s EXPORTED_RUNTIME_METHODS="['cwrap']"

Note that the generated module must export the following functions at minimum:

  • _malloc
  • _free
  • _getInitialTime
  • _getFinalTime
  • _getSaveper
  • _setLookup
  • _runModelWithBuffers
  • cwrap

Documentation

API documentation is available in the docs directory.

License

SDEverywhere is distributed under the MIT license. See LICENSE for more details.