forio Toggle navigation

Model Creation in Vensim

When you create a model in Vensim, you can use it with the Epicenter platform by:

Then, when you create a user interface for your Vensim model on Epicenter, each user's interaction includes:

Creating and Uploading your Model File

Primary Vensim Model File

Epicenter directly simulates Vensim models, using a special Vensim engine.

In order to use a Vensim model, it must be saved in the VMF binary format (file name ending in ".vmf"). Other formats (such as "mdl" or "vpm") do not work with Epicenter.

Because the Vensim models are directly simulated and not translated, fidelity and performance are high. All mathematical expressions and functions are simulated exactly as in the desktop Vensim software.

Model variables designated as "GAME" variables are available for viewing and updating through the Epicenter APIs when you create your project's user interface. (See more on retrieving and updating variables in your project's user interface.)

Model variables designated as "CONSTANT" or "LOOKUP" variables can only be changed at the start of the simulation run. See the section on setting initial values, below.

Use the Epicenter user interface to upload your model file (.vmf) to the Model folder within your project.

External Data Used in Your Model

If your model uses external resources such as a spreadsheet or CSV file, upload that file to the Model folder within your project as well.

  • If you are using the current Epicenter v2 APIs, then the external data will automatically be available to your Vensim model. Uploading the external data to your project's Model folder is all you need to do.
    • This is true for external data in *.xls, *.xlsx, *.vdf, *.txt, *.tab, *.cin, and *.csv file formats.
    • The Interface Builder uses the v2 APIs, so if you are working with that, you're all set.
  • If you are using the older Epicenter v1 APIs, then in addition to uploading the external data to your project's Model folder, you also need to:
    • Include a files object (.cfg) or mapped_files object (.ctx) in your context file, and
    • Include a files field when you create a run.

For more information on working with external resources, see How To: Use External Data in Vensim. If you run into any problems, you can check the troubleshooting guide.

For more information on Epicenter API versions, see Version History.

Creating a Run

A "run" is a collection of end user interactions with the project and its model. Every time an end user wants to interact with a project, you as the project author need to create a new run.

If you are using the Interface Builder to create your interface, the name of your model file is detected automatically, and a run is created automatically when an end user visits this project page.

If you are using one of the Epicenter APIs, you'll need to create the run yourself.

For example, using the Run API Service (JavaScript), you might use:

var rs = new F.service.Run({
    account: 'acme-simulations', 
    project: 'supply-chain-game', 
    token: 'eyJhbGciOiJSUzI1NiJ9'
});
rs.create('supply-chain-model.vmf');

Or if you're using the Run API (RESTful), you might use:

curl -X POST \
    'https://api.forio.com/v2/run/acme-simulations/supply-chain-game' \
    --header 'Content-Type:application/json' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
    --data '{"model": "supply-chain-model.vmf"}'

Setting Initial Values

Model variables that describe initial conditions are typically updated exactly once, before the simulation begins. (You can think of these updates as being required to occur in "step 0.") These model variables are typically designated as "CONSTANT" or "LOOKUP" variables within Vensim and can only be changed at the start of the simulation run.

Use one of the Epicenter APIs to set constants and/or initial values.

For example, using the Run API Service (JavaScript), you might use:

rs.load('runID').then(function() 
    {rs.save(
        {variables: 
            {"initialConditionVariable": "initialValue"}
        }
    )}
);

Or if you're using the Run API (RESTful), you might use:

curl -X PATCH \
    'https://api.forio.com/v2/run/acme-simulations/supply-chain-game/runID/variables' \
    --header 'Content-Type:application/json' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
    --data '{"initialConditionVariable": "initialValue"}'

Notes:

  • For Vensim "LOOKUP" variables, the Epicenter format is an array. Each array element is itself an array with two elements: the x-y pairs from the original Vensim variable. For example:

    • Original Vensim LOOKUP representation: [(2000,0)-(2010,2)],(2000,1),(2005,.5),(2010,1)
    • Epicenter representation: [ [2000,1], [2005, .5], [2010, 1] ].
  • Variable names are case sensitive, so make sure that the variable names in your API calls match their case with the variable names in your Vensim model.

Initializing the Model to Step 1

The Interface Builder and Epicenter APIs both allow you to manipulate a run using operations exposed by the model. For Vensim models, there are four available operations: startGame, step, stepTo, and reset.

To initialize the model to step 1 for a particular run, use the operation startGame. This operation takes no arguments.

Using the separate startGame operation is optional if you are using the Epicenter v2 APIs. (Because it is not required, it is not available in the Operation drop-down menus in when you are using the Interface Builder.)

For example, if you are using the Epicenter.js Run API Service (JavaScript), you might use:

rs.load('runID').then(function() 
    { rs.do('startGame'); });

Or if you're using the Run API (RESTful), you might use:

curl -X POST \
    'https://api.forio.com/v2/run/acme-simulations/supply-chain-game/runID/operations/startGame' \
    --header 'Content-Type:application/json' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
    --data '{"arguments": []}'

Advancing the Model

The Interface Builder and Epicenter APIs both allow you to manipulate a run using operations exposed by the model. For Vensim models, there are four available operations: startGame, step, stepTo, and reset.

To advance the Vensim model for a particular run, use the step or stepTo operation.

  • The step operation advances the run a specified number of Vensim time units. It has one optional argument, a floating point number for the steps (Vensim time units) to advance. The default value is 1.
  • The stepTo operation advances the run up to a particular Vensim time, or the end of the model. It has one argument, which can be either:
    • An integer: step the model to that time but not past.
    • The string "end": step the run to the end of the sim.

If you are using the Interface Builder to create your project's interface, you can select Step under Add Operations for the Properties of a button. Optionally, you can select from the Parameters drop-down to choose how far to step (1 step, 10 steps, or to the end of the model). There is not an explicit stepTo available from the Interface Builder.

If you are using one of the Epicenter APIs, for example, you could advance the model by three steps using the Epicenter.js Run API Service:

rs.load('runID').then(function() 
    { rs.do('step', [3]); });

Or if you're using the Run API (RESTful), you might use:

curl -X POST \
    'https://api.forio.com/v2/run/acme-simulations/supply-chain-game/runID/operations/step' \
    --header 'Content-Type:application/json' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
    --data '{"arguments": [3]}'

Retrieving and Updating Variables

You can reference any Vensim variables from your project's user interface if they are designated as "GAME", "CONSTANT", or "LOOKUP" variables within Vensim.

You can update any of these types of Vensim variables before you start the simulation run. Once you have started the simulation, you can only update "GAME" variables. (If you're not sure about a particular variable, you can Introspect the run and check the access field for that variable: BEFORE means you can only update the variable before the model is advanced; ALWAYS means you can update the variable any time after the run is created.)

In the Interface Builder, enter the variable name under the Variable property of decisions, tables, or other components. In Flow.js, add the variable to an element on the page, for example using data-f-bind.

Unlike some other modeling languages supported by Epicenter, Vensim models are necessarily time-based: they deal in discrete steps, and the model advances over time. For this reason, each variable is actually an array of values over steps.

Important Notes on Variables

  • Steps are 1-based. Including the step is optional when you reference a variable. Leaving it off implies the current step. Only variables in the current step can be updated. The value from any step (including the current step) can be retrieved.

  • To retrieve the value of a variable in the current time step, you can either include the current time step as an array index, or append .POINT_IN_TIME to the name of the variable when you look it up.

  • To retrieve the value of an arrayed variable with the array collapsed for each step, append .COLLAPSED_ARRAY to the name of the variable when you look it up.

  • Variable names are case sensitive, so make sure that the variable names in your project's user interface match their case with the variable names in your Vensim model and in your model context file.

  • Variables that you want to save in the Epicenter backend database need to be noted in the model context file.

Scalars

To update or reference a scalar variable, use the variable name. Optionally, include the step in square brackets, [s]. Only variables in the current step can be updated. The value from any step (including the current step) can be retrieved.

Unlike other modeling languages, Vensim models are necessarily time-based: they deal in discrete steps, and the model advances over time. For this reason, each variable is actually an array of values over steps.

For example, suppose you have the variable Budget, which changes over time:

BudgetStep
1001
1202
1303

If you are using Flow.js, by default the value at the current step is selected. You can also specify a particular step. This looks like:

<!-- update Budget for current step -->
<input data-f-bind="Budget"></input> 

<!-- Budget for step 2: returns "120". can reference, but not update -->
<span data-f-bind="Budget[2]"></span>

You can list values of an array (that is, your scalar variable over all steps) using the data-f-foreach attribute.

And if you are using the Run API, this looks like:

<!-- update Budget for current step -->
curl -X PATCH \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables' \
    --header 'Content-Type:application/json' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
    --data '{"Budget": 95}'

<!-- Budget for step 2: returns "120". can reference, but not update -->
curl -G \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables/Budget[2]' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9'

<!-- Budget for current step, using the value of the step (3): returns 130 -->
curl -G \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables/Budget[3]' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9'

<!-- Budget for current step, using the POINT_IN_TIME notation: returns 130 -->
curl -G \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables/Budget.POINT_IN_TIME' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9'

Using the Run API, you can also ask for the variable over all steps. For example:

curl -G \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables/Budget' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9'

returns:

[
    100,
    120,
    130
]

Arrays

To update or reference an element of an array, use square brackets and strings to describe the index of the array: [indexName]. Optionally, include the step as the second subscript: [indexName,s]. Only variables in the current step can be updated. The value from any step (including the current step) can be retrieved.

For example, suppose in Vensim you have:

Sales, ApplesSales, OrangesStep
1002001
1202202
1302303
1402404

If you are using Flow.js, this looks like:

<!-- sales of apples in current step: returns 140 -->
<span data-f-bind="Sales[apples]"></span>

<!-- set sales of apples and oranges sold in current step
    (step 4), requires two different inputs -->
<input data-f-bind="Sales[apples][4]"></input>
<input data-f-bind="Sales[oranges][4]"></input>

You can list values of an array (that is, your variable over all steps) using the data-f-foreach attribute.

And if you are using the Run API, this looks like:

<!-- sales of apples in step 3: returns 130 -->
curl -G \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables/Sales[apples][3]' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9'

<!-- set sales of apples and oranges sold in current step
    (step 4), requires two different updates -->
curl -X PATCH \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables' \
    --header 'Content-Type:application/json' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
    --data '{"Sales[apples][4]": 150, "Sales[oranges][4]": 250}'

Using the Run API, you can also ask for the variable over all steps. For example:

curl -G \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables/Sales' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9'

returns:

{
    "apples": [
        100,
        120,
        130,
        140
    ],
    "oranges": [
        200,
        220,
        230,
        240
    ]
}

This format is easier to parse if you are looking for the values from a specific dimension of your array.

To retrieve the values in the current time step only, append .POINT_IN_TIME to the name of the variable when you look it up:

curl -G \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables/Sales.POINT_IN_TIME' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9'

returns:

{
    "apples": 140,
    "oranges": 240
}

To retrieve the values of your arrayed variable with the array collapsed for each step, append .COLLAPSED_ARRAY to the name of the variable when you look it up:

curl -G \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables/Sales.COLLAPSED_ARRAY' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9'

returns:

[
    [
        100,  // "apples" dimension for the first step
        200  // "oranges" dimension for the first step
    ],
    [
        120,  // "apples" dimension for the second step
        220   // "oranges" dimension for the second step
    ],
    [
        130,  // etc.
        230
    ],
    [
        140,
        240
    ]
]

This format is easier to parse if you are looking for all values from a specific step of your model, and can be helpful for example if you are graphing the values over steps.

Note that you cannot update variables which do not exist (including arrayed variables, for example Sales[pineapple] if your only products are apples and oranges). In other words, you cannot create new variables this way; your variables must already be defined in your model.

Multidimensional Arrays

For multidimensional arrays, you must explicitly specify the additional dimensions, either by adding the specific dimension, or by using * (wildcard) to indicate all dimensions.

For example, suppose in Vensim you have:

Sales, Apples, WestSales, Apples, EastStep
1002001
1202202
1302303
1402404

To look up all of the apple sales in the west region, you can use:

<!-- sales of apples in west region -->
curl -G \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables/Sales[apples,west]' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9'

And to look up all of the apple sales in all regions, you can use:

<!-- sales of apples in all regions -->
curl -G \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables/Sales[apples,*]' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9'

However, asking just for sales of apples will return an error:

<!-- asking for sales of apples without any region information is an error: returns 404  -->
curl -G \
    'https://api.forio.com/v2/run/acme-simulations/sample-vensim-model/000001577c0c5359720faa8b0c4b32e182d9/variables/Sales[apples]' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9'

Determining the Current Time or Step

In some situations, you may know already the time or step for which you want to view or update variables. If you are not sure, there are a few ways to determine this:

  • For the current step, read from the Step variable. This variable is automatically included for you and always holds the current Vensim step. (It is a scalar value, not an array.)

    For example, using the Run API Service (JavaScript), you might use:

      rs.load('runID', {include: 'Step'});

    Or if you're using the Run API (RESTful), you might use:

      curl -G \
          'https://api.forio.com/v2/run/acme-simulations/supply-chain-game/000001577c0c5359720faa8b0c4b32e182d9/variables/Step' \
          --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
  • For additional time details if you are working with Epicenter v2 APIs, read from the Time,Start Time, Final Time, or Time Step variables.

    The Time variable returns an array of the simulation times that you have stepped through so far, while the other variables return scalars. See the index, below for complete descriptions of each.

    For example, using the Run API Service (JavaScript), you might use:

      rs.load('runID', {include: 'Start Time'});

    Or if you're using the Run API (RESTful), you might use:

      curl -G \
          'https://api.forio.com/v2/run/acme-simulations/supply-chain-game/000001577c0c5359720faa8b0c4b32e182d9/variables/Start Time' \
          --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
  • For additional time details if you are working with Epicenter v1 APIs, request all of the time details with the getTimeDetails operation. (Important! This operation only works with the Epicenter v1 APIs.)

    This operation does not take any arguments.

    For example, using the Run API Service (JavaScript), you might use:

      rs.load('runID').then(function() 
          { rs.do('getTimeDetails'); });

    Or if you're using the Run API (RESTful), you might use:

      curl -X POST \
          'https://api.forio.com/v1/run/acme-simulations/supply-chain-game/runID/operations/getTimeDetails' \
          --header 'Content-Type:application/json' \
          --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \
          --data '{"arguments": []}'

    This operation returns an object showing the value of the Vensim TIME STEP variable (timeStep), the current Vensim time (time), the current Vensim step (step), and the start and end (final) times (startTime, finalTime) for the model:

      {
          "name": "getTimeDetails",
          "arguments": [],
          "result": {
              "timeStep": 0.08333,
              "time": 2000,
              "finalTime": 2050,
              "startTime": 2000
              "step": 1
          }
      }

Index of Available Vensim Operations

  • getTimeDetails
    • Arguments: none
    • Result: Returns an object showing the value of the Vensim TIME STEP variable (timeStep), the current Vensim time (time), the current Vensim step (step), and the start and end (final) times (startTime, finalTime) for the model.
    • Note! that this operation ONLY works with the Epicenter v1 APIs. (See more on the versions of the Epicenter APIs.)
    • More info
  • reset
    • Arguments: none
    • Result: Returns a new run, that is, a new instantiation of your model for an end user to play with. (Remember that a run is a collection of interactions with a model.) For example, this is useful if your end user needs to "start over" to create a new scenario within your project.
    • Note that this can ONLY be called from your project's user interface if you are using the Interface Builder or Flow.js. (Under the hood, this is not an operation as defined for the RESTful Run API. If you are building your project's user interface with the Epicenter RESTful APIs, you should just create a new run instead of calling reset().)
  • startGame
    • Arguments: none
    • Result: Initialize the model to step 1 for a particular run.
    • Note that this operation is optional if you are using the current version of the Epicenter APIs, v2. It is required if you are using the previous version of the Epicenter APIs. (See more on the version history.)
    • More info
  • step
    • Arguments: Optional, floating point number for steps (Vensim time units) to advance. If not provided, 1 is assumed.
    • Result: Advances the run the specified number of Vensim time units, rounded to the nearest multiple of Vensim TIME STEP.
    • More info
    • Note that step is also the name of a Vensim model variable (current Vensim step), see above. Don't accidentally confuse looking up the current step and advancing the model!
  • stepTo

    • Arguments:

      • Integer, the Vensim time unit to step to (but not past)

        or

      • String "end", step the run to the end of the sim.
    • Result: Advances the run up a particular Vensim time unit, or the end of the model.
    • More info

Index of Available Vensim Variables

In addition to any variables in your Vensim model, the following variables are available for reference when you are running a Vensim model on Epicenter.

  • Final Time, alias FINAL TIME: The end of your simulation.
  • Time: An array of the simulation times that you have stepped through so far.
  • Time Step, alias TIME STEP: The value of the Vensim TIME STEP variable.
  • Start Time, alias INITIAL TIME: The beginning of your simulation.
  • Step, alias STEP: The current step.

For example, in a model in which we have stepped twice and then asked for all of these variables, using the Run API (RESTful):

curl -G \
    'https://api.forio.com/v2/run/acme-simulations/supply-chain-game/000001577c0c5359720faa8b0c4b32e182d9/variables?include=Time,Start Time,Final Time,Time Step,Step' \
    --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9' \

which returns:

{
  "Start Time": 2015,
  "Final Time": 2020,
  "Time": [
    2015,
    2016,
    2017
  ],
  "Step": 3,
  "Time Step": 1
}