How to compile and simulate a Modelica model

This notebook shows how to

  1. load a Modelica model
  2. compile the model
  3. run a single simulation
  4. change the model parameters and simulate multiple times

The source code of the model is

model HelloWorld  "The simplest differential equation ever"
  Real x
   "The unknown variable";
  constant Real a = -2.0
   "Constant that characterizes the model";
  parameter Real x_start = 5.0
   "Initial value of the variable x";
initial equation
   // Define initial conditions here...
   x = x_start;
equation
   // Write the equations here...
   der(x) = a*x;
end HelloWorld;

and it's locatios is the repository ModelicaInAction is ModelicaInAction/modelica/HelloWorld.mo.

When starting the docker container using the command make start

# Excerpt from ModelicaInAction/Makefile

start: ## Starts the container in detached mode and exposes an ipython notebook server listening on port 8888.
        docker run -d -v $(shell pwd)/modelica:/home/docker/modelica \
        -v $(shell pwd)/ipynotebooks:/home/docker/ipynotebooks \
        -p 127.0.0.1:8888:8888 jmodelica:1.0 \
        sh -c 'ipython notebook --no-browser --matplotlib=inline --ip=0.0.0.0 --port=8888 --notebook-dir=/home/docker/ipynotebooks'

the option -v $(shell pwd)/modelica:/home/docker/modelica attaches the folder ModelicaInAction/modelica/ to the folder /home/docker/modelica inside the container.

In this way we can modify/create Modelica files on the host, compile and simulate them on the guest (the docker container).


In [1]:
from pymodelica import compile_fmu
from pyfmi import load_fmu
from pylab import rcParams
rcParams['figure.figsize'] = 12, 6
from matplotlib import pyplot as plt
import numpy as np

Load and compile the model


In [2]:
# Specify Modelica model and model file (.mo or .mop)
model_name = 'HelloWorld'
mo_file = '/home/docker/modelica/HelloWorld.mo'

# Compile the model and save the return argument, which is the file name of the FMU
my_fmu = compile_fmu(model_name, mo_file)

JModelica.org starts by opening the Modelica model named HelloWorld located in file /home/docker/modelica/HelloWorld.mo. Once the .mo file is loaded JModelica.org parses and compiles it. The result of the compilation is an FMU file.

An FMU (Functional Mock-up Unit) is a file compliant with the Functional Mock-up Interface (FMI). FMI is a tool independent standard to support both model exchange and co-simulation of dynamic models using a combination of xml-files and compiled C-code.

Long story short, JModelica.org generates C-code and an xml representation of the model. Both the C-code and the xml-files are packaged inside the FMU.

Simulate the model

We can now use JModelica to load the files contained in the FMU and simulate the model.


In [3]:
# Load the model and simulate
hello_world = load_fmu(my_fmu)
res = hello_world.simulate(final_time=5.0)


Final Run Statistics: HelloWorld 

 Number of steps                                 : 60
 Number of function evaluations                  : 78
 Number of Jacobian evaluations                  : 2
 Number of function eval. due to Jacobian eval.  : 2
 Number of error test failures                   : 2
 Number of nonlinear iterations                  : 74
 Number of nonlinear convergence failures        : 0

Solver options:

 Solver                   : CVode
 Linear multistep method  : BDF
 Nonlinear solver         : Newton
 Linear solver type       : DENSE
 Maximal order            : 5
 Tolerances (absolute)    : 1e-06
 Tolerances (relative)    : 0.0001

Simulation interval    : 0.0 - 5.0 seconds.
Elapsed simulation time: 0.008998 seconds.

In [4]:
plt.plot(res["time"], res['x'], label="$x(t)$")
plt.xlabel("Time [s]")
plt.ylabel("State variable x")
plt.legend()


Out[4]:
<matplotlib.legend.Legend at 0x7f5633fff0d0>

Change a parameter and simulate multiple times

The model has a parameter called x_init that is the initial value of the state variable x at the beginning of the simulation time. We'll now run multiple simulations that start from different initial conditions.

The model has already been simulated, therefore in order to run a new simulation we need to reset the model. To reset the model we use the reset() method

hello_world.reset()

To change the value of a parameter we use the set() method

hello_world.set(<PARAMETER_NAME>, <NEW_VALUE>)

In [5]:
x_init = np.linspace(5.0, 10.0, 10)
results = []
for xi in x_init:
    hello_world.reset()
    hello_world.set("x_start", xi)
    results.append(hello_world.simulate(final_time=5.0))


Final Run Statistics: HelloWorld 

 Number of steps                                 : 60
 Number of function evaluations                  : 78
 Number of Jacobian evaluations                  : 2
 Number of function eval. due to Jacobian eval.  : 2
 Number of error test failures                   : 2
 Number of nonlinear iterations                  : 74
 Number of nonlinear convergence failures        : 0

Solver options:

 Solver                   : CVode
 Linear multistep method  : BDF
 Nonlinear solver         : Newton
 Linear solver type       : DENSE
 Maximal order            : 5
 Tolerances (absolute)    : 1e-06
 Tolerances (relative)    : 0.0001

Simulation interval    : 0.0 - 5.0 seconds.
Elapsed simulation time: 0.009559 seconds.
Final Run Statistics: HelloWorld 

 Number of steps                                 : 60
 Number of function evaluations                  : 77
 Number of Jacobian evaluations                  : 2
 Number of function eval. due to Jacobian eval.  : 2
 Number of error test failures                   : 2
 Number of nonlinear iterations                  : 73
 Number of nonlinear convergence failures        : 0

Solver options:

 Solver                   : CVode
 Linear multistep method  : BDF
 Nonlinear solver         : Newton
 Linear solver type       : DENSE
 Maximal order            : 5
 Tolerances (absolute)    : 1e-06
 Tolerances (relative)    : 0.0001

Simulation interval    : 0.0 - 5.0 seconds.
Elapsed simulation time: 0.008975 seconds.
Final Run Statistics: HelloWorld 

 Number of steps                                 : 60
 Number of function evaluations                  : 77
 Number of Jacobian evaluations                  : 2
 Number of function eval. due to Jacobian eval.  : 2
 Number of error test failures                   : 2
 Number of nonlinear iterations                  : 73
 Number of nonlinear convergence failures        : 0

Solver options:

 Solver                   : CVode
 Linear multistep method  : BDF
 Nonlinear solver         : Newton
 Linear solver type       : DENSE
 Maximal order            : 5
 Tolerances (absolute)    : 1e-06
 Tolerances (relative)    : 0.0001

Simulation interval    : 0.0 - 5.0 seconds.
Elapsed simulation time: 0.008889 seconds.
Final Run Statistics: HelloWorld 

 Number of steps                                 : 60
 Number of function evaluations                  : 77
 Number of Jacobian evaluations                  : 2
 Number of function eval. due to Jacobian eval.  : 2
 Number of error test failures                   : 2
 Number of nonlinear iterations                  : 73
 Number of nonlinear convergence failures        : 0

Solver options:

 Solver                   : CVode
 Linear multistep method  : BDF
 Nonlinear solver         : Newton
 Linear solver type       : DENSE
 Maximal order            : 5
 Tolerances (absolute)    : 1e-06
 Tolerances (relative)    : 0.0001

Simulation interval    : 0.0 - 5.0 seconds.
Elapsed simulation time: 0.009097 seconds.
Final Run Statistics: HelloWorld 

 Number of steps                                 : 60
 Number of function evaluations                  : 78
 Number of Jacobian evaluations                  : 2
 Number of function eval. due to Jacobian eval.  : 2
 Number of error test failures                   : 2
 Number of nonlinear iterations                  : 74
 Number of nonlinear convergence failures        : 0

Solver options:

 Solver                   : CVode
 Linear multistep method  : BDF
 Nonlinear solver         : Newton
 Linear solver type       : DENSE
 Maximal order            : 5
 Tolerances (absolute)    : 1e-06
 Tolerances (relative)    : 0.0001

Simulation interval    : 0.0 - 5.0 seconds.
Elapsed simulation time: 0.009719 seconds.
Final Run Statistics: HelloWorld 

 Number of steps                                 : 60
 Number of function evaluations                  : 78
 Number of Jacobian evaluations                  : 2
 Number of function eval. due to Jacobian eval.  : 2
 Number of error test failures                   : 2
 Number of nonlinear iterations                  : 74
 Number of nonlinear convergence failures        : 0

Solver options:

 Solver                   : CVode
 Linear multistep method  : BDF
 Nonlinear solver         : Newton
 Linear solver type       : DENSE
 Maximal order            : 5
 Tolerances (absolute)    : 1e-06
 Tolerances (relative)    : 0.0001

Simulation interval    : 0.0 - 5.0 seconds.
Elapsed simulation time: 0.009016 seconds.
Final Run Statistics: HelloWorld 

 Number of steps                                 : 60
 Number of function evaluations                  : 78
 Number of Jacobian evaluations                  : 2
 Number of function eval. due to Jacobian eval.  : 2
 Number of error test failures                   : 2
 Number of nonlinear iterations                  : 74
 Number of nonlinear convergence failures        : 0

Solver options:

 Solver                   : CVode
 Linear multistep method  : BDF
 Nonlinear solver         : Newton
 Linear solver type       : DENSE
 Maximal order            : 5
 Tolerances (absolute)    : 1e-06
 Tolerances (relative)    : 0.0001

Simulation interval    : 0.0 - 5.0 seconds.
Elapsed simulation time: 0.010334 seconds.
Final Run Statistics: HelloWorld 

 Number of steps                                 : 61
 Number of function evaluations                  : 79
 Number of Jacobian evaluations                  : 2
 Number of function eval. due to Jacobian eval.  : 2
 Number of error test failures                   : 2
 Number of nonlinear iterations                  : 75
 Number of nonlinear convergence failures        : 0

Solver options:

 Solver                   : CVode
 Linear multistep method  : BDF
 Nonlinear solver         : Newton
 Linear solver type       : DENSE
 Maximal order            : 5
 Tolerances (absolute)    : 1e-06
 Tolerances (relative)    : 0.0001

Simulation interval    : 0.0 - 5.0 seconds.
Elapsed simulation time: 0.008977 seconds.
Final Run Statistics: HelloWorld 

 Number of steps                                 : 61
 Number of function evaluations                  : 79
 Number of Jacobian evaluations                  : 2
 Number of function eval. due to Jacobian eval.  : 2
 Number of error test failures                   : 2
 Number of nonlinear iterations                  : 75
 Number of nonlinear convergence failures        : 0

Solver options:

 Solver                   : CVode
 Linear multistep method  : BDF
 Nonlinear solver         : Newton
 Linear solver type       : DENSE
 Maximal order            : 5
 Tolerances (absolute)    : 1e-06
 Tolerances (relative)    : 0.0001

Simulation interval    : 0.0 - 5.0 seconds.
Elapsed simulation time: 0.008874 seconds.
Final Run Statistics: HelloWorld 

 Number of steps                                 : 61
 Number of function evaluations                  : 79
 Number of Jacobian evaluations                  : 2
 Number of function eval. due to Jacobian eval.  : 2
 Number of error test failures                   : 2
 Number of nonlinear iterations                  : 75
 Number of nonlinear convergence failures        : 0

Solver options:

 Solver                   : CVode
 Linear multistep method  : BDF
 Nonlinear solver         : Newton
 Linear solver type       : DENSE
 Maximal order            : 5
 Tolerances (absolute)    : 1e-06
 Tolerances (relative)    : 0.0001

Simulation interval    : 0.0 - 5.0 seconds.
Elapsed simulation time: 0.009068 seconds.

In [6]:
for i, res in enumerate(results):
    plt.plot(res["time"], res['x'], 'b', label="$x(t)$" if i==0 else None)
plt.xlabel("Time [s]")
plt.ylabel("State variable x")
plt.legend()


Out[6]:
<matplotlib.legend.Legend at 0x7f5631060710>

Question: can we change the value of a?

No because it's declared as a constant and constants cannot be modified. If we try JModelica.org will give us an error.