from BPTK_Py import Model
from BPTK_Py import sd_functions as sd
Creating User-defined Functions in SD Models
Creating User-defined Functions in SD Models
One of the benefits of creating System Dynamics models in Python is that we can use the full power of Python to create our own functions, which we can then use in our models.
This how to illustrates how to do this.
First of all, lets set up our model:
= Model(starttime=1,stoptime=10,dt=0.25,name='TestModel') model
Now let’s define a function we would like to use in our model. A user defined function can have as many arguments as you like, but it must accept at least a model and time parameter (you don’t need to use the parameters if you don’t want to).
How you define your function is up to you - you can use any of the methods available in Python, such as class methods, using def, or lambda functions.
The example below uses a lambda function which simply multiplies the current time t
with 5.
= model.function("my_model_function", lambda model, t: 5*t) my_model_function
As you can see, much like with stocks and converters, we associate our function with the model by calling the models function
method.
Next we set up a converter:
= model.converter("converter") converter
The converters equation calls the model function.
= my_model_function() converter.equation
We can test the function as follows:
5) converter(
25.0
Let’s plot the function over time:
converter.plot()
We can also create a stock that has the converter as an inflow:
= model.stock("stock") stock
= converter stock.equation
stock.plot()
We can do all the usual arithmethic:
=converter/(sd.time()) stock.equation
stock.plot()
The function we created above was just dependent on time and not on other model variables. Let’s create a function that takes more arguments, e.g. one that multiplies a model variable with time.
You can add as many arguments as you like, but they must come after the model
and t
arguments.
= model.function("another_model_function", lambda model, t, input_function, multiplier : t*input_function*multiplier) another_model_function
Define a new converter which will be the input for the function:
= model.converter("input_function") input_function
= 5.0 input_function.equation
= model.converter("multiplier") multiplier
=1.0 multiplier.equation
Now add a converter which will apply the another_model_function
:
= model.converter("another_converter") another_converter
=another_model_function(input_function, multiplier) another_converter.equation
another_converter.plot()
from BPTK_Py.bptk import bptk
import numpy as np
=bptk() bptk
Of course functions defined in this way can also be used within scenarios. The quickest way to set up a scenario manager for a given model is as follows:
bptk.register_model(model)
This automatically creates a scenario manager whose name is the name of the model with the prefix “sm” and a base scenario. The models name is normalized to start with a capital letter (so TestModel is converted to smTestmodel).
It also creates a “base” scenario which runs the model as-is, without any changed settings.
You can list all scenarios and scenario managers using the list_scenarios
method.
=["smTestmodel"]) bptk.list_scenarios(scenario_managers
*** smTestmodel ***
base
Let’s add some new scenarios:
bptk.register_scenarios(=
scenarios
{"multiplier5": {
"constants": {
"multiplier": 5.0
}
},"multiplier10": {
"constants": {
"multiplier": 10.0
}
},"multiplier15": {
"constants": {
"multiplier": 15.0
}
}
}
,="smTestmodel") scenario_manager
=["smTestmodel"]) bptk.list_scenarios(scenario_managers
*** smTestmodel ***
base
multiplier5
multiplier10
multiplier15
=["smTestmodel"],scenarios=["base","multiplier5","multiplier10","multiplier15"],equations=["another_converter"]) bptk.plot_scenarios(scenario_managers