Simulation of models in JModelica.org is preformed via the simulate method of a model object. The model objects in JModelica.org are:
JMUModel (located in pyjmi)
FMUModel (located in pyfmi)
The difference between the two are that JMUModel supports compiled models from JModelica.org (extension .jmu) while the FMUModel supports compiled models from other simulation/modelling tools that follow the FMI standard (extension .fmu). For more information
about compiling a model in JModelica.org see Chapter 4.
The simulation method is the preferred method for simulation of models and which by default is connected to the Assimulo simulation
package but can also be connected to other simulation platforms. The simulation method for FMUModel is defined as:
class FMUModel(...)
...
def simulate(self,
start_time=0.0,
final_time=1.0,
input=(),
algorithm='AssimuloFMIAlg',
options={}):
And used in the following way:
res = FMUModel.simulate() #Using default values
The only difference between the simulation method in JMUModel compared to FMUModel is that the algorithm is AssimuloAlg. They are although both connected to the Assimulo package and able to use its solvers.
The start and final time attributes are simply the time where the solver should start the integration and stop the integration.
The input however is a bit more complex and is described in more detail in the following section. The algorithm attribute
is where the different simulation package can be specified, however currently only a connection to Assimulo is supported and
connected through the algorithm AssimuloAlg for JMUModel and AssimuloFMIAlg for FMUModel.
The input defines the input trajectories to the model and should be a 2-tuple consisting of the name(s) of the input variables and the second argument should be either a data matrix or a function. If the argument is a data matrix it should contain a time vector as the first column and the second column should correspond to the first name in the first argument and so forth. If instead the second argument is a function it should be defined to take the time as input and return the number of inputs in the order defined by the first argument.
For example, consider that we have a model with an input variable u1 and that the model should be driven by a sinus wave as input. Also we are interested in the interval 0 to 10.
t = N.linspace(0.,10.,100) #Create one hundred evenly spaced points u = N.sin(t) #Create the input vector u_traj = N.transpose(N.vstack((t,u))) #Create the data matrix and transpose #it to the correct form
The above code have created the data matrix that we are interested in giving to the model as input, we just need to connect
the data to a specific input variable, u1:
input_object = ('u1', u_traj)
Now we are ready to simulate using the input and simulate 10 seconds.
res = model.simulate(final_time=10, input=input_object)
If we on the other hand would have two input variables, u1 and u2 the script would instead look like:
t = N.linspace(0.,10.,100) #Create one hundred evenly spaced points u1 = N.sin(t) #Create the first input vector u2 = N.cos(t) #Create the second input vector u_traj = N.transpose(N.vstack((t,u1,u2))) #Create the data matrix and #transpose it to the correct form input_object = (['u1','u2'], u_traj) res = model.simulate(final_time=10, input=input_object)
Note that the variables are now a List of variables.
If we were to do the same example using input functions instead, the code would like for the single input case:
input_object = ('u1', N.sin)and for the double input case:
def input_function(t):
return N.array([N.sin(t),N.cos(t)])
input_object = (['u1','u2'],input_function)
The options attribute are where options to the specified algorithm are stored and are preferably used together with:
opts = JMUModel.simulate_options()
which returns the default options for the default algorithm. Information about the available options can be viewed by typing
help on the opts variable:
>>> help(opts) Options for simulation of a JMU model using the Assimulo simulation package. The Assimulo package contain both explicit solvers (CVode) for ODEs and implicit solvers (IDA) for DAEs. The ODE solvers require that the problem is written on the form, ydot = f(t,y). ...
In Table 7.1 the general options for the AssimuloAlg algorithm are described while in Table 7.3 a selection of the different solver arguments for the DAE solver IDA is shown. In Table 7.2 a selection of solver arguments for the ODE solver CVode is shown. More information regarding the solver options can be found here, http://www.jmodelica.org/assimulo.
Table 7.1. General options for AssimuloAlg.
| Option | Default | Description |
|---|---|---|
| solver | 'IDA' | Specifies the simulation method that is to be used. |
| ncp | 0 | Number of communication points. If ncp is zero, the solver will return the internal steps taken. |
| initialize | True | If set to True, an algorithm for initializing the differential equation is invoked, otherwise the differential equation is assumed to have consistent initial conditions. |
| write_scaled_result | False | Set this parameter to True to write the result to file without taking scaling into account. If the value of scaled is False, then the variable scaling factors of the model are used to reproduced the unscaled variable values. |
| result_file_name | Empty string (default generated file name will be used) | Specifies the name of the file where the simulation result is written. Setting this option to an empty string results in a default file name that is based on the name of the model class. |
Lets look at an example, consider that you want to simulate a JMU model using the solver CVode together with changing the discretization method (discr) from BDF to Adams:
... opts = model.simulate_options() #Retrieve the default options opts['solver'] = 'CVode' #Change the solver from IDA to CVode opts['CVode_options']['discr'] = 'Adams' #Change from using BDF to Adams model.simulate(options=opts) #Pass in the options to simulate and simulate
It should also be noted from the above example the options regarding a specific solver, say the tolerances for CVode or IDA, should be stored in a double dictionary where the first is named after the solver concatenated with _options:
opts['CVode_options']['atol'] = 1.0e-6 #Options specific for CVode #or opts['IDA_options']['atol'] = 1.0e-6 #Options specific for IDA
For the general options, as changing the solver, they are accessed as a single dictionary:
opts['solver'] = 'CVode' #Changing the solver
opts['ncp'] = 1000 #Changing the number of communication points.
Table 7.2. Selection of solver arguments for CVode
| Option | Default | Description |
|---|---|---|
| discr | 'BDF' | The discretization method. Can be either 'BDF' or 'Adams' |
| iter | 'Newton' | The iteration method. Can be either 'Newton' or 'FixedPoint'. |
| maxord | 5 | The maximum order used. Maximum for 'BDF' is 5 while for the 'Adams' method the maximum is 12 |
| maxh | Inf | Maximum step-size. Positive float. |
| atol | 1.0e-6 | Absolute Tolerance. Can be an array of floats where each value corresponds to the absolute tolerance for the corresponding variable. Can also be a single positive float. |
| rtol | 1.0e-6 | Relative Tolerance. Positive float. |
Table 7.3. Selection of solver arguments for IDA
| Option | Default | Description |
|---|---|---|
| maxord | 5 | The maximum order used. Positive integer. |
| maxh | Inf | Maximum step-size. Positive float. |
| atol | 1.0e-6 | Absolute Tolerance. Can be an array of floats where each value corresponds to the absolute tolerance for the corresponding variable. Can also be a single positive float. |
| rtol | 1.0e-6 | Relative Tolerance. Positive float. |
| suppress_alg | False | Suppress the algebraic variables on the error test. Can be either False or True. |
| sensitivity | False | If set to True, sensitivities for the states with respect to parameters set to free in the model will be calculated. |
The options attribute are where options to the specified algorithm are stored and are preferably used together with:
opts = FMUModel.simulate_options()
which returns the default options for the default algorithm. Information about the available options can be viewed by typing
help on the opts variable:
>>> help(opts) Options for the solving the FMU using the Assimulo simulation package. Currently, the only solver in the Assimulo package that fully supports simulation of FMUs is the solver CVode. ...
In Table 7.4 the general options for the AssimuloFMIAlg algorithm are described while in Table 7.5 a selection of the different solver arguments for the ODE solver CVode is shown. Note that there are minor differences in the tolerances compared to the options described in Table 7.2. More information regarding the solver options can be found here, http://www.jmodelica.org/assimulo.
Table 7.4. General options for AssimuloFMIAlg.
| Option | Default | Description |
|---|---|---|
| solver | 'CVode' | Specifies the simulation method that is to be used. |
| ncp | 0 | Number of communication points. If ncp is zero, the solver will return the internal steps taken. |
| initialize | True | If set to True, the initializing algorithm defined in the FMU model is invoked, otherwise it is assumed the user have manually invoked model.initialize() |
| write_scaled_result | False | Set this parameter to True to write the result to file without taking scaling into account. If the value of scaled is False, then the variable scaling factors of the model are used to reproduced the unscaled variable values. |
| result_file_name | Empty string (default generated file name will be used) | Specifies the name of the file where the simulation result is written. Setting this option to an empty string results in a default file name that is based on the name of the model class. |
Lets look at an example, consider that you want to simulate a FMU model using the solver CVode together with changing the
discretization method (discr) from BDF to Adams:
... opts = model.simulate_options() #Retrieve the default options #opts['solver'] = 'CVode' #Not necessary, default solver is CVode opts['CVode_options']['discr'] = 'Adams' #Change from using BDF to Adams opts['initialize'] = False #Dont initialize the model model.simulate(options=opts) #Pass in the options to simulate and simulate
It should also be noted from the above example the options regarding a specific solver, say the tolerances for CVode, should be stored in a double dictionary where the first is named after the solver concatenated with _options:
opts['CVode_options']['atol'] = 1.0e-6 #Options specific for CVode
For the general options, as changing the solver, they are accessed as a single dictionary:
opts['solver'] = 'CVode' #Changing the solver
opts['ncp'] = 1000 #Changing the number of communication points.
Table 7.5. Selection of solver arguments for CVode
| Option | Default | Description |
|---|---|---|
| discr | 'BDF' | The discretization method. Can be either 'BDF' or 'Adams' |
| iter | 'Newton' | The iteration method. Can be either 'Newton' or 'FixedPoint'. |
| maxord | 5 | The maximum order used. Maximum for 'BDF' is 5 while for the 'Adams' method the maximum is 12 |
| maxh | Inf | Maximum step-size. Positive float. |
| atol | rtol*0.01*(nominal values of the continuous states) | Absolute Tolerance. Can be an array of floats where each value corresponds to the absolute tolerance for the corresponding variable. Can also be a single positive float. |
| rtol | 1.0e-4 | The relative tolerance. The relative tolerance are retrieved from the 'default experiment' section in the XML-file and if not found are set to 1.0e-4 |
The return argument from the simulate method is an object derived from a common result object ResultBase in algorithm_drivers.py with a few extra convenience methods for retrieving the result of a variable. The result object can
be accessed in the same way as a dictionary type in Python with the name of the variable as key.
res = model.simulate() y = res['y'] #Return the result for the variable/parameter/constant y dery = res['der(y)'] #Return the result for the variable/parameter/constant der(y)
This can be done for all the variables, parameters and constants defined in the model and is the preferred way of retrieving the result. There are however some more options available in the result object, see Table 7.6.
Table 7.6. Result Object
| Option | Type | Description |
|---|---|---|
| options | Property | Gets the options object that was used during the simulation. |
| solver | Property | Gets the solver that was used during the integration. |
| result_file | Property | Gets the name of the generated result file. |
| is_variable(name) | Method | Returns True if the given name is a time-varying variable. |
| data_matrix | Property | Gets the raw data matrix. |
| is_negated(name) | Method | Returns True if the given name is negated in the result matrix. |
| get_column(name) | Method | Returns the column number in the data matrix which corresponds to the given variable. |