-
Notifications
You must be signed in to change notification settings - Fork 0
Utilizing SDEverywhere
The workflow for developing FeliX ISE was significantly streamlined by utilizing the SDEverywhere toolchain. SDEverywhere is a Vensim transpiler, which facilitates the integration of System Dynamics models into a web-based environment.
At the core of the application lies the FeliX IAM, a System Dynamics model initially developed in Vensim. Using SDEverywhere, the model is transpiled into WebAssembly (Wasm), a low-level binary format optimized for near-native execution speed in browsers. Table 1 below lists all SDEverywhere packages required for the application.
Table 1. A List of SDEverywhere packages used for the FeliX ISE
| Package | Version | Description |
|---|---|---|
@sdeverywhere/build |
0.3.4 | This package provides the core build and plugin API for SDEverywhere. |
@sdeverywhere/check-core |
0.1.2 | This package provides the core implementation of the System Dynamics model checking and comparison functionality in SDEverywhere. |
@sdeverywhere/cli |
0.7.23 | This package contains the sde command line interface for the SDEverywhere suite of tools. |
@sdeverywhere/plugin-check |
0.3.5 | This package provides a plugin that runs model checks and comparison tests for a given System Dynamics model generated by SDEverywhere. |
@sdeverywhere/plugin-config * |
0.2.4 | This package provides a plugin that reads CSV files used to configure a library or app around a System Dynamics model generated by SDEverywhere. |
@sdeverywhere/plugin-vite |
0.1.8 | This package provides a plugin that uses Vite and a given Vite configuration file to bundle an application or library as part of the SDEverywhere builder process (i.e., sde bundle or sde dev). |
@sdeverywhere/plugin-wasm |
0.2.3 | This package provides a plugin that builds a WebAssembly (Wasm) module for a given System Dynamics model generated by SDEverywhere. |
@sdeverywhere/plugin-worker |
0.2.3 | This package provides a plugin that generates a worker.js file that can run a System Dynamics model (as generated by SDEverywhere) asynchronously in a Web Worker or Node.js worker thread. |
* The functionality of the @sdeverywhere/plugin-config package was extended beyond its original design. Multiple additional columns were introduced, allowing the package to support a much wider range of configurations and to better meet the requirements of the FeliX ISE. These new columns (as well as the original ones) are described in detail in section “Configuration-Driven UI” below.
The development and production workflows are streamlined using Vite, a modern frontend build tool. During local development, the “sde dev” command utilizes Vite’s live-reload server, which automatically rebuilds the model and refreshes the UI upon changes to the model (.mdl) file, configuration (.csv) files, or any of the code contained in the “src” directory.
For production, the “npm run build” command uses the “sde bundle” process to generate static assets (HTML, CSS, JavaScript, images etc.).
These assets can then be deployed to a static hosting service, by using the “npm run deploy” command. GitHub Pages was chosen because the code was already hosted on GitHub, and it provided a free, reliable and easy-to-configure solution.
For more information on how SDEverywhere works, see: https://github.com/climateinteractive/SDEverywhere/wiki/Creating-a-Web-Application
The FeliX ISE is a static web application; therefore, it does not need a database to store information. Instead, during development, a directory named "config" is utilized, which contains CSV files (e.g., inputs.csv, graphs.csv) responsible for choosing which variables of the model to use, where to use them and how to present them in the UI.
Through these CSV files, mappings between model variables and UI components, such as sliders, switches, and graph definitions are specified, as shown in the following Figures. The code of the web application is separate and unaffected from these config files, while also allowing for dynamic rendering of the variables defined in the CSV files.
In more detail, each time a change is made in the CSV files, a new build process takes place, which replaces the previously generated model variables with the new ones. This design allows for modifying UI elements -- such as adjusting slider ranges, adding new graphs, or reorganizing input sections -- without altering application code, fostering collaboration between modelers and developers.
Useful Tip: The VSCode extension used above is Edit CSV, which can prove quite useful when working with CSV files inside VSCode.
In the previous Figure, the structure of the inputs.csv file is shown, where each row corresponds to a different input instance. The columns define the characteristics of each input, with key characteristics summarized in Table 2 below.
Table 2. List of key input characteristics as defined in the inputs.csv file
| Column Name | Possible Values | Description |
|---|---|---|
id |
Unique identifier (e.g., d1, d2, w1) |
A unique identifier for each input. |
input type |
slider, switch
|
Defines how the input is represented in the UI. |
categoryid * |
e.g., Diet Change, Food Loss and Waste
|
Identifies the category under which this input falls. |
input group * |
e.g., Self Efficacy, Social Norms
|
Groups inputs into logical sections. |
secondary type * |
dropdown main, dropdown assumptions, dropdown main label, dropdown combined, without
|
Defines additional categorization for inputs. |
label |
Name of the input | The display name of the input in the UI. |
varname |
Variable name (e.g., Self efficacy aggregated multiplier) |
The internal model variable linked to this input. |
description |
Text description | A brief explanation of what this input represents. |
hover description * |
Text shown on hover | Provides additional details when the user hovers over the input’s info tooltip. |
slider min |
Numeric value (e.g., 0, 2000) |
Minimum value for the slider input. |
slider max |
Numeric value (e.g., 2, 2100) |
Maximum value for the slider input. |
slider/switch default |
Default numeric value (e.g., 1, 2020) |
The default value when the UI loads. |
slider step |
Numeric value (e.g., 0.05, 1) |
The increment step for sliders. |
units |
Dmnl (dimensionless), years, etc. |
The unit of measurement for the input. |
format |
.2f, .0f
|
Defines the number format for the displayed values. |
controlled input ids |
List of input IDs like w1;w2|w3;w4
|
Specifies which other inputs this switch controls. |
segmented * |
"yes" or left blank |
Whether this slider should be rendered as a segmented button. |
mui icon * |
The name of a Material UI icon, or left blank | The Material UI icon to render on the left side of this input’s title. |
second label * |
Text | The title for the second button of the switch. |
extensive description * |
Name of a Markdown file | Renders the specified Markdown file inside a popup modal when the user clicks the “book” icon for this input. |
range N start |
Numeric value | The starting value for this slider’s range. |
range N label |
Text | The label for this slider’s range. |
enabled value |
Numeric value | The value when this switch is enabled. |
disabled value |
Numeric value | The value when this switch is disabled. |
* All these have been introduced as additional columns by extending the functionality of the @sdeverywhere/plugin-config, allowing the package to support a much wider range of configurations. See https://www.npmjs.com/package/@fmard/felix-plugin-config
Similarly to inputs.csv, the graphs.csv file defines the structure for graph instances. Each row represents a different graph instance, with columns describing its characteristics, as outlined in Table 3.
Table 3. List of key graph characteristics as defined in the graphs.csv file
| Column Name | Possible Values | Description |
|---|---|---|
id |
Unique identifier (e.g., fy, fx, f5, foo) |
A unique identifier for each graph. |
graph category * |
e.g., Diet Change, Food Loss and Waste
|
Identifies the category under which this graph falls. |
classification * |
Main, Etc
|
A broad classification of the graph. |
levels * |
Scenario1, Scenario2
|
Which scenario this graph corresponds to. |
graph title |
Title of the graph | The title displayed for the graph. |
kind |
stacked-line, line, etc. |
The type of graph visualization. |
scenario display * |
"combined" or left blank |
Whether two comparison graphs should be rendered as one combined graph or two separate ones. |
units |
Dmnl, Pcal / Year, Billion People, etc. |
The measurement units for the graph. |
description |
Explanation of the graph | A detailed description of what the graph represents. |
x axis min |
Numeric value (e.g., 1950) |
The minimum value for the x-axis. |
x axis max |
Numeric value (e.g., 2100) |
The maximum value for the x-axis. |
x axis label |
Time (Year) |
The label for the x-axis. |
y axis min |
Numeric value (optional, e.g., 0) |
The minimum value for the y-axis. |
y axis max |
Numeric value (optional, e.g., 1) |
The maximum value for the y-axis. |
y axis label |
Dmnl, Billion ha, kcal / (Person * Day)
|
The label for the y-axis. |
Plot Variables (1-15) |
e.g., Diet Composition Percentage[PasMeat]
|
The variables plotted on the graph. |
Plot Styles (1-15) |
line, area, etc. |
Defines the visualization style of each plot. |
Plot Labels (1-15) |
Labels like Pas Meat, Crop Meat, Dairy, etc. |
The display labels for each plotted variable. |
Plot Colors (1-15) |
maroon, green, red, olive, etc. |
The colors used for the graph. |
Plot Sources (1-15) |
"Ref" or left blank |
Whether this variable should render as a reference line (Business As Usual scenario). |
* All these have been introduced as additional columns by extending the functionality of the @sdeverywhere/plugin-config, allowing the package to support a much wider range of configurations. See https://www.npmjs.com/package/@fmard/felix-plugin-config