Vensim Translation¶
PySD parses a vensim ‘.mdl’ file and translates the result into python, creating a new file in the
same directory as the original. For example, the Vensim file Teacup.mdl
:
{UTF-8}
Characteristic Time=
10
~ Minutes
~ |
Heat Loss to Room=
(Teacup Temperature - Room Temperature) / Characteristic Time
~ Degrees/Minute
~ This is the rate at which heat flows from the cup into the room. We can \
ignore it at this point.
|
Room Temperature=
70
~
~ |
Teacup Temperature= INTEG (
-Heat Loss to Room,
180)
~ Degrees
~ |
********************************************************
.Control
********************************************************~
Simulation Control Parameters
|
FINAL TIME = 30
~ Minute
~ The final time for the simulation.
|
INITIAL TIME = 0
~ Minute
~ The initial time for the simulation.
|
SAVEPER =
TIME STEP
~ Minute [0,?]
~ The frequency with which output is stored.
|
TIME STEP = 0.125
~ Minute [0,?]
~ The time step for the simulation.
|
becomes Teacup.py
:
"""
Python model test-models/samples/teacup/teacup.py
Translated using PySD version 0.7.5
"""
from __future__ import division
import numpy as np
from pysd import utils
import xarray as xr
from pysd.functions import cache
from pysd import functions
_subscript_dict = {}
_namespace = {
'SAVEPER': 'saveper',
'Characteristic Time': 'characteristic_time',
'Teacup Temperature': 'teacup_temperature',
'FINAL TIME': 'final_time',
'INITIAL TIME': 'initial_time',
'Heat Loss to Room': 'heat_loss_to_room',
'Room Temperature': 'room_temperature',
'TIME STEP': 'time_step',
'Time': 'time',
'TIME': 'time'
}
@cache('run')
def final_time():
"""
FINAL TIME
----------
(final_time)
Minute
The final time for the simulation.
"""
return 30
integ_teacup_temperature = functions.Integ(lambda: -heat_loss_to_room(), lambda: 180)
@cache('run')
def time_step():
"""
TIME STEP
---------
(time_step)
Minute [0,?]
The time step for the simulation.
"""
return 0.125
@cache('step')
def heat_loss_to_room():
"""
Heat Loss to Room
-----------------
(heat_loss_to_room)
Degrees/Minute
This is the rate at which heat flows from the cup into the room. We can
ignore it at this point.
"""
return (teacup_temperature() - room_temperature()) / characteristic_time()
@cache('run')
def initial_time():
"""
INITIAL TIME
------------
(initial_time)
Minute
The initial time for the simulation.
"""
return 0
@cache('step')
def teacup_temperature():
"""
Teacup Temperature
------------------
(teacup_temperature)
Degrees
"""
return integ_teacup_temperature()
@cache('run')
def characteristic_time():
"""
Characteristic Time
-------------------
(characteristic_time)
Minutes
"""
return 10
@cache('run')
def room_temperature():
"""
Room Temperature
----------------
(room_temperature)
"""
return 70
@cache('step')
def saveper():
"""
SAVEPER
-------
(saveper)
Minute [0,?]
The frequency with which output is stored.
"""
return time_step()
This allows model execution independent of the Vensim environment, which can be handy for deploying models as backends to other products, or for performing massively parallel distributed computation.
These translated model files are read by PySD, which provides methods for modifying or running the model and conveniently accessing simulation results.
Translated Functions¶
Ongoing development of the translator will support the full subset of Vensim functionality that has an equivalent in XMILE. The current release supports the following functionality:
Vensim | Python Translation |
---|---|
COS | np.cos |
EXP | np.exp |
MIN | min |
<= | <= |
STEP | functions.step |
PULSE | functions.pulse |
POISSON | np.random.poisson |
EXPRND | np.random.exponential |
SIN | np.sin |
>= | >= |
IF THEN ELSE | functions.if_then_else |
LN | np.log |
PULSE TRAIN | functions.pulse_train |
RAMP | functions.ramp |
INTEGER | int |
TAN | np.tan |
PI | np.pi |
= | == |
< | < |
> | > |
MODULO | np.mod |
ARCSIN | np.arcsin |
ABS | abs |
^ | ** |
LOGNORMAL | np.random.lognormal |
MAX | max |
SQRT | np.sqrt |
ARCTAN | np.arctan |
ARCCOS | np.arccos |
RANDOM NORMAL | self.functions.bounded_normal |
RANDOM UNIFORM | np.random.rand |
DELAY1 | functions.Delay |
DELAY3 | functions.Delay |
DELAY N | functions.Delay |
SMOOTH3I | functions.Smooth |
SMOOTH3 | functions.Smooth |
SMOOTH N | functions.Smooth |
SMOOTH | functions.Smooth |
INITIAL | functions.Initial |
XIDZ | functions.XIDZ |
ZIDZ | functions.XIDZ |
np corresponds to the numpy package
Additionally, identifiers are currently limited to alphanumeric characters and the dollar sign $.
Future releases will include support for:
- subscripts
- arrays
- arbitrary identifiers
There are some constructs (such as tagging variables as ‘suplementary’) which are not currently parsed, and may throw an error. Future releases will handle this with more grace.