OpenModelica

Solvers

The different integration methods for the C runtime are listed here. The default solver used is DASSL. The C++ runtime has support for the IDA solver and other sundials packages.

DASSL

This is a BDF method that selects its order (1-5) and step size at each step. It uses Newton’s method to solve the resulting system of equations. It provides Newton’s method with an initial guess by evaluating a polynomial that interpolates the last few time steps. These points are then used to calculate initial guesses for the derivatives. It has additional features like root finding functionality, and an initial condition solver for when not all initial values are given explicitly.

Runge-Kutta

This is the classical 4-th order Range-Kutta method based on a fixed step.

Euler

Standard Euler method with fixed step.

Compiler

The OpenModelica Compiler (OMC) is used to flatten Modelica models, transform them and output them into a format suitable for simulation. The compiler source code is mainly written in MetaModelica and is contained in the OMCompiler/Compiler directory.

Model Flattening and Debugging

Return flat Modelica for last class in file file.mo using MSL and SolarTherm libraries:

omc file.mo Modelica SolarTherm

Create graph dot model for DAE of class (silencing flat model output):

omc -q -d=daedumpgraphv file.mo

Use omc --help=debug to get more debug options.

Simulation

The OMC SimCode module outputs the model into the target language. By default this is C source code, but other formats can be selected with the --simCodeTarget flag (see also OMCompiler/Compiler/SimCode/SimCodeMain.mo).

The simulation runtime source code is contained under OMCompiler/SimulationRuntime. This contains the C and C++ runtimes and several others.

C Simulation Runtime

The C code target is selected by default and the resulting code is generated by:

omc -q -s file.mo Modelica SolarTherm

The generated source is then compiled and linked to the C simulation runtime library into a final executable. When the last class in the input file is Class, the executable is built with:

make -f Class.makefile

It is then simulated with:

./Class

Experiment annotations in Class don’t seem to be used. The Class_init.xml file contains model information and simulation parameters. The C simulation runtime reads this file, so things like time intervals can be changed without recompiling the simulation executable.

The simulation executable can accept a number of command line (call with -help and -help=<flag> for more information). For example to output events:

./Class -lv=LOG_EVENTS

By default the simulation will output the results into a file named Class_res.mat, which is a MAT-file version 4. Another optional output is a CSV file, but this dramatically slows down the simulation.

Listed below are the source files generated in this process and an initial attempt to explain their purpose.

.makefile
Makefile for building the simulation executable. It could be manually edited if trouble with linking libraries in compilation.
_init.xml
Is an extension of the FMI standard. It has 3 main parts. The first is a high level description of the mode including the model name and number of variables. The second is the experiment parameters and the third is a list of the model variables along with their types, reference values and some parameters.
_info.json
Appears to contain similar information as that in the variables section of Class_init.xml.
.c
This contains the main function for the simulation, which puts together the simulation data (the DATA struct defined in SimulationRuntime/c/simulation_data.h) from the other source files and then passes it off to the _main_SimulationRuntime function (defined in SimulationRuntime/c/simuation/simulation_runtime.{h,cpp}). This data contains information about the model (e.g., number of states) and callbacks for evaluating different parts of the model. The file defines functions for evaluating equations and algorithms in the model. It then builds the DAE and ODE systems from these functions which are used as callbacks.
_functions.{h,c}
These files appear to contain struct definitions for any records that are defined and wrapper functions for any external C code used. Included by most other files here.
_model.h
A whole heap of macros that are used for conveniently accessing things like the current value of a variable in the simulation. The macros are used in the callback functions and operate on the simulation data passed to the callback function. Included by most other files here.
_literals.h
I think just some simple string literals defined. Included by most other files here.
_includes.h
Empty in the examples examined.
_records.c
Contains some additional code for records, for example names for the record and record fields.
_01exo.c
Constructors and deconstructors for external objects.
_02nls.c
Contains nonlinear systems (haven’t observed it populated yet).
_03lsy.c
Linear systems (haven’t observed it populated yet).
_04set.c
Initial state set (haven’t observed it populated yet).
_05evt.c
Raw time, zero crossing, relation and discrete events. For zero crossings it contains a callback function that calls relevant functions defined in .c in order to update variables, and another callback function for checking transitions.
_06inz.c
Contains equation and algorithm functions for initialising variables. These equations are named with indices smaller than the functions in .c. Also contains function to initialise mixed systems (haven’t observed it populated yet).
_07dly.c
Delay. Don’t know what this does and haven’t seen it populated.
_08bnd.c
Updates bound parameters and variable attributes start, nominal, min and max. Not sure exactly when this would be used. It contains equation and algorithm functions for this purpose with indices greater than those in .c.
_09alg.c
Collects together the functions from .c for the algebraic system.
_10asr.c
Contains functions checking and throwing asserts. These functions have indices greater than those in _08bnd.c.
_11mix.{h,c}
Contains mixed systems (haven’t observed it populated yet).
_12jac.{h,c}
Contains functions for calculating and initialising the Jacobian. It seems to always contain sparsity information. The compiler flag --generateSymbolicJacobian needs to be set to produce equations for the symbolic calculation of the jacobian. Additionally a compiler call with -g=Optimica flag on an optimization class will produce stuff.
_13opt.{h,c}
Contains functions needed in optimisation like the objective and Lagrangian and for grabbing bounds from variables. Need to call compiler with -g=Optimica flag and have an optimization class to get something interesting here.
_14lnz.c
Linearisation. Not sure what for and haven’t seen it populated.

The C simulation runtime is located under OMCompiler/SimulationRuntime/c. Interesting files include:

simulation_data.h
Contains the DATA struct and others.
simuation/simulation_runtime.{h,cpp}
Contains _main_SimulationRuntime function which gets called to run the simulation with the model data from the generated model code.
simulation/solver/solver_main.c
The solver_main_step function gets called to step the simulation and then passes the stepping off to the appropriate backend solver.
simulation/solver/perform_simulation.c
Contains the main simulation while loop in the function prefixedName_performSimulation.
simulation/solver/dassl.c
Contains the DASSL related functions including the dassl_step function. According to a comment in the file the integrated zero crossing method is disabled and zero crossings are instead handled outside DASSL (not same thing as internal root finding, which by default is turned on). It has functions for the symbolic or numeric calculations of Jacobians. The method can be selected with the -dasslJacobian flag, where coloredNumerical is the default. See the _12jac.{h,c} files for where the symbolic jacobian comes from (has to be enabled at during model compilation).

C++ Simulation Runtime

An example of C++ code generation:

omc -q -s --simCodeTarget=Cpp file.mo Modelica SolarTherm

The resulting files are slow to compile and sometimes fail for more complicated models. The simulation parameters are passed to the executable on the command line instead of being read from an XML file. See the Class.sh script for an example of the command line switches. It is able to use IDA instead of DASSL, which worked on at least a very simple example.

Language

Here are some notes on different aspects of the Modelica language. Some of the quirks presented here may just be specific to OpenModelica, whereas others are part of the language specification.

Expandable Connectors

Expandable connectors can have some defined components:

expandable connector Bus
    Real a;
end Bus;

Those that are undefined must be connected to a defined component, and the connect operator must be used:

model Model
    input Real x;
    input Real y;
    Bus bus1;
    Bus bus2;
equation
    connect(x, bus1.a);
    connect(y, bus1.b);

    connect(bus2.b, bus1.b); // Fail: two undefined components connected
    bus1.b = y; // Fail: connect must be used to construct b
end Model;

Expandable connectors cannot have flow components, but may contain non-expandable flow components.

The direction (input/output) of an expandable connector component will be determined using the normal rules with respect to the direction of the component connected to.

Discrete Equations

OpenModelica doesn’t yet appear to fully support having systems of equations. This error might be triggered by other issues. If in doubt put all the when clauses in an algorithm section.