# Porting Modelica libraries to OpenModelica¶

One of the goals of OpenModelica is to provide a full, no-compromise implementation of the latest version of the Modelica Language Specification, released by the non-profit Modelica Association. This means that a main requirement for a Modelica library to work in OpenModelica is to be fully compliant to the Language Specification.

Libraries and models developed with other Modelica tools may contain some code
which is not valid according to the current language specification, but still accepted
by that tool, e.g. to support legacy code of their customers. In order to use
those libraries and models in OpenModelica, one needs to make sure that such code
is replaced by a valid one. Note that getting rid of invalid Modelica code
does not make the library *only* usable in OpenModelica; to the contrary, doing that
is the best guarantee that the library will be usable *both* with the original
tool used for development *and* with OpenModelica, as well as with any other present
or future Modelica tool that follows the standard strictly.

The first recommendation is to use any flag or option of the tool that was originally used to develop the library, that allows to check for strict compliance to the language specification. For example, Dymola features a translation option 'Pedantic mode for checking Modelica semantics' that issues an error if non-standard constructs are used.

For your convenience, here you can find a list of commonly reported issues.

## Mapping of the library on the file system¶

Packages can be mapped onto individual *.mo* files or onto hierarchical
directory structures on the file system, according to the rules set forth in
Section 13.4.
of the language specification.
The file encoding must be UTF-8; the use of a BOM at the beginning of the file
is deprecated and preferably avoided. If there are non-ASCII characters
in the comments or in the documentation of your library, make sure that the
file is encoded as UTF-8.

If a directory-based representation is chosen, each *.mo* file must start with
a *within* clause, and each directory should contain a *package.order* file that lists
all the classes and constants defined as separate files in that directory.

When using revision control systems such as GIT or SVN, if the library is stored in a directory structure, it is recommended to include the top-level directory (that must have the same name as the top-level package) in the repository itself, to avoid problems in case the repository is cloned locally on a directory that doesn't have the right name.

The top-level directory name, or the single *.mo* file containing the entire
package, should be named exactly as the package (e.g. *Modelica*),
possibly followed by a space and by the version number (e.g. *Modelica 3.2.3*).

## Modifiers for arrays¶

According to the rules set forth in Section 7.2.5
of the language specification, when instantiating arrays of components, modifier
values should be arrays of the same size of the component array, unless the *each*
prefix is introduced, in which case the scalar modifier values is applied to
all the elements of the array. Thus, if *MyComponent* has a Real parameter *p*,
these are all valid declarations

```
parameter Real q = {0, 1, 2};
MyComponent ma[3](p = {10, 20, 30});
MyComponent mb[3](p = q);
MyComponent mb[3](each p = 10);
```

while these are not

```
parameter Real r = 4;
MyComponent ma[3](p = r);
MyComponent mb[3](p = 20);
```

In most cases, the problem is solved by simply adding the *each* keyword where
appropriate.

## Access to conditional components¶

According to Section 4.4.5 of the language specification, "A component declared with a condition-attribute can only be modified and/or used in connections". When dealing, e.g., with conditional input connectors, one can use the following patterns:

```
model M
parameter Boolean activateIn1 = true;
parameter Boolean activateIn2 = true;
Modelica.Blocks.Interfaces.RealInput u1_in if activateIn1;
Modelica.Blocks.Interfaces.RealInput u2_in = u2 if activateIn2;
Real u2 "internal variable corresponding to u2_in";
Real y;
protected
Modelica.Blocks.Interfaces.RealInput u1 "internal connector corresponding to u1_in";
equation
y = u1 + u2;
connect(u1_in, u1) "automatically disabled if u1_in is deactivated";
if not activateIn1 then
u1 = 0 "default value for protected connector value when u1_in is disabled";
end if;
if not activateIn2 then
u2 = 0 "default value for u2 when u2_in is disabled";
end if;
end M;
```

where conditional components are only used in connect equations. The following patterns instead are not legal:

```
model M
parameter Boolean activateIn1 = true;
parameter Boolean activateIn2 = true;
Modelica.Blocks.Interfaces.RealInput u1_in if activateIn1;
Modelica.Blocks.Interfaces.RealInput u2_in if activateIn2;
Real u1 "internal variable corresponding to u1_in";
Real u2 "internal variable corresponding to u2_in";
Real y;
equation
if activateIn1 then
u1 = u1_in "invalid: uses conditional u1_in outside connect equations";
end if;
if activateIn2 then
u2 = u2_in "invalid: uses conditional u1_in outside connect equations";
end if;
y = u1 + u2;
end M;
```

because those components are also used in other equations. The fact that those equations are conditional and are not activated when the corresponding conditional components are also not activated is irrelevant, according to the language specification.

## Access to classes defined in partial packages¶

Consider the following example package

```
package TestPartialPackage
partial package PartialPackage
function f
input Real x;
output Real y;
algorithm
y := 2*x;
end f;
end PartialPackage;
package RegularPackage
extends PartialPackage;
model A
Real x = time;
end A;
end RegularPackage;
model M1
package P = PartialPackage;
Real x = P.f(time);
end M1;
model M2
extends M1(redeclare package P = RegularPackage);
end M2;
model M3
encapsulated package LocalPackage
import TestPartialPackage.PartialPackage;
extends PartialPackage;
end LocalPackage;
package P = LocalPackage;
Real x = P.f(time);
end M3;
end TestPartialPackage;
```

Model *M1* references a class (a function, in this case) from a partial
package. This is perfectly fine if one wants to write a generic model, which
is then specialized by redeclaring the package to a non-partial one, as in
*M2*. However, *M1* cannot be compiled for simulation, since, according to
Section 5.3.2
of the language specification, the classes that are looked inside during
lookup shall not be partial in a simulation model.

This problem can be fixed by accessing that class (the function *f*, in this case)
from a non-final package that extends the partial one, either by redeclaring
the partial package to a non-partial one, as in *M2*, or by locally defining
a non-partial package that extends from the partial one, as in *M3*. The latter
option is of course viable only if the class being accessed is in itself not a partial
or somehow incomplete one.

This issue is often encountered in models using *Modelica.Media*, that sometimes
use some class definitions (e.g. unit types) from partial packages such as
*Modelica.Media.Interfaces.PartialMedium*. The fix in most cases is just to
use the same definition from the actual replaceable *Medium* package defined
in the model, which will eventually be redeclared to a non-partial one
in the simulation model.

## Equality operator in algorithms¶

The following code is illegal, because it uses the equality '=' operator, which is reserved for equations, instead of the assignment operator ':=' inside an algorithm:

```
function f
input Real x;
input Real y = 0;
output Real z;
algorithm
z = x + y;
end f;
```

so, the OpenModelica parser does not accept it. The correct code is:

```
function f
input Real x;
input Real y = 0;
output Real z;
algorithm
z := x + y;
end f;
```

Some tools automatically and silently apply the correction to the code, please save it in its correct form to make it usable with OpenModelica.

Also note that binding *equations* with '=' sign are instead required for
default values of function inputs.

## Public non-input non-output variables in functions¶

According to Section 12.2 of the language specification, only input and output formal parameters are allowed in the function's public variable section. Hence, the following function declaration is not valid:

```
function f
input Real x;
output Real y;
Real z;
algorithm
z := 2;
y := x+z;
end f;
```

and should be fixed by putting the variable *z* in the protected section:

```
function f
input Real x;
output Real y;
protected
Real z;
algorithm
z := 2;
y := x+z;
end f;
```

## Subscripting of expressions¶

Some libraries use expression subscripting, e.g.

```
model M
Real x[3];
Real y[3];
Real z;
equation
z = (x.*y)[2];
...
end M;
```

This construct is already accepted by some Modelica tools, but is not yet included in the current Modelica Specification 3.6, so it is not supported in OpenModelica up to version 1.22.0. It has now been included in the draft for the 3.7 language specification, so it will be implemented in the future also by OpenModelica.

## Incomplete specification of initial conditions¶

The simulation of Modelica models of dynamical systems requires the tool to determine a consistent initial solution for the simulation to start. To do so, the system equations are augmented by adding one initial condition for each continuous state variable (after index reduction) and one initial condition for each discrete state variable. Then, the augmented system is solved upon initialization.

These initial conditions can be formulated by adding
a *start = <expression>* and a *fixed = true* attribute to those variables, e.g.

```
parameter Real x_start = 10;
parameter Real v_start = 2.5;
Real x(start = x_start, fixed = true);
discrete Real v(start = v_start, fixed = true);
Integer i(start = 2, fixed = true);
```

or by adding initial equations, e.g.:

```
parameter Real x_start = 10;
parameter Real v_start = 2.5;
Real x;
discrete Real v;
Integer i;
Real y(start = 3.5);
initial equation
x = x_start;
v = v_start;
i = 2;
der(y) = 0;
```

Note that in the latter case, the start attribute on *y* is not used directly
to set the initial value of that variable, but only potentially used as initial
guess for the solution of the initialization problem, that may require using
an iterative nonlinear solver. Also note that sets of initial equations are
often added to the models taken from reusable component libraries
by selecting certain component parameters, such as *initOpt* or similar.

If the number of initial conditions matches the number of continuous and discrete states, then the initialization problem is well-defined. Although this is per se not a guarantee that all tools will be able to solve it and find the same solution, this is for sure a prerequisite for across-tool portability.

Conversely, if the number of initial conditions is less than the number of states, the tool has to add some initial equations, using some heuristics to change the fixed attribute of some variables from false to true. Consider for example the following model:

```
model M
Real x;
Real y(start = 1);
Real z(start = 2);
equation
der(x) = y + z;
y = 2*x;
z = 10*x + 1;
end M;
```

This model has one state variable *x*, no variables with *fixed = true*
attributes and no initial equation, so there is one missing initial condition.
One tool could choose to add the *fixed = true* attribute to the state variable
*x*, fixing it to the default value of zero of its *start* attribute. Or, it
could decide to give more priority to variables that have an explicitly modified
*start* attribute, hence fix the initial value of *y* to 1, or the initial value
of *z* to 2. Three completely different simulations would ensue.

The Modelica Language Specification, Section 8.6 does not prescribe or recommend any specific choice criterion in this case. Hence, different tools, or even different versions of the same tool, could add different initial conditions, leading to completely different simulations. In order to avoid any ambiguity and achieve good portability, it is thus recommended to make sure that the initial conditions of all simulation model are well-specified.

A model with not enough initial conditions causes the OMC to issue the
following translation warning: "The initial conditions are not fully specified".
By activating the Tools | Options | Simulation | Show additional information from
the initialization process option, or the *-d=initialization* compiler flag,
one can get an explicit list of the additional equations that OpenModelica
automatically adds to get a fully specified initialization problem, which may be
helpful to figure out which initial conditions are missing. In this case, we
recommend to amend the source code of the model by adding suitable extra initial
conditions, until that warning message no longer appears.

## Modelica_LinearSystems2 Library¶

The Modelica_LinearSystem2 library was originally developed in Dymola
with a plan of eventually making it part of the Modelica Standard Library
(thus the underscore in the library name). The library is based on several
functions, e.g. *readStringMatrix()*, *simulateModel()*, *linearizeModel()*
that are built-in Dymola functions but are not part of the Modelica Standard
Library.

In principle, these functions could be standardized and become part of the ModelicaServices library, which collects standardized interfaces to tool-specific functionality; then, OpenModelica could easily implement them based on its internal functionality. However, until this effort is undertaken, the Modelica_LinearSystem2 library cannot be considered as a full-fledged Modelica library, but only a Dymola-specific one.

If you are interested in using this library in OpenModelica and are willing to contribute to get it supported, please contact the development team, e.g. by opening an ticket on the issue tracker.