3. Simulation of Models

Simulation of models in JModelica.org is preformed via the simulate method of a model object. The model objects in JModelica.org are:

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.

3.1. Arguments

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.

3.1.1. Input

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)

3.1.2. Options for JMUModel

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.

3.1.3. Options for FMUModel

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

3.2. Return argument

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.