Modelica Tutorial
Modelica Tutorial
by the
Modelica Association
Abstract:
This document is a tutorial for the Modelica language, version 1.4, which is developed by the Modelica
Association, a non-profit organization with seat in Linkping, Sweden. Modelica is a freely available,
object-oriented language for modeling of large, complex, and heterogeneous physical systems. It is suited
for multi-domain modeling, for example, mechatronic models in robotics, automotive and aerospace
applications involving mechanical, electrical, hydraulic and control subsystems, process oriented
applications and generation and distribution of electric power. Models in Modelica are mathematically
described by differential, algebraic and discrete equations. No particular variable needs to be solved for
manually. A Modelica tool will have enough information to decide that automatically. Modelica is
designed such that available, specialized algorithms can be utilized to enable efficient handling of large
models having more than hundred thousand equations. Modelica is suited and used for hardware-in-theloop simulations and for embedded control systems. More information is available at
http://www.Modelica.org/
Contents
1.
2.
2.1
2.2
2.3
2.4
2.5
2.6
2.7
2.8
2.9
2.10
2.11
2.12
3.
EXAMPLES............................................................................................................46
4.
CONCLUSIONS .....................................................................................................47
5.
REFERENCES .......................................................................................................47
6.
1. Modelica at a Glance
To give an introduction to Modelica we will consider modeling of a simple electrical circuit as
shown below.
The system can be broken up into a set of connected electrical standard components. We have a
voltage source, two resistors, an inductor, a capacitor and a ground point. Models of these
components are typically available in model libraries and by using a graphical model editor we
can define a model by drawing an object diagram very similar to the circuit diagram shown
above by positioning icons that represent the models of the components and drawing
connections.
A Modelica description of the complete circuit looks like
model circuit
Resistor R1(R=10);
Capacitor C(C=0.01);
Resistor R2(R=100);
Inductor L(L=0.1);
VsourceAC AC;
Ground
G;
equation
connect (AC.p, R1.p);
connect (R1.n, C.p);
connect (C.n, AC.n);
connect (R1.p, R2.p);
connect (R2.n, L.p);
connect (L.n, C.n);
connect (AC.n, G.p);
end circuit;
// Capacitor circuit
// Inductor circuit
// Ground
For clarity, the definition of the graphical layout of the composition diagram (here: electric
circuit diagram) is not shown, although it is usually contained in a Modelica model as
annotations (which are not processed by a Modelica translator and only used by tools). A
composite model of this type specifies the topology of the system to be modeled. It specifies the
components and the connections between the components. The statement
Resistor R1(R=10);
where Real is the name of a predefined variable type. A real variable has a set of attributes such
as unit of measure, initial value, minimum and maximum value. Here, the units of measure are
set to be the SI units.
In Modelica, the basic structuring element is a class. There are seven restricted classes with
specific names, such as model, type (a class which is an extension of built-in classes, such as
Real, or of other defined types), connector (a class which does not have equations and can be
used in connections). For a valid model it is fully equivalent to, e.g., replace the model, and type
keywords by the keyword class, because the restrictions imposed by such a specialized class are
fulfilled by a valid model.
The concept of restricted classes is advantageous because the modeler does not have to learn
several different concepts, but just one: the class concept. All properties of a class, such as
syntax and semantic of definition, instantiation, inheritance, genericity are identical to all kinds
of restricted classes. Furthermore, the construction of Modelica translators is simplified
considerably because only the syntax and semantic of a class has to be implemented along with
some additional checks on restricted classes. The basic types, such as Real or Integer are builtin type classes, i.e., they have all the properties of a class and the attributes of these basic types
are just parameters of the class.
There are two possibilities to define a class: The standard way is shown above for the definition
of the electric circuit (model circuit). A short hand notation is possible, if a new class is identical
to an existing one and only the default values of attributes are changed. The types above, such as
Voltage, are declared in this way.
A connector class is defined as
connector Pin
Voltage
v;
flow Current i;
end Pin;
A connection connect (Pin1, Pin2), with Pin1 and Pin2 of connector class Pin, connects the
two pins such that they form one node. This implies two equations, namely Pin1.v = Pin2.v
and Pin1.i + Pin2.i = 0. The first equation indicates that the voltages on both branches
connected together are the same, and the second corresponds to Kirchhoffs current law saying
4
that has two pins, p and n, a quantity, v, that defines the voltage drop across the component and a
quantity, i, that defines the current into the pin p, through the component and out from the pin n.
The equations define generic relations between quantities of a simple electrical component. In
order to be useful a constitutive equation must be added. The keyword partial indicates that
this model class is incomplete. The key word is optional. It is meant as an indication to a user
that it is not possible to use the class as it is to instantiate components. Between the name of a
class and its body it is allowed to have a string. It is treated as a comment attribute and is meant
to be a documentation that tools may display in special ways.
To define a model for a resistor we exploit OnePort and add a definition of parameter for the
resistance and Ohms law to define the behavior:
model Resistor "Ideal electrical resistor"
extends OnePort;
parameter Real R(unit="Ohm") "Resistance";
equation
R*i = v;
end Resistor;
The keyword parameter specifies that the quantity is constant during a simulation run, but can
change values between runs. A parameter is a quantity which makes it simple for a user to
modify the behavior of a model.
A model for an electrical capacitor can also reuse the TwoPin as follows:
model Capacitor "Ideal electrical capacitor"
extends OnePort;
parameter Real C(unit="F") "Capacitance";
equation
C*der(v) = i;
end Capacitor;
In order to provide not too much information at this stage, the constant PI is explicitly declared,
although it is usually imported from the Modelica standard library (see appendix of the Language
Specification). Finally, we must not forget the ground point.
model Ground "Ground"
Pin p;
equation
p.v = 0;
end Ground;
The purpose of the ground model is twofold. First, it defines a reference value for the voltage
levels. Secondly, the connections will generate one Kirchhoffs current law too many. The
ground model handles this by introducing an extra current quantity p.i, which implicitly by the
equations will be calculated to zero.
This example clearly shows the benefits of physically oriented, non-causal modeling compared
to block oriented, causal modeling.
Modelica Libraries
In order that Modelica is useful for model exchange, it is important that libraries of the most
commonly used components are available, ready to use, and sharable between applications. For
this reason, the Modelica Association develops and maintains a growing Modelica Standard
Library. Furthermore, other people and organizations are developing free and commercial
Modelica libraries. For more information and especially for downloading the free libraries, see
http://www.Modelica.org/library/library.html. Currently, component libraries are available in the
following domains:
below:
2.1
The language constructs will be developed gradually starting with small examples, and then
extended by considering practical issues when modeling large systems.
Handling large models means careful structuring in order to reuse model knowledge. A model is
built-up from
connections
functions
Some means of declaring variable properties is needed, since there are different kinds of
variables, Parameters should be given values and there should be a possibility to give initial
conditions.
Basic declarations of variables can be made as follows:
Real u, y(start=1);
parameter Real T=1;
Real is the name of a predefined class or type. A Real variable has an attribute called start to
give its initial value. A component declaration can be preceded by a specifier like constant or
parameter indicating that the component is constant, i.e., its derivative is zero. The specifier
parameter indicates that the value of the quantity is constant during simulation runs. It can be
8
2.2
Assume we would like to connect two filters in series. Instead of repeating the filter equation, it
is more convenient to make a definition of a filter once and create two instances. This is done by
declaring a class. A class declaration contains a list of component declarations and a list of
equations preceded by the keyword equation. An example of a low pass filter class is shown
below.
class LowPassFilter
parameter Real T=1;
Real u, y(start=1);
equation
T*der(y) + y = u;
end LowPassFilter;
The model class can be used to create two instances of the filter with different time constants and
"connecting" them together as follows
class FiltersInSeries
LowPassFilter F1(T=2), F2(T=3);
equation
F1.u = sin(time);
F2.u = F1.y;
end FiltersInSeries;
In this case we have used a modification to modify the time constant of the filters to T=2 and
T=3 respectively from the default value T=1 given in the low-pass filter class. Dot notation is
used to reference components, like u, within structured components, like F1. For the moment it
can be assumed that all components can be reached by dot-notation. Restrictions of accessibility
will be introduced later. The independent variable is referenced as time. It is available in all
classes without declaration.
If the FiltersInSeries model is used to declare components at a higher hierarchical level, it is still
possible to modify the time constants by using a hierarchical modification:
model ModifiedFiltersInSeries
FiltersInSeries F12(F1(T=6), F2(T=11, k=2));
FiltersInSeries F34(F1.T=6, F2.T=11, F2.k=2);
end ModifiedFiltersInSeries;
// alternative 1
// alternative 2
The class concept is similar as in programming languages. It is used for many purposes in
Modelica, such as model components, connection mechanisms, parameter sets, input-output
9
10
Information hiding does not control interactive environments though. It is possible to inspect and
plot protected variables. Note, that variables of a protected section of a class A can be accessed
by a class which extends class A. In order to keep Modelica simple, additional visibility rules
present in other object-oriented languages, such as private (no access by subtypes), are not used.
2.3
Connections
We have seen how classes can be used to build-up hierarchical models. It will now be shown
how to define physical connections by means of a restricted class called connector.
We will study modeling of a simple electrical circuit. The first issue is then how to represent pins
and connections. Each pin is characterized by two variables, voltage and current. A first attempt
would be to use a connector as follows.
connector Pin
Real v, i;
end Pin;
A descriptive text string enclosed in " " can be associated with a component like R. A comment
which is completely ignored can be entered after //. Everything until the end of the line is then
ignored. Larger comments can be enclosed in /* ... */.
A simple circuit with series connections of two resistors would then be described as:
model FirstCircuit
Resistor R1(R=100), R2(R=200);
equation
R1.n = R2.p;
end FirstCircuit;
11
This describes the series connection correctly because only two components were connected.
Some mechanism is needed to handle Kirchhoffs current law, i.e. that the currents of all wires
connected at a node are summed to zero. Similar laws apply to flows in a piping network and to
forces and torques in mechanical systems. The default rule is that connected variables are set
equal. Such variables are called across variables. Real variables that should be summed to zero
are declared with prefix flow. Such variables are also called through variables. In Modelica we
assume that such variables are positive when the flow (or corresponding vector) is into the
component.
connector Pin
Real v;
flow Real i;
end Pin;
It is useful to introduce units in order to enhance the possibility to generate diagnostics based on
redundant information. Modelica allows deriving new classes with certain modified attributes.
The keyword type is used to define a new class, which is derived from the built-in data types or
defined records. Defining Voltage and Current as modifications of Real with other attributes and
a corresponding Pin can thus be made as follows:
type Voltage = Real(unit="V");
type Current = Real(unit="A");
connector Pin
Voltage v;
flow Current i;
end Pin;
model Resistor
Pin p, n;
// "Positive" and "negative" pins.
parameter Real R(unit="Ohm") "Resistance";
equation
R*p.i = p.v - n.v;
p.i + n.i = 0;
// Positive currents into component.
end Resistor;
connect is a special operator that generates equations taking into account what kind of variables
that are involved. The equations are in this case equivalent to
12
R1.p.v = R2.p.v;
R1.p.v = R3.p.v;
R1.p.i + R2.p.i + R3.p.i = 0;
In certain cases, a model library might be built on the assumption that only one connection can
be made to each connector. There is a built-in function cardinality(c) that returns the number
of connections that has been made to a connector c. It is also possible to get information about
the direction of a connection by using the built-in function direction(c) (provided cardinality(c)
== 1). For a connection, connect(c1, c2), direction(c1) returns -1 and direction(c2) returns 1. The
cardinality and direction operators can be, e.g., used to build a library of bond graph components.
2.4
A very important feature in order to build reusable descriptions is to define and reuse partial
models. Since there are other electrical components with two pins like capacitor and inductor we
can define a generic component with one electrical port1, model OnePort, having two pins as a
base for all of these models.
partial model OnePort
Pin p, n;
Voltage v "Voltage drop";
equation
v = p.v - n.v;
p.i + n.i = 0;
end TwoPin;
Such a partial model can be extended or reused to build a complete model like an inductor.
model Inductor "Ideal electrical inductance"
extends OnePort;
parameter Real L(unit="H") "Inductance";
equation
L*der(i) = v;
end Inductor;
The facility is similar to inheritance in other languages. Multiple inheritance, i.e., several
extends statements, is supported.
The type system of Modelica is greatly influenced by type theory (Abadi and Cardelli 1996), in
particular their notion of subtyping. Abadi and Cardelli separate the notion of subclassing (the
mechanism for inheritance) from the notion of subtyping (the structural relationship that
determines type compatibility). The main benefit is added flexibility in the composition of types,
while still maintaining a rigorous type system.
Inheritance is not used for classification and type checking in Modelica. An extends clause can
In the Modelica Standard Library model OnePort is a component where the current flowing into the first pin is the
same as the current flowing out of the second pin, where as model TwoPin is a component where this assumption
does not necessarily hold, e.g., because the component consists internally of a non-trivial electrical circuit.
13
It is not possible to extend this model from the ideal resistor model Resistor discussed in
Chapter 2, because the equation of the Resistor class needs to be replaced by a new equation.
Still, the TempResistor is a subtype of Resistor because it contains all the public components
of Resistor.
2.5
Class Parameterization
We will now discuss a more powerful parameterization, not only involving values like time
constants and matrices but also classes. (This section might be skipped during the first reading.)
Assume that we have the description (of an incomplete circuit) as above.
model SimpleCircuit
replaceable Resistor R1(R=100), R2(R=200), R3(R=300);
equation
connect(R1.p, R2.p);
connect(R1.p, R3.p);
end SimpleCircuit;
Assume we would like to utilize the parameter values given for R1.R and R2.R and the circuit
topology, but exchange Resistor with the temperature dependent resistor model, TempResistor,
discussed above. This can be accomplished by redeclaring R1 and R2 as follows.
model RefinedSimpleCircuit
Real Temp;
extends SimpleCircuit(
redeclare TempResistor R1(RT=0.1, Temp=Temp),
redeclare TempResistor R2);
end RefinedSimpleCircuit;
Since TempResistor is a subtype of Resistor, it is possible to replace the ideal resistor model.
Values of the additional parameters of TempResistor and definition of the actual temperature can
be added in the redeclaration:
redeclare TempResistor R1(RT=0.1, Temp=Temp);
14
It is also possible to state that a parameter is frozen to a certain value, i.e., is not a parameter
anymore:
Resistor R3(final R=300);
Here, the resistors R1 and R2 can be replaced by any electrical component which is a subtype of
model OnePort, as in the following redeclaration:
model RefinedSimpleCircuit2
extends SimpleCircuit(redeclare Capacitor R1(C=0.001));
end RefinedSimpleCircuit2;
To use another resistor model in the model SimpleCircuit, we needed to know that there were
two replaceable resistors and we needed to know their names. To avoid this problem and prepare
for replacement of a set of models, one can define a replaceable class, ResistorModel. The actual
class that will later be used for R1 and R2 must have Pins p and n and a parameter R in order to
be compatible with how R1 and R2 are used within SimpleCircuit2. The replaceable model
ResistorModel is declared to be a Resistor model. This means that it will be enforced that the
actual class will be a subtype of Resistor, i.e., have compatible connectors and parameters.
Default for ResistorModel, i.e., when no actual redeclaration is made, is in this case Resistor.
Note, that R1 and R2 are in this case of class ResistorModel.
model SimpleCircuit2
replaceable model ResistorModel = Resistor;
protected
ResistorModel R1(R=100), R2(R=200);
Resistor R3(final R=300);
equation
connect(R1.p, R2.p);
connect(R1.p, R3.p);
end SimpleCircuit2;
Another case where redeclarations are needed is extensions of interfaces. Assume we have a
definition for a Tank in a model library:
connector Stream
Real pressure;
flow Real volumeFlowRate;
end Stream;
model Tank
parameter Real Area=1;
replaceable connector TankStream = Stream;
TankStream Inlet, Outlet;
Real level;
equation
// Mass balance.
Area*der(level) = Inlet.volumeFlowRate + Outlet.volumeFlowRate;
Outlet.pressure = Inlet.pressure;
end Tank;
We would like to extend the Tank to model the temperature of the stream. This involves both
extension to interfaces and to model equations.
connector HeatStream
extends Stream;
Real temp;
end HeatStream;
model HeatTank
extends Tank(redeclare connector TankStream = HeatStream);
Real temp;
equation
// Energy balance.
Area*Level*der(temp) = Inlet.volumeFlowRate*Inlet.temp +
Outlet.volumeFlowRate*Outlet.temp;
Outlet.temp = temp; // Perfect mixing assumed.
end HeatTank;
The definition of HeatTank above is equivalent to the following definition (which has been
automatically produced by a Modelica translator).
model HeatTankT
parameter Real Area=1;
connector TankStream
Real pressure;
flow Real volumeFlowRate;
Real temp;
end TankStream;
TankStream Inlet, Outlet;
Real level;
Real temp;
equation
16
Replaceable classes are also very convenient to separate fluid properties from the actual device
where the fluid is flowing, such as a pump.
2.6
An array variable can be declared by appending dimensions after the class name or after a
component name.
Real[3] position, velocity, acceleration;
Real[3,3] transformation;
Real[3,2,10] table;
or
Real position[3], velocity[3], acceleration[3], transformation[3, 3];
Real table[3,2,10];
The following definitions are appropriate for modeling 3D motion of mechanical systems.
type Position = Real(unit="m");
type Position3 = Position[3];
type Force = Real(unit="N");
type Force3 = Force[3];
type Torque = Real(unit="N.m");
type Torque3 = Torque[3];
It is now possible to introduce the variables that are interacting between rigidly connected bodies
in a free-body diagram.
connector MbsCut
Transformation S
Position3
flow Force3
flow Torque3
end MbsCut;
17
Vector and matrix expressions are formed in a similar way as in Mathematica and Matlab. The
operators +, -, * and / can operate on either scalars, vectors or two-dimensional matrices of type
Real and Integer. Division is only possible with a scalar. An array expression is constructed as
{expr1, expr2, ... exprn}. A matrix (two dimensional array) can be formed as
[expr11, expr12, ... expr1n;
expr21, expr22, ... expr2n;
i.e. with commas as separators between columns and semicolon as separator between rows.
Indexing is written as A[i] with the index starting at 1. Submatrices can be formed by utilizing :
notation for index ranges, A[i1:i2, j1:j2]. The then and else branches of if-then-else expressions
may contain matrix expressions provided the dimensions are the same. There are several built-in
matrix functions like zeros, ones, identity, transpose, skew (skew operator for 3 x 3 matrices) and
cross (cross product for 3-dimensional vectors). For details about matrix expressions and
available functions, see the Language Specification.
Matrix sizes and indices in equations must be constant during simulation. If they depend on
parameters, it is a matter of "quality of implementation" of the translator whether such
parameters can be changed at simulation time or only at compilation time.
Block Diagrams
We will now illustrate how the class concept can be used to model block diagrams as a special
case. It is possible to postulate the data flow directions by using the prefixes input and output in
declarations. This also allows checking that only one connection is made to an input, that outputs
are not connected to outputs and that inputs are not connected to inputs on the same hierarchical
level.
A matrix can be declared without specific dimensions by replacing the dimension with a colon:
A[:, :]. The actual dimensions can be retrieved by the standard function size. A general state
space model is an input-output block (restricted class, only inputs and outputs) and can be
described as
18
block StateSpace
parameter Real A[:, :],
B[size(A, 1), :],
C[:, size(A, 2)],
D[size(C, 1), size(B, 2)]=zeros(size(C, 1), size(B, 2));
input
Real u[size(B, 2)];
output
Real y[size(C, 1)];
protected
Real
x[size(A, 2)];
equation
assert(size(A, 1) == size(A, 2), "Matrix A must be square.");
der(x) = A*x + B*u;
y
= C*x + D*u;
end StateSpace;
Assert is a predefined function for giving error messages taking a Boolean condition and a string
as arguments. The actual dimensions of A, B and C are implicitly given by the actual matrix
parameters. D defaults to a zero matrix:
block TestStateSpace
StateSpace S(A = [0.12, 2;
3, 1.5], B = [2, 7;
equation
S.u = {time, sin(time)};
end TestStateSpace;
The block class is introduced to allow better diagnostics for pure input/output model
components. In such a case the correctness of the component can be analyzed locally which is
not possible for components where the causality of the public variables is unknown.
2.7
with a given set of coefficients ci in a vector a[n+1] with a[i] = ci-1. Such a sum can be expressed
in matrix form as a scalar product of the form
a * {1, x, x^2, ... x^n}
19
The recursive formulation above is not so understandable though. One possibility would have
been to introduce a special matrix operator for element exponentiation as in Matlab (.^). The
readability does not increase much though.
Matrix equations like
xpowers[2:n+1] = xpowers[1:n]*x;
can be expressed in a form that is more familiar to programmers by using a for loop:
for i in 1:n loop
xpowers[i+1] = xpowers[i]*x;
end for;
This for-loop is equivalent to n equations. It is also possible to use a block for the polynomial
evaluation:
block PolynomialEvaluator
parameter Real a[:];
input Real x;
output Real y;
protected
parameter Integer n = size(a, 1)-1;
Real xpowers[n+1];
equation
xpowers[1] = 1;
for i in 1:n loop
xpowers[i+1] = xpowers[i]*x;
end for;
y = a * xpowers;
end PolynomialEvaluator;
It is also possible to bind the inputs and outputs in the parameter list of the invocation.
PolynomialEvaluator polyeval(a={1, 2, 3, 4}, x=time, y=p);
Component components[n];
equation
for i in 1:n-1 loop
connect(components[i].Outlet, components[i+1].Inlet);
end for;
Algorithms
The basic describing mechanism of Modelica are equations and not assignment statements. This
gives the needed flexibility, e.g., that a component description can be used with different
causalities depending on how the component is connected. Still, in some situations it is more
convenient to use assignment statements. For example, it might be more natural to define a
digital controller with ordered assignment statements since the actual controller will be
implemented in such a way.
It is possible to call external functions written in other programming languages from Modelica
and to use all the power of these programming languages. This can be quite dangerous because
many difficult-to-detect errors are possible which may lead to simulation failures. Therefore, this
should only be done by the simulation specialist if tested legacy code is used or if a Modelica
implementation is not feasible. In most cases, it is better to use a Modelica algorithm which is
designed to be much more secure than calling external functions.
The vector xvec in the polynomial evaluator above had to be introduced in order that the number
of unknowns are the same as the number of equations. Such a recursive calculation scheme is
often more convenient to express as an algorithm, i.e., a sequence of assignment statements, ifstatements and loops, which allows multiple assignments:
algorithm
y := 0;
xpower := 1;
for i in 1:n+1 loop
y := y + a[i]*xpower;
xpower := xpower*x;
end for;
A Modelica algorithm is a function in the mathematical sense, i.e. without internal memory and
side-effects. That is, whenever such an algorithm is used with the same inputs, the result will be
exactly the same. If a function is called during continuous integration this is an absolute
prerequisite. Otherwise the mathematical assumptions on which the integration algorithms are
based on, would be violated. An internal memory in an algorithm would lead to a model giving
different results when using different integrators. With this restriction it is also possible to
symbolically form the Jacobian by means of automatic differentiation. This requirement is also
present for functions called only at event instants (see below). Otherwise, it would not be
possible to restart a simulation at any desired time instant, because the simulation environment
does not know the actual value of the internal algorithm memory.
In the algorithm section, ordered assignment statements are present. To distinguish from
equations in the equation sections, a special operator, :=, is used in assignments (i.e. given
causality) in the algorithm section. Several assignments to the same variable can be performed
21
Functions
The polynomial evaluator above is a special input-output block since it does not have any states.
Since it does not have any memory, it would be possible to invoke the polynomial function as a
function, i.e. memory for variables are allocated temporarily while the algorithm of the function
is executing. Modelica allows a specialization of a class called function which has only public
inputs and outputs, one algorithm and no equations.
The polynomial evaluation can thus be described as:
function
input
input
output
PolynomialEvaluator2
Real a[:];
Real x;
Real y;
protected
Real
xpower;
algorithm
y := 0;
xpower := 1;
for i in 1:size(a, 1) loop
y := y + a[i]*xpower;
xpower := xpower*x;
end for;
end PolynomialEvaluator2;
A function declaration is similar to a class declaration but starts with the function keyword. The
input arguments are marked with the keyword input (since the causality is input). The result
argument of the function is marked with the keyword output.
22
It is also possible to invoke the function with positional association of the actual arguments:
p = PolynomialEvaluator2({1, 2, 3, 4}, time);
i.e., the actual values of all input variables are provided in the list after the function name and the
return values of this function are provided at the left hand side of the equal sign enclosed in
parentheses.
External functions
It is possible to call functions defined outside of the Modelica language. The body of an external
function is marked with the keyword external:
function log
input Real x;
output Real y;
external
end log;
There is a "natural" mapping from Modelica to the target language and its standard libraries. The
C language is used as the least common denominator.
The arguments of the external function are taken from the Modelica declaration. If there is a
scalar output, it is used as the return type of the external function; otherwise the results are
returned through extra function parameters. Arrays of simple types are mapped to an argument of
the simple type, followed by the array dimensions. Storage for arrays as return values is allocated
by the calling routine, so the dimensions of the returned array is fixed. It is possible to specify
exactly the order of the arguments for the external C-function as well as the name of the C23
It is expected that an external C-function is available which has the following prototype:
void ab04md(const char *, size_t, size_t, size_t, double, double,
double *, size_t, double *, size_t, double *, size_t,
double *, size_t, int *, double *, size_t, int *);
and the Modelica translator maps a function call of BilinearSampling to a function call of the Cfunction ab04md. Within Modelica, this function is called as:
parameter Real alpha=1, beta=1;
parameter Real A[:,:] = [0, 1; 2, 4], B[:,:]=...;
Real Ares[size(A, 1), size(A, 2)], Bres ...;
equation
(Ares,Bres,Cres,Dres,info) = BilinearSampling(alpha,beta,A,B,C,D,true);
More details, especially the exact mapping of the Modelica types to C and Fortran 77 types, are
discussed in the appendix of the Modelica Language Specification.
2.8
Hybrid Models
Modelica can be used for mixed continuous and discrete models. For the discrete parts, the
synchronous data flow principle with the single assignment rule is used. This fits well with the
continuous DAE with equal number of equations as variables. Certain inspiration for the design
has been obtained from the languages Signal (Gautier, et.al., 1994) and Lustre (Halbwachs, et.al.
1991).
Discontinuous Models
If-then-else expressions allow modeling of a phenomena with different expressions in different
24
This construct might introduce discontinuities. If this is the case, appropriate information about
the crossing points should be provided to the integrator. The use of crossing functions is
described later.
More drastic changes to the model might require replacing one set of equations with another
depending on some condition. It can be described as follows using vector expressions:
zeros(3) = if cond_A
{ expression_A1l expression_A2l else if cond_B then
{ expression_B1l expression_B2l else
{ expression_C1l expression_C2l -
then
expression_A1r,
expression_A2r }
expression_B1r,
expression_B2r }
expression_C1r,
expression_C2r };
The size of the vectors must be the same in all branches, i.e., there must be equal number of
expressions (equations) for all conditions.
It should be noted that the order of the equations in the different branches is important. In certain
cases systems of simultaneous equations will be obtained which might not be present if the
ordering of the equations in one branch of the if-construct is changed. In any case, the model
remains valid. Only the efficiency might be unnecessarily reduced.
Conditional Models
It is useful to be able to have models of different complexities. For complex models, conditional
components are needed as shown in the next example where the two controllers are modeled
itself as subcomponents:
block Controller
input Boolean simple=true;
input Real e;
output Real y;
protected
Controller1 c1(u=e, enable=simple);
Controller2 c2(u=e, enable=not simple);
equation
y = if simple then c1.y else c2.y;
end Controller;
Attribute enable is built-in Boolean input of every block with default equation "enable=true". It
allows enabling or disabling a component. The enable-condition may be time and state
dependent. If enable=false for an instance, its equations are not evaluated, all declared variables
are held constant and all subcomponents are disabled. Special consideration is needed when
enabling a subcomponent. The reset attribute makes it possible to reset all variables to their Startvalues before enabling. The reset attribute is propagated to all subcomponents. The previous
controller example could then be generalized as follows, taking into account that the Boolean
variable simple could vary during a simulation.
25
The equations are active instantaneously when the condition becomes true. It is possible to use a
vector of conditions. In such a case the equations are active whenever any of the conditions
becomes true.
Special actions can be performed when the simulation starts and when it finishes by testing the
built-in predicates initial() and terminal( ). A special operator reinit(state, value) can be used to
assign new values to the continuous states of a model at an event.
Lets consider discrete time systems or sampled data systems. They are characterized by the
ability to periodically sample continuous input variables, calculate new outputs influencing the
continuous parts of the model and update discrete state variables. The output variables keep their
values between the samplings. We need to be able to activate equations once every sampling.
There is a built-in function sample(Start, Interval) that is true when time=Start + n*Interval,
n>=0. A discrete first order state space model can then be written as
block DiscreteStateSpace
parameter Real a, b, c, d;
parameter Real Period=1;
input Real u;
discrete output Real y;
protected
discrete Real x;
equation
when sample(0, Period) then
x = a*pre(x) + b*u;
y = c*pre(x) + d*u;
end when;
end DiscreteStateSpace;
The special notation pre(x) is used to denote the left limit of the discrete state variable x at an
event instant, whereas variable x always denotes the right limit.
In this case, the first sampling is performed when simulation starts. With Start > 0, there would
not have been any equation defining x and y initially. All variables being defined by whenstatements hold their values between the activation of the equations and have the value of their
26
The built-in operator edge(v), for discrete-time variable v, is defined as "v and not pre(v)", i.e.,
it is true at the time instant when v changes its value and otherwise it is false. With this operator
the precise meaning of a when clause
when condition then
v2 = f1(..);
v3 = f2(..);
end when
In other words, at the time instant when b changes its value from false to true, the two equations
are activated. At all other time instants, v2 and v3 hold their previous value. The pre-value of b
at the initial time is determined by evaluating the condition with the start values of all variables
appearing in this condition. If this evaluates to true, the when-clause equations are not activated
at the initial time. As sketched in this example, when-clause equations are mapped to equations
which can be sorted together with all other discrete and continuous equations. In order that this is
possible, there is the restriction that equations in when-clauses do not have the general form
"expr1 = expr2", but the restricted form "v1 = expr", i.e., a single variable or array at the left
hand side of the equality sign. The reason for this restriction becomes apparent in the following
example:
27
When the equations of the when-clause are not activated it is not clear which variable to hold
constant, either x or y. A corrected version of this example is:
Real x,y;
equation
x + y = 5;
when condition then
y = 7 - 2*x;
end when;
// fine
Here, variable y is held constant when the when-clause is de-activated and x is computed from
the first equation using the value of y from the previous event instant.
When-clauses in equation sections can have only one branch. However, in algorithm sections,
elsewhen branches are possible. This is useful, in order to define priorities between discrete
actions, such as:
Boolean open;
algorithm
when h1 < hmax then
open := true;
elsewhen pushbutton then
open := false;
end when;
Here, the condition "h1 < hmax" has higher priority as the condition "pushbutton", if both
conditions become true at the same event instant. Similarly as for when-clauses in equation
sections, the precise meaning of this when-clause in an algorithm can be expressed as:
Boolean open(start = false);
Boolean b1 (start = h1.start < hmax);
Boolean b2 (start = pushbutton.start);
algorithm
open := pre(open);
b1
:= h1 < hmax;
b2
:= pusbutton;
if edge(b1) then
open := true;
elseif edge(b2) then
open := false;
end when;
Note, that this is a conceptual mapping and a Modelica translator may perform it more
efficiently. In general, all discrete-time variables which are potentially assigned in an algorithm
section (such as variable "open" above) are initialized with their "pre"-value when the algorithm
section is entered, whereas all continuous-time variables which are potentially assigned in an
algorithm section are initialized with their "start"-value.
The condition of a when-clause may be a vector expression. In this case the when-clause is
activated whenever one of the elements of the vector condition becomes true. Example:
28
model vectorwhen
parameter Real A=1.5, w=6;
Real
u1, u2;
Boolean b1, b2;
equation
u1 = A*Modelica.Math.sin(w*time);
u2 = A*Modelica.Math.cos(w*time);
when u1 > 0 or u2 > 0 then
b1 = not pre(b1);
end when;
when {u1 > 0, u2 > 0} then
// vector condition
b2 = not pre(b2);
end when;
end vectorwhen;
The two when clauses are not equivalent as can be seen when applying the discussed mapping
rule:
b1 = if edge(u1 > 0 or u2 > 0)
then not pre(b1) else pre(b1);
b2 = if edge(u1 > 0) or edge(u2 > 0) then not pre(b2) else pre(b2);
If the conditions used in if-the-else expressions contain relations with dynamic variables, the
corresponding derivative function f might not be continuous and have as many continuous partial
derivatives as required by the integration routine in order for efficient simulation. Every change
of such a relation triggers an event in Modelica in order to efficiently and reliably handle such a
discontinuity. Modern integrators have indicator functions for such discontinuous events. For a
relation like v1 > v2, a proper indicator function is v1 - v2.
If the resulting if-then-else expression is smooth, the modeller has the possibility to give this
extra information to the integrator in order to avoid event handling and thus enhance efficiency.
This can be done by embedding the corresponding relation in a function noEvent as follows.
y = if
noEvent(u > HighLimit) then HighLimit
else if noEvent(u < LowLimit) then LowLimit else u;
The noEvent() operator can only be applied in Real equations, but not in Boolean, Integer or
String equations, in order that Boolean, Integer and String variables can change their value only
at event instants, i.e., they are always discrete-time variables. (for the exact formulation of this
restriction, see section 3.4.8 in the Modelica Language Specification).
Synchronization and event propagation
Propagation of events can be done by the use of Boolean variables. A Boolean equation like
Out.Overflowing = Height > MaxLevel;
29
It is not possible to write i as a function of v or vice versa because the ideal characteristics.
However, for such planar curves a parametric form can be used
x = f(s)
y = g(s)
30
This technique is also appropriate to model ideal thyristors, hysteresis and ideal friction.
Conditional Equations with Causality Changes
The following example models a breaking pendulum - a simple variable structure model. The
number of degrees-of-freedom increases from one to two when the pendulum breaks. The
example shows the needs to transfer information from one set of state variables (phi, phid) to
another (pos, vel) at an event. Consider the following description with a parameter Broken.
model BreakingPendulum
parameter Real m=1, g=9.81, L=0.5;
parameter Boolean Broken;
input Real
u;
Real pos[2], vel[2];
constant Real PI=3.141592653589793;
Real phi(start=PI/4), phid;
equation
vel = der(pos);
if not Broken then
// Equations of pendulum
pos = {L*sin(phi), -L*cos(phi)};
phid = der(phi);
m*L*L*der(phid) + m*g*L*sin(phi) = u;
else;
// Equations of free flying mass
m*der(vel) = m*{0, -g};
end if;
end BreakingPendulum;
This problem is non-trivial to simulate if Broken would be a dynamic variable because the
defining equations of the absolute position "pos" and of the absolute velocity "vel" of the mass
change causality when the pendulum breaks. When "Broken=false", the position and the velocity
are calculated from the Pendulum angle "phi" and Pendulum angular velocity "phid". After the
Pendulum is broken, the position and velocity are state variables and therefore known quantities
in the model.
31
block Pendulum
extends BasePendulum;
constant Real PI=3.141592653589793;
output
Real phi(start=PI/4), phid;
equation
phid = der(phi);
p.m*p.L*p.L*der(phid) + p.m*p.g*p.L*sin(phi) = u;
pos = {p.L*sin(phi), -p.L*cos(phi)};
vel = der(pos);
end Pendulum;
block BrokenPendulum
extends BasePendulum;
equation
vel = der(pos);
p.m*der(vel) = p.m*{0, -p.g};
end BrokenPendulum;
model BreakingPendulum2
extends BasePendulum(p(m=1, g=9.81, L=0.5));
input Boolean Broken;
protected
Pendulum
pend (p=p, u=u, enable=not Broken);
BrokenPendulum bpend(p=p, u=u, enable=Broken);
equation
when Broken then
reinit(bpend.pos, pend.pos);
reinit(bpend.vel, pend.vel);
end when;
pos = if not Broken then pend.pos else bpend.pos;
vel = if not Broken then pend.vel else bpend.vel;
end BreakingPendulum2;
This rewriting scheme is always possible and results in a larger model. It has the drawback that
32
The trick was to use complete polar coordinates including the length, L and to give a differential
equation for L in the non Broken mode. If the derivatives of some variables are not calculated
during the "not Broken"-phase, the variables "pos" and "vel" can be considered as algebraic
variables. A simulator thus has the possibility to remove them from the set of active state
variables.
2.9
Physical Fields
Modeling of physical fields, such as an environment with fixed temperature and pressure, or an
electrical or a gravity field, is possible with the already introduced language elements. However,
for bigger systems modeling becomes tedious and inconvenient, because lumped physical field
models lead to 1 to n or n to n connections between all n components influenced by a field. For 1
to n connections, Modelica offers a convenient modeling mechanism with the inner and outer
language elements. Basically, these two elements are used in the following way:
model Component
outer Real T0;
Real T;
equation
T = T0;
end Component;
model Environment
inner Real T0;
Component c1, c2;
parameter Real a=1;
33
All components which generate heat need a reference to the environment heat connector:
model Component
outer HeatCut environment; // reference to environment
HeatCut heat;
// heat connector of component
...
equation
connect(heat, environment);
...
end Component;
The components can be used in several levels until the environment of the circuit board is
reached where the "inner" declaration of the heat connector is present. All instances of model
Component which are used inside model CircuitBoard automatically connect their heat flow
connector to the environment connector, i.e., there is a 1 to n connection of the "inner HeatCut
34
where only the interface of the function is defined. Since it is a partial function, this function
cannot be called and can only be used as superclass for other functions, such as:
function uniformGravity
extends gravityInterface;
algorithm
g := {0, -9.81, 0};
end uniformGravity;
function pointGravity
extends gravityInterface;
parameter Real k=1;
protected
Real n[3]
algorithm
n := -r/sqrt(r*r);
g := k/(r*r) * n;
end pointGravity;
The idea is to utilize the partial function "gravityInterface" when defining the particle model
which shall move in a gravity field
model Particle
parameter Real m = 1;
outer function gravity = gravityInterface;
Real r[3](start = {1,1,0}) "position";
Real v[3](start = {0,1,0}) "velocity";
equation
der(r) = v;
m*der(v) = m*gravity(r);
end Particle;
and to define the function which is actually used to compute the gravity acceleration at an outer
level using an inner function definition:
model Composite1
inner function gravity = pointGravity(k=1);
Particle p1, p2(r(start={1,0,0}));
end Composite1;
model Composite2
inner function gravity = uniformGravity;
Particle p1, p2(v(start={0,0.9,0}));
end Composite2;
35
As can be seen by this example, different fields of this nature can be handled at the same time.
// Modelica.Mechanics.Rotational.Inertia
From the outside of package Modelica, components can be accessed via dot-notation, e.g., model
Inertia is uniquely identified as Modelica.Mechanics.Rotational.Inertia.
Name look-up in hierarchically structured classes
Within a hierarchical package (or in general in any class, such as a model or a block), the first
part of a name is searched recursively in upper hierarchies until this name is found. The rest of
the name is located in the hierarchy below this name. For example:
package Modelica
package Blocks
package Interfaces
connector InPort
...
end InPort;
end Interfaces;
end Blocks;
package Mechanics
package Rotational
package Interfaces
connector Flange_a
...
end Flange_a;
end Interfaces
model Inertia
Interfaces.Flange_a a1; // Modelica.Blocks.Interfaces.Flange_a
Modelica.Mechanics.Rotational.Interfaces.Flange_a a2;
end Inertia;
36
// Modelica.Blocks...
37
The encapsulated prefix stops name look-up from lower to upper hierarchies. As a result, within
such a "self-contained unit" it is no longer possible to access classes outside of this unit in an
uncontrolled way. Instead, such classes have to be made explicitly available with the import
statement. Consequently, when moving or copying an encapsulated class, at most the import
statements in this class have to be changed, and nothing else. If an encapsulated class does not
contain another encapsulated class, not even import statements have to be changed in such a
situation.
In the example above, the typical usage of the encapsulated prefix is demonstrated. Package
Modelica.Blocks is constructed as a "self-contained unit". Since this unit is already quite large, it
is further hierarchically structured with subpackages, such as "Interfaces", "Continuous",
"Examples". These subpackages are not defined as encapsulated, because (1) there are many
dependencies between these subpackages and it is more convenient to access the different parts
of package Blocks directly and because (2) it is not very useful to cut-off parts of this package
and use it somewhere else, i.e., the library developer does not see, e.g.,
"Modelica.Blocks.Continuous" as a self-contained unit. On the other hand, the models within the
Modelica:Blocks.Examples subpackage are declared as encapsulated, because a modeller may
wish to copy such an example model out of the library and use or modify it.
The import statement can be used in three different variants:
import Modelica.Mechanics.Rotational;
// access by Rotational.Torque
import R = Modelica.Mechanics.Rotational;// access by R.Torque
import Modelica.Mechanics.Rotational.*; // access by Torque
In all cases, the first part of the name defined in the import statement is located within the toplevel classes and no hierarchical search in upper hierarchical levels is performed. Note, that
import statements are not inherited in order to not introduce hidden dependencies. The third,
"unqualified", form for import statements should be avoided, because, e.g., the later addition of a
model "Gearbox" to package Modelica.Mechanics.Rotational may give rise to a name conflict, if
the same name is already used in the user model where this import statement is present.
Therefore, by just getting a new version of the Modelica Standard Library, existing user models
may no longer work. This cannot happen with the first two variants. The "unqualified" variant is
useful, to arrive at the standard notation for some basic mathematical constants and functions,
such as:
model SineVoltageSource
import Modelica.Constants.*;
// to access Modelica.Constants.pi
import Modelica.Math.*;
// to access Modelica.Math.sin
extends Modelica.Electrical.Analog.Interfaces.OnePort;
parameter Real A=220 "amplitude";
parameter Real f=50 "frequency";
38
The complete class is stored in one file, where the file name is the class name with extension
".mo". Examples:
file
: Modelica.mo
content: encapsulated package Modelica
encapsulated package Blocks
...
end Blocks;
...
end Modelica;
file
: robot.mo
content: model robot
...
end robot;
: .../library/Modelica/Blocks/Examples/package.mo:
39
The top-level classes, such as "Modelica", are located in all directories defined in the
environment variable MODELICAPATH, which contains a semicolon-separated list of directory
names. For example, the first part of the class name A.B.C (i.e., A) is located by searching the
ordered list of directories in MODELICAPATH. If no directory contains A the lookup fails. If A
has been found in one of the directories, the rest of the name is located in A; if that fails, the
entire lookup fails without searching for A in any of the remaining directories in
MODELICAPATH.
The quantity attribute defines the category of the variable, like Length, Mass, Pressure. The unit
attribute defines the unit of a variable as utilized in the equations. That is, all equations in which
the corresponding variable is used are only correct, provided the numeric value of the variable is
given with respect to the defined unit. Finally, displayUnit gives the default unit to be used in
tools based on Modelica for interactive input and output. If, for example, a parameter value is
input via a menu, the user can select the desired unit from a list of units, using the "displayUnit"
value as default. When generating Modelica code, the tool makes the conversion to the defined
40
the units of type Torque and type Energy can be both transformed to the same base units, namely
"kg.m2/s2". Still, the two types characterize different physical quantities and when displaying
the possible displayUnits for torque types, unit "J" should not be in such a list. If only a unit
name is given and no quantity name, it is not possible to get a list of displayUnits in a simulation
environment.
Together with Modelica the standard package Modelica.SIunits of predefined quantity and
connector types is provided in the form as shown in the example above. This package is based on
the corresponding ISO norm. This will give some help in standardization of the interfaces of
models. The grammar for unit expressions, such as "N.m/s2" is defined in the Modelica
Language Specification and follows an ISO recommendation. Note, that the prefix final defines
that the quantity and unit values of the predefined types cannot be modified.
Conversion between units is not supported within the Modelica language. This simplifies a
Modelica translator considerably, especially because a unit-database with its always incomplete
collection of units is not needed, see e.g. (Cardarelli 1997). As a consequence, the semantics of a
correct Modelica model is independent of the unit attributes and the Modelica translator can
ignore them during code generation. Especially, the unit attributes need not be checked for a
connection, i.e., connected variables may have different quantities and units.
Much more support on units and quantities will be given by tools based on Modelica. This will
be considered as "quality of implementation". An object-diagram editor may, for example,
support automatic unit conversion when two interfaces are connected. As a general rule it will
always be allowed to connect any variable to a variable which has no quantity and unit
associated with it. Furthermore, a Modelica translator may optionally check equations on correct
dimensionality (this will produce only warning messages, i.e., code will be produced anyway).
The equation "f=m*a" would, for example, produce a warning, if "f" is given in "N.m" because
then the units are not compatible to each other. The variables in the equations may have non-SI
units. Therefore, for example, the compiler will not detect that "f=m*a" is an error, if the units
"N" for "f", "g" for "m" and "m/s2" for "a" are used. Dimension checking is done by
transforming the "quantity" information into one of the seven base "quantities" (like "Mass",
"Length").
Usually, units are associated with types. There are however elements where instances may have a
different unit by redefinition of the quantity type. Example:
type Voltage = Real(final quantity="Voltage", final unit="V");
41
In a block diagram library there is a general sine signal generator. When it is used to generate a
voltage sine for a voltage source, the output of the signal generator should have a unit of "V".
This can be accomplished by having the type of the amplitude and of the output as a replaceable
type which can be changed appropriately when this signal generator is instantiated.
Annotations associated with a component, typically to specify position and size of the
component.
Annotations of a class to specify the graphical representation of its icon (see above),
diagram, and common properties such as the local coordinate system.
Annotations associated with connections, i.e., route, color of connection line, etc.
The example below shows the use of such graphical attributes to define a resistor.
model Resistor
Pin p annotation (extent=[-110, -10; -90, 10]);
Pin n annotation (extent=[ 110, -10; 90, 10]);
parameter R "Resistance in [Ohm]";
equation
R*p.i = p.v - n.v;
n.i = p.i;
public
annotation (Icon(
Rectangle(extent=[-70, -30; 70, 30], style(fillPattern=1)),
Text(extent=[-100, 55; 100, 110], string="%name=%R"),
Line(points=[-90, 0; -70, 0]),
Line(points=[70, 0; 90, 0])
));
end Resistor;
The resistor has two pins, and we specify two opposite corners of the extent of their graphical
representation. An icon of the Resistor is defined by a rectangle, a text string and two lines. For
the rectangle we specify additional style attributes for fill pattern.
The extent specified for a component is used to scale the icon image. The icon is drawn in the
master coordinate system specified in the components class. The icon is scaled and translated so
the coordinate system is mapped to the region defined in the component declaration.
The attribute set to represent component positions, connections and various graphical primitives
for building icons is shown below. The attribute structures are described through Modelica
classes. Points and extents (two opposite points) are described in matrix notation.
type Point = Real[2];
// {x, y}
record CoordinateSystem
Extent extent;
Point grid;
Point size;
end CoordinateSystem;
// Attribute to class
record Placement
Extent extent;
Real rotation;
end Placement;
43
The graphical unit of the master coordinate system used when drawing lines, rectangles, text etc.
is the baseline spacing of the default font used by the graphical tool, typically 12 points for a 10
point font (note: baseline spacing = space between text lines).
Definition of menu lists
If replaceable models are used, it is convenient in a graphical user environment to present the
user a list of alternative models which can be used for redeclaration. This can be accomplished
with the predefined annotation "choices":
replaceable model MyResistor=Resistor
annotation(choices(
choice(redeclare MyResistor=lib2.Resistor(a={2}) "Resistor 1"),
choice(redeclare MyResistor=lib2.Resistor2 "Resistor 2")));
replaceable Resistor Load(R=2) extends OnePort
annotation(choices(
choice(redeclare lib2.Resistor Load(a={2}) "Resistor"),
44
The "choices" annotation contains modifiers on choice, where each of them indicates a suitable
redeclaration or modifications of the element. The string comments on the choice declaration can
be used as textual explanations of the choices. A graphical user environment could display the
string comments in a list and after selection of one of the alternatives by the user, the redeclare
statement of the corresponding choice is executed.
This annotation is not restricted to replaceable elements but can also be applied to nonreplaceable elements, enumerated types, and simple variables. Example:
type controllerType=Integer(min=1,max=3)
annotation(choices(
choice=1 "P",
choice=2 "PI",
choice=3 "PID"));
model test
parameter controllerType c;
...
end test;
test t;
When displaying the parameter menu for model t, a Modelica environment could present not a
value field for parameter c, but a choice selecting menu with the entries "P", "PI" and "PID" as
choices. After the selection, the graphical environment transforms the choice into the Integer
values 1, 2 or 3.Documentation of models
In practical modeling studies, documenting the model is an important issue. It is not only for
writing a report on the modeling work, but also to record additional information which can be
consulted when the model is reused. This information need not necessarily be completely
structured and standardized in the sense that Modelica language constructs are available for all
aspects. The following aspects should typically be recognized:
History information
Major milestones, like creation, important changes, release into public accessibility should be
recorded. Information to store are the author, date and a brief description. This functionality
is comparable with version control of software, using tools such as SCCS or RCS. If a
specific modeling procedure is used, the mile stones of such a procedure can be recorded in
this part.
References to literature
References to external documents and/or scientific literature for understanding the model, its
context and/or underlying theory should be mentioned here. The format can be like a
45
Currently, no further detail on structuring information is given. The information is given as plain
text in the appropriate category. It is likely that companies have their own way of documenting
their models and experiments, so that different ways of filling in the documentation information
are needed. In the Modelica Standard Library, the annotation "info" is used to define the
documentation. For example, the documentation of this package is defined as:
annotation ( Documentation( info = "
<HTML>
<p>
Package <b>Modelica</b> is a <b>standardized</b> and <b>pre-defined</b>
package that is developed together with the Modelica language from the
Modelica Association, see
<a href=\"http://www.Modelica.org\">http://www.Modelica.org</a>.
It is also called <b>Modelica Standard Library</b>.
It provides constants, types, connectors, partial models and model
components in various disciplines.</p>
...
<HTML>" ) );
Within the documentation HTML-tags may be present. When extracting the documentation from
a model, a tool shall store this part of the documentation as HTML-file which can be displayed
by appropriate browsers such as Netscape or Microsoft Explorer in a nice way.
3. Examples
Modelica has been used to model various kinds of systems. Otter et.al., 1997 describes modeling
of automatic gearboxes for the purpose of real-time simulation. Such models are non-trivial
46
4. Conclusions
An overview of the most important language constructs as well as a series of useful modeling
examples has been given for Modelica, version 1.4, which was released in December 15, 2000.
Since the first release of Modelica 1.0 in September 1997, all necessary ingredients for modeling and
simulation of industrial applications with Modelica have been developed and put together: The
language, libraries, tools and successful applications. More detailed information and the most
actual status can be found at
http://www.Modelica.org/
Therefore, it can be expected that Modelica will have a significant impact in the modeling and
simulation community in the future. The Modelica Association is very interested to further adapt
the Modelica language to the needs of the end-users and to further develop the Modelica
libraries. Interested simulation professionals who would like to contribute are encouraged and
invited to participate at the design meetings (see the Modelica homepage for details where and
when design meetings take place).
5. References
Abadi M., and L. Cardelli: A Theory of Objects. Springer Verlag, ISBN 0-387-94775-2, 1996.
Broenink J.F.: "Bond-Graph Modeling in Modelica". ESS97 - European Simulation
Symposium, Oct., 1997.
Cardarelli F.: Scientific Unit Conversion. Springer Verlag, 1997.
Cardelli L.: "Types for Data-Oriented Languages (Overview)", in J. W. Schmidt, S. Ceri and M.
Missikof (Eds.): Advances in Database Technology - EDBT88, Lecture Notes in Computer
Science n. 303, Springer-Verlag, 1988.
Cardelli L.: "Typeful Programming", in E. J. Neuhold and M. Paul (Eds.): Formal description of
Programming Concepts, Springer-Verlag, 1991. Also published as SRC Research Report 45,
Digital Equipment Corporation.
Elmqvist H., F.E. Cellier, and M. Otter: Object-oriented modeling of hybrid systems. In
47
6. Revision history
This section describes the history of the Modelica Language Design, and its contributors. The
current version of this document is available from http://www.modelica.org/.
This document was written together with the Modelica Language Specification 1 as one
document, and in version 1.1 they were revised and separated into two documents.
For Modelica 1.4, the tutorial has been updated with the most important language elements
introduced since version 1.1 and therefore reflects the current status of the Modelica language.
This document was edited by M. Otter and H. Olsson.
Modelica 1.4
Modelica 1.4 was released December 15, 2000. The Modelica Association was formed in Feb. 5,
2000 and is now responsible for the design of the Modelica language.
Functions can specify their derivative. This allows, e.g., the application of the Pantelides
algorithm to reduce the index of a DAE also for external functions.
New built-in operator "rem" (remainder) and the built-in operators div, mod, ceil, floor,
integer, previously only allowed to be used in when-clauses can now be used
everywhere, because state events are automatically generated when the result value of
one of these operator changes discontinuously ().
Quantity attribute also for base types Boolean, Integer, String (and not only for Real), in
order to allow abstracted variables to refer to physical quantities (e.g. Boolean
i(quantity="Current") is true if current is flowing and is false if no current is flowing).
Modelica 1.4 is backwards compatible with Modelica 1.3, with the exception of (1) some exotic
cases where different results are achieved with the removed "declare-before-use-rule" and the
previous declaration order, (2) when-clauses in equations sections, which use the general form
"expr1 = expr2" (now only "v=expr" is allowed + some special cases for functions), (3) some
exotic cases where a when-clause may be no longer evaluated at the initial time, because the
initialization of the when-condition is now defined in a more meaningful way (before Modelica
1.4, every condition in a when-clause has a "previous" value of false), and (4) models containing
the nondiscrete keyword which was removed.
Modelica 1.0
Modelica 1, the first version of Modelica, was released in September 1997, and had the language
specification as a short appendix to the rationale.
52