Home

Awesome

SDEverywhere    Build

SDEverywhere is a collection of libraries and command line tools that help you improve the quality and expand the reach of a System Dynamics model. SDEverywhere allows for unit testing, continuous integration, the ability to compare model runs, and a toolchain to transform a model into C, JavaScript, and WebAssembly code.

Using SDEverywhere, you can deploy interactive System Dynamics models on mobile, desktop, and the web for policymakers and the public. Or you could perform model analysis using general-purpose languages, running the model as high-performance JavaScript or C code.

By following the "Quick Start" instructions below, within minutes you can turn a Vensim model like this:

<img width="500" alt="sde-vensim" src="https://github.com/climateinteractive/SDEverywhere/assets/438425/97e9b89e-54e4-438e-8cbd-51b9cd10a027"> <p> <br/> ...into an interactive (and fully customizable) simulator that runs in any web browser: </p> <img width="500" alt="sde-explorer" src="https://github.com/climateinteractive/SDEverywhere/assets/438425/95a51d0d-0201-47ae-b224-9820709de6c2">

Supported Platforms

The SDEverywhere tools can be used on on any computer running macOS, Windows, or Linux. The libraries and code generated by SDEverywhere can be run in web browsers on almost any device (including phones and tablets) as well as on the server side (using C/C++, JavaScript, and/or WebAssembly).

Supported File Formats

SDEverywhere currently supports a broad range of System Dynamics models in Vensim format and handles many features of the Vensim modeling language, including subscripts, subranges, and subscript mapping. The full list of Vensim functions that are implemented in SDEverywhere can be found on the Supported Vensim Functions page in the SDEverywhere wiki.

Support for models in XMILE format (as used by e.g., Stella) is not yet available. However, our long-term vision is for SDEverywhere to have first-class support for both Vensim and XMILE formats. Please get in touch on the discussion board if you are interested in helping to add support for XMILE.

Features

Live Editing

SDEverywhere provides a live development environment and configuration files that allow you to see your edits in real time. Every time you save changes to your Vensim model or to the CSV config files, the local builder automatically rebuilds your project and the changes appear instantaneously in your browser, no manual reloads required.

The following video demonstrates using a text editor to make simple edits in the CSV config files that affect the appearance and behavior of the generated web application. In the video, we tweak the color of a graph plot, change an axis label, and set a new default for a slider. All of these settings and more can be configured by editing the CSV files in your favorite text editor or in Excel.

https://github.com/climateinteractive/SDEverywhere/assets/438425/cd495776-5744-40b9-a922-8ad5b138106c

Quality Checks and Comparisons

SDEverywhere includes extensive QA (quality assurance) tools that you can run as you develop your model, either locally on your machine or in the cloud in a continuous integration environment (or both). There is support for two different kinds of tests:

In the following video, we demonstrate how the model-check tools can be run alongside Vensim to give you immediate feedback whenever you make changes to your model. In this example, we have an existing "check" test that verifies that the different population variables always produce values in the range 0 to 10000. If we multiply a variable by -1 and save the model file, the builder detects the change and re-runs all the defined check and comparison tests.

Since the "Recovered Population" variable is now producing negative values, there is a failing check that gets flagged in the Model Check report, showing that the data now goes outside the expected (green) range. Additionally, the comparison tests show how the new model results differ from the previous ones over many different input scenarios.

https://github.com/climateinteractive/SDEverywhere/assets/438425/b6f05b3f-f18a-48c4-89a9-80f1d8bfbfde

Core Functionality

At its core, SDEverywhere includes a transpiler that can read a Vensim model and generate a high-performance version of that model as JavaScript or C code.

The sde command line tool — in addition to generating JavaScript or C code — provides a plugin-based build system for extended functionality:

Additionally, the runtime and runtime-async packages make it easy to interact with your generated model in a JavaScript- or TypeScript-based application.

For more details on all of these packages, refer to the "Packages" section below.

Requirements

The SDEverywhere libraries and tools can be used on any computer running macOS, Windows, or Linux.

SDEverywhere requires Node.js version 18 or later (the current LTS version 20 is recommended). Node.js is a cross-platform runtime environment that allows for running JavaScript-based tools (like SDEverywhere) on macOS, Windows, and Linux computers.

Note: It is not necessary to have extensive knowledge of Node.js and JavaScript in order to use SDEverywhere, but a one-time download of Node.js is necessary to get started. Once you download and install Node.js, you can run the commands listed on this page that start with npm. (The npm command line tool is included when you install the Node.js runtime environment.)

If you are already familiar with Node.js and have it installed, note that SDEverywhere is also compatible with the pnpm and Yarn package managers, which can be used as an alternative to npm.

Quick Start

The following video shows what it will look like when you follow the steps in this section. In this video, we demonstrate commands that turn a Vensim model (the SIR model from examples/sir) into a web application project.

https://github.com/climateinteractive/SDEverywhere/assets/438425/c0c81bcd-f5a5-4cf1-8698-be46118d7c9c

As shown in the video above, the quickest way to get started with SDEverywhere is to open your terminal emulator ("Terminal" on macOS or Linux, or "Command Prompt" on Windows) and type the commands explained below.

If you already have a directory containing a Vensim mdl file, change to that directory first. (The script will generate some new files in that directory, so if you would prefer, feel free to create a fresh directory that includes just your mdl file.)

# Change to the directory containing your `mdl` file:
cd my-project-folder

Or, if you don't already have a Vensim mdl file, and/or you want to evaluate SDEverywhere for the first time, you can create an empty directory, and the script will provide a sample model to get you started:

# Create an empty directory and change to that directory:
mkdir my-project-folder
cd my-project-folder

Once you are in the correct folder, run the create script:

# Use `npm` to run the "create" script:
npm create @sdeverywhere@latest

# Or, if you use pnpm:
pnpm create @sdeverywhere@latest

# Or, if you use Yarn:
yarn create @sdeverywhere

Answer a few questions, and within minutes you can have a functional web application that runs your model!

Documentation

Detailed API and usage documentation for each @sdeverywhere package can be found in the "Packages" section below.

Additional user guides and documentation for contributors can be found in the SDEverywhere wiki. For example:

Caveats

SDEverywhere has been used to generate code for complex models with thousands of equations, but your model may use features of Vensim that SDEverywhere cannot translate yet. Please fork our code and contribute! Here are some prominent current limitations:

Tabbed arrays and macros are removed from the model during preprocessing and written to the removals.txt file for your reference.

SDEverywhere in Production

Packages

SDEverywhere is developed in a monorepo structure. Each package listed in the table below is developed as a separate npm package/library under the packages directory in this repository. All packages are published independently to the npm registry.

If you're new to SDEverywhere, refer to the "Quick Start" section above. Running the npm create @sdeverywhere@latest command described in that section will take care of setting up a recommended project structure and will install/configure the necessary @sdeverywhere packages from the table below.

If you want more control over which packages are installed, or for API documentation and configuration instructions, refer to the links below.

Packages marked with an asterisk (*) are implementation details. Most users won't need to interact with these implementation packages directly, but they may be useful for advanced use cases (for example, if you want to create a new build plugin or a custom test runner).

<table> <tr> <th>Package</th> <th>Version</th> <th>Links</th> </tr> <tr> <td colspan="3"><em>Project creation</em></td> </tr> <tr> <td><a href="./packages/create">@sdeverywhere/create</a></td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/create"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/create.svg?label=%20"></a></td> <td> <a href="./packages/create">Source</a>&nbsp;|&nbsp; <a href="./packages/create/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/create/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td colspan="3"><em>Command line interface</em></td> </tr> <tr> <td><a href="./packages/cli">@sdeverywhere/cli</a></td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/cli"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/cli.svg?label=%20"></a></td> <td> <a href="./packages/cli">Source</a>&nbsp;|&nbsp; <a href="./packages/cli/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/cli/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td colspan="3"><em>Build plugins</em></td> </tr> <tr> <td><a href="./packages/plugin-config">@sdeverywhere/plugin-config</a></td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/plugin-config"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/plugin-config.svg?label=%20"></a></td> <td> <a href="./packages/plugin-config">Source</a>&nbsp;|&nbsp; <a href="./packages/plugin-config/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/plugin-config/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td><a href="./packages/plugin-wasm">@sdeverywhere/plugin-wasm</a></td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/plugin-wasm"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/plugin-wasm.svg?label=%20"></a></td> <td> <a href="./packages/plugin-wasm">Source</a>&nbsp;|&nbsp; <a href="./packages/plugin-wasm/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/plugin-wasm/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td><a href="./packages/plugin-worker">@sdeverywhere/plugin-worker</a></td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/plugin-worker"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/plugin-worker.svg?label=%20"></a></td> <td> <a href="./packages/plugin-worker">Source</a>&nbsp;|&nbsp; <a href="./packages/plugin-worker/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/plugin-worker/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td><a href="./packages/plugin-vite">@sdeverywhere/plugin-vite</a></td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/plugin-vite"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/plugin-vite.svg?label=%20"></a></td> <td> <a href="./packages/plugin-vite">Source</a>&nbsp;|&nbsp; <a href="./packages/plugin-vite/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/plugin-vite/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td><a href="./packages/plugin-check">@sdeverywhere/plugin-check</a></td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/plugin-check"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/plugin-check.svg?label=%20"></a></td> <td> <a href="./packages/plugin-check">Source</a>&nbsp;|&nbsp; <a href="./packages/plugin-check/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/plugin-check/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td colspan="3"><em>Runtime libraries</em></td> </tr> <tr> <td><a href="./packages/runtime">@sdeverywhere/runtime</a></td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/runtime"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/runtime.svg?label=%20"></a></td> <td> <a href="./packages/runtime">Source</a>&nbsp;|&nbsp; <a href="./packages/runtime/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/runtime/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td><a href="./packages/runtime-async">@sdeverywhere/runtime-async</a></td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/runtime-async"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/runtime-async.svg?label=%20"></a></td> <td> <a href="./packages/runtime-async">Source</a>&nbsp;|&nbsp; <a href="./packages/runtime-async/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/runtime-async/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td colspan="3"><em>Build/CLI implementation</em></td> </tr> <tr> <td><a href="./packages/build">@sdeverywhere/build</a> *</td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/build"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/build.svg?label=%20"></a></td> <td> <a href="./packages/build">Source</a>&nbsp;|&nbsp; <a href="./packages/build/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/build/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td><a href="./packages/compile">@sdeverywhere/compile</a> *</td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/compile"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/compile.svg?label=%20"></a></td> <td> <a href="./packages/compile">Source</a>&nbsp;|&nbsp; <a href="./packages/compile/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/compile/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td><a href="./packages/parse">@sdeverywhere/parse</a> *</td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/parse"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/parse.svg?label=%20"></a></td> <td> <a href="./packages/parse">Source</a>&nbsp;|&nbsp; <a href="./packages/parse/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/parse/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td colspan="3"><em>`model-check` implementation</em></td> </tr> <tr> <td><a href="./packages/check-core">@sdeverywhere/check-core</a> *</td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/check-core"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/check-core.svg?label=%20"></a></td> <td> <a href="./packages/check-core">Source</a>&nbsp;|&nbsp; <a href="./packages/check-core/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/check-core/CHANGELOG.md">Changelog</a> </td> </tr> <tr> <td><a href="./packages/check-ui-shell">@sdeverywhere/check-ui-shell</a> *</td> <td><a href="https://www.npmjs.com/package/@sdeverywhere/check-ui-shell"><img style="vertical-align:middle;" src="https://img.shields.io/npm/v/@sdeverywhere/check-ui-shell.svg?label=%20"></a></td> <td> <a href="./packages/check-ui-shell">Source</a>&nbsp;|&nbsp; <a href="./packages/check-ui-shell/README.md">Docs</a>&nbsp;|&nbsp; <a href="./packages/check-ui-shell/CHANGELOG.md">Changelog</a> </td> </tr> </table>

Contributing

SDEverywhere covers a subset of the Vensim modeling language used in models that have been deployed with it. There is still much to contribute, for example:

For more guidance on contributing to SDEverywhere, please consult the wiki.

License

All packages developed in the SDEverywhere repository are distributed under the MIT license. See LICENSE for more details.