This package is a reference to Modelica keywords, Modelica builtin operators, and the Modelica grammar. It is based on the Modelica Language Specification version 3.4 from 10th April 2017. Currently, not the whole Modelica language is documented in ModelicaReference (but a large subset).
Copyright © 2003-2020, Modelica Association and contributors
This Modelica package is free software and the use is completely at your own risk; it can be redistributed and/or modified under the terms of the 3-Clause BSD license. For license conditions (including the disclaimer of warranty) visit https://modelica.org/licenses/modelica-3-clause-bsd.
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Name | Description |
---|---|
ModelicaGrammar | Modelica Grammar |
Annotations | Annotations |
Classes | Classes (model, function, ...) |
Operators | Operators (+, der, size, ...) |
BalancedModel | Balanced model |
'encapsulated' | encapsulated |
'extends' | extends |
'flow' | flow |
'for' | for |
'if' | if |
'import' | import |
'input' | input |
'output' | output |
'partial' | partial |
StateMachines | State Machines |
'stream' | stream |
Synchronous | Synchronous Language Elements |
'time' | time |
'when' | when |
'while' | while |
Contact | Contact |
Icons | Library of icons |
This is the grammar of Modelica 3.4 in EBNF form. Each non-terminal appearing on the right hand side of a production is a link to the production for that non-terminal. This grammar is identical to that in the Modelica 3.4 specification except for removal of some unnecessary parentheses, grouping of some common terms, and reformatting for easier readability. The following typographic conventions are used:
stored_definition:
[ within [ name ] ";" ] { [ final ] class_definition ";" }
class_definition:
[ encapsulated ] class_prefixes class_specifier
class_prefixes:
[ partial ]
( class | model | [ operator ] record | block | [ expandable ] connector
| type | package | [ pure | impure ] [ operator ] function | operator )
class_specifier:
long_class_specifier | short_class_specifier | der_class_specifier
long_class_specifier:
IDENT string_comment composition end IDENT
| extends IDENT [ class_modification ] string_comment composition end IDENT
short_class_specifier:
IDENT "=" base_prefix type_specifier [ array_subscripts ] [ class_modification ] comment
| IDENT "=" enumeration "(" ( [ enum_list ] | ":" ) ")" comment
der_class_specifier:
IDENT "=" der "(" type_specifier "," IDENT { "," IDENT } ")" comment
base_prefix:
[ input | output ]
enum_list:
enumeration_literal { "," enumeration_literal }
enumeration_literal:
IDENT comment
composition:
element_list
{ public element_list | protected element_list | equation_section | algorithm_section }
[ external [ language_specification ]
[ external_function_call ] [ annotation_comment ] ";" ]
[ annotation_comment ";" ]
language_specification:
STRING
external_function_call:
[ component_reference "=" ] IDENT "(" [ expression_list ] ")"
element_list:
{ element ";" }
element:
import_clause
| extends_clause
| [ redeclare ] [ final ] [ inner ] [ outer ]
( class_definition
| component_clause
| replaceable ( class_definition | component_clause )
[ constraining_clause comment ] )
import_clause:
import ( IDENT "=" name | name [ "." "*" | ".*" | "{" import_list "}" ] ) comment
import_list:
IDENT { "," IDENT }
extends_clause:
extends type_specifier [ class_modification ] [ annotation_comment ]
constraining_clause:
constrainedby type_specifier [ class_modification ]
component_clause:
type_prefix type_specifier [ array_subscripts ] component_list
type_prefix:
[ flow | stream ] [ discrete | parameter | constant ] [ input | output ]
component_list:
component_declaration { "," component_declaration }
component_declaration:
declaration [ condition_attribute ] comment
condition_attribute:
if expression
declaration:
IDENT [ array_subscripts ] [ modification ]
modification:
class_modification [ "=" expression ]
| "=" expression
| ":=" expression
class_modification:
"(" [ argument_list ] ")"
argument_list:
argument { "," argument }
argument:
element_modification_or_replaceable | element_redeclaration
element_modification_or_replaceable:
[ each ] [ final ] ( element_modification | element_replaceable )
element_modification:
name [ modification ] string_comment
element_redeclaration:
redeclare [ each ] [ final ]
( short_class_definition | component_clause1 | element_replaceable )
element_replaceable:
replaceable ( short_class_definition | component_clause1 )
[ constraining_clause ]
component_clause1:
type_prefix type_specifier component_declaration1
component_declaration1:
declaration comment
short_class_definition:
class_prefixes short_class_specifier
equation_section:
[ initial ] equation { equation ";" }
algorithm_section:
[ initial ] algorithm { statement ";" }
equation:
( simple_expression "=" expression
| if_equation
| for_equation
| connect_clause
| when_equation
| component_reference function_call_args ) comment
statement:
( component_reference ( ":=" expression | function_call_args )
| "(" output_expression_list ")" ":=" component_reference function_call_args
| break
| return
| if_statement
| for_statement
| while_statement
| when_statement ) comment
if_equation:
if expression then { equation ";" }
{ elseif expression then { equation ";" } }
[ else { equation ";" } ]
end if
if_statement:
if expression then { statement ";" }
{ elseif expression then { statement ";" } }
[ else { statement ";" } ]
end if
for_equation:
for for_indices loop { equation ";" } end for
for_statement:
for for_indices loop { statement ";" } end for
for_indices:
for_index { "," for_index }
for_index:
IDENT [ in expression ]
while_statement:
while expression loop { statement ";" } end while
when_equation:
when expression then { equation ";" }
{ elsewhen expression then { equation ";" } }
end when
when_statement:
when expression then { statement ";" }
{ elsewhen expression then { statement ";" } }
end when
connect_clause:
connect "(" component_reference "," component_reference ")"
expression:
simple_expression
| if expression then expression
{ elseif expression then expression }
else expression
simple_expression:
logical_expression [ ":" logical_expression [ ":" logical_expression ] ]
logical_expression:
logical_term { or logical_term }
logical_term:
logical_factor { and logical_factor }
logical_factor:
[ not ] relation
relation:
arithmetic_expression [ relational_operator arithmetic_expression ]
relational_operator:
"<" | "<=" | ">" | ">=" | "==" | "<>"
arithmetic_expression:
[ add_operator ] term { add_operator term }
add_operator:
"+" | "-" | ".+" | ".-"
term:
factor { mul_operator factor }
mul_operator:
"*" | "/" | ".*" | "./"
factor:
primary [ ( "^" | ".^" ) primary ]
primary:
UNSIGNED_NUMBER
| STRING
| false
| true
| component_reference
| ( component_reference | der | initial | pure ) function_call_args
| "(" output_expression_list ")"
| "[" expression_list { ";" expression_list } "]"
| "{" array_arguments "}"
| end
type_specifier:
[ "." ] name
name:
IDENT { "." IDENT }
component_reference:
[ "." ] IDENT [ array_subscripts ] { "." IDENT [ array_subscripts ] }
function_call_args:
"(" [ function_arguments ] ")"
function_arguments:
expression [ "," function_arguments_non_first | for for_indices ]
| function name "(" [ named_arguments ] ")" [ "," function_arguments_non_first ]
| named_arguments
function_arguments_non_first:
function_argument [ "," function_arguments_non_first ]
| named_arguments
array_arguments:
expression [ "," array_arguments_non_first | for for_indices ]
array_arguments_non_first:
expression [ "," array_arguments_non_first ]
named_arguments:
named_argument [ "," named_arguments ]
named_argument:
IDENT "=" function_argument
function_argument:
function name "(" [ named_arguments ] ")"
| expression
output_expression_list:
[ expression ] { "," [ expression ] }
expression_list:
expression { "," expression }
array_subscripts:
"[" subscript { "," subscript } "]"
subscript:
":" | expression
comment:
string_comment [ annotation_comment ]
string_comment:
[ STRING { "+" STRING } ]
annotation_comment:
annotation class_modification
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
The basic concept to count unknowns and equations.
Restrictions for model and block classes are present, in order that missing or too many equations can be detected and localized by a Modelica translator before using the respective model or block class.
partial model BaseCorrelation input Real x; Real y; end BaseCorrelation; model SpecialCorrelation // correct in Modelica 2.2 and 3.0 extends BaseCorrelation(x=2); equation y=2/x; end SpecialCorrelation; model UseCorrelation // correct according to Modelica 2.2 // not valid according to Modelica 3.0 replaceable model Correlation=BaseCorrelation; Correlation correlation; equation correlation.y=time; end UseCorrelation; model Broken // after redeclaration, there is 1 equation too much in Modelica 2.2 UseCorrelation example(redeclare Correlation=SpecialCorrelation); end Broken;
In this case one can argue that both UseCorrelation (adding an acausal equation) and SpecialCorrelation (adding a default to an input) are correct, but still when combined they lead to a model with too many equations - and it is not possible to determine which model is incorrect without strict rules. In Modelica 2.2, model Broken will work with some models. However, by just redeclaring it to model SpecialCorrelation, an error will occur and it will be very difficult in a larger model to figure out the source of this error. In Modelica 3.0, model UseCorrelation is no longer allowed and the translator will give an error. In fact, it is guaranteed that a redeclaration cannot lead to an unbalanced model any more.
The restrictions below apply after flattening " i.e., inherited components are included " possibly modified.
Definition 1: Local Number of Unknowns
The local number of unknowns of a model or block class is the sum based on the components:
Definition 2: Local Equation Size
The local equation size of a model or block class is the sum of the following numbers:
Here "u" and "u2" are top-level inputs and not connectors. The variable u2 has a binding equation, but u does not have a binding equation. In the equation count, it is assumed that an equation for u is supplied when using the model.]model M input Real u; input Real u2=2; end M;
Definition 3: Locally Balanced
A model or block class is "locally balanced" if the "local number of unknowns" is identical to the "local equation size" for all legal values of constants and parameters [respecting final bindings and min/max-restrictions. A tool shall verify the "locally balanced" property for the actual values of parameters and constants in the simulation model. It is a quality of implementation for a tool to verify this property in general, due to arrays of (locally) undefined sizes, conditional declarations, for loops, etc.].
Definition 4: Globally Balanced
Similarly as locally balanced, but including all unknowns and equations from all components. The global number of unknowns is computed by expanding all unknowns (i.e., excluding parameters and constants) into a set of scalars of primitive types. This should match the global equation size defined as:
The following restrictions hold:
Based on these restrictions, the following strong guarantee can be given for simulation models and blocks:
Proposition 1: All simulation models and blocks are globally balanced.
[Therefore the number of unknowns equal to the number of equations of a simulation model or block, provided that every used non-partial model or block class is locally balanced.]
Example 1: connector Pin Real v; flow Real i; end Pin; model Capacitor parameter Real C; Pin p, n; Real u; equation 0 = p.i + n.i; u = p.v - n.v; C*der(u) = p.i; end Capacitor;
Model Capacitor is a locally balanced model according to the following analysis:
Locally unknown variables: p.i, p.v, n.i, n.v, u Local equations: 0 = p.i + n.i; u = p.v - n.v; C*der(u) = p.i; and 2 equations corresponding to the 2 flow-variables p.i and n.i.
These are 5 equations in 5 unknowns (locally balanced model). A more detailed analysis would reveal that this is structurally non-singular, i.e., that the hybrid DAE will not contain a singularity independent of actual values. If the equation "u = p.v - n.v" would be missing in the Capacitor model, there would be 4 equations in 5 unknowns and the model would be locally unbalanced and thus simulation models in which this model is used would be usually structurally singular and thus not solvable. If the equation "u = p.v - n.v" would be replaced by the equation "u = 0" and the equation C*der(u) = p.i would be replaced by the equation "C*der(u) = 0", there would be 5 equations in 5 unknowns (locally balanced), but the equations would be singular, regardless of how the equations corresponding to the flow-variables are constructed because the information that "u" is constant is given twice in a slightly different form.
Example 2: connector Pin Real v; flow Real i; end Pin; partial model TwoPin Pin p,n; end TwoPin; model Capacitor parameter Real C; extends TwoPin; Real u; equation 0 = p.i + n.i; u = p.v " n.v; C*der(u) = p.i; end Capacitor; model Circuit extends TwoPin; replaceable TwoPin t; Capacitor c(C=12); equation connect(p, t.p); connect(t.n, c.p); connect(c.n, n); end Circuit;
Since t is partial we cannot check whether this is a globally balanced model, but we can check that Circuit is locally balanced. Counting on model Circuit results in the following balance sheet:
Locally unknown variables (8): p.i, p.v, n.i, n.v, and 2 flow variables for t (t.p.i, t.n.i) and 2 flow variable for c (c.p.i, c.n.i). Local equations: p.v = t.p.v; 0 = p.i - t.p.i; c.p.v = load.n.v; 0 = c.p.i+load.n.i; n.v = c.n.v; 0 = n.i - c.n.i; and 2 equation corresponding to the flow variables p.i, n.i
In total we have 8 scalar unknowns and 8 scalar equations, i.e., a locally balanced model (and this feature holds for any models used for the replaceable component "t"). Some more analysis reveals that this local set of equations and unknowns is structurally non-singular. However, this does not provide any guarantees for the global set of equations, and specific combinations of models that are "locally non-singular" may lead to a globally non-singular model.]
Example 3: import Modelica.Units.SI; partial model BaseProperties "Interface of medium model for all type of media" parameter Boolean preferredMediumStates=false; constant Integer nXi "Number of independent mass fractions"; InputAbsolutePressure p; InputSpecificEnthalpy h; InputMassFraction Xi[nXi]; SI.Temperature T; SI.Density d; SI.SpecificInternalEnergy u; connector InputAbsolutePressure = input SI.AbsolutePressure; connector InputSpecificEnthalpy = input SI.SpecificEnthalpy; connector InputMassFraction = input SI.MassFraction; end BaseProperties;
The use of connector here is a special design pattern. The variables p, h, Xi are marked as input to get correct equation count. Since they are connectors they should neither be given binding equations in derived classes nor when using the model. The design pattern is to give textual equations for them (as below); using connect-statements for these connectors would be possible (and would work) but is not part of the design. This partial model defines that T,d,u can be computed from the medium model, provided p,h,Xi are given. Every medium with one or multiple substances and one or multiple phases, including incompressible media, has the property that T,d,u can be computed from p,h,Xi. A particular medium may have different "independent variables" from which all other intrinsic thermodynamic variables can be recursively computed. For example, a simple air model could be defined as:
model SimpleAir "Medium model of simple air. Independent variables: p,T" extends BaseProperties(nXi = 0, p(stateSelect = if preferredMediumStates then StateSelect.prefer else StateSelect.default), T(stateSelect = if preferredMediumStates then StateSelect.prefer else StateSelect.default)); constant SI.SpecificHeatCapacity R_s = 287; constant SI.SpecificHeatCapacity cp = 1005.45; constant SI.Temperature T0 = 298.15 equation d = p/(R_s*T); h = cp*(T-T0); u = h - p/d; end SimpleAir;
The local number of unknowns in model SimpleAir (after flattening) is:
The local equation size is:
Therefore, the model is locally balanced. The generic medium model BaseProperties is used as a replaceable model in different components, like a dynamic volume or a fixed boundary condition:
import Modelica.Units.SI; connector FluidPort replaceable model Medium = BaseProperties; SI.AbsolutePressure p; flow SI.MassFlowRate m_flow; SI.SpecificEnthalpy h; flow SI.EnthalpyFlowRate H_flow; SI.MassFraction Xi [Medium.nXi] "Independent mixture mass fractions"; flow SI.MassFlowRate mXi_flow[Medium.nXi] "Independent substance mass flow rates"; end FluidPort; model DynamicVolume parameter SI.Volume V; replaceable model Medium = BaseProperties; FluidPort port(redeclare model Medium = Medium); Medium medium(preferredMediumStates=true); // No modifier for p,h,Xi SI.InternalEnergy U; SI.Mass M; SI.Mass MXi[medium.nXi]; equation U = medium.u*M; M = medium.d*V; MXi = medium.Xi*M; der(U) = port.H_flow; // Energy balance der(M) = port.m_flow; // Mass balance der(MXi) = port.mXi_flow; // Substance mass balance // Equations binding to medium (inputs) medium.p = port.p; medium.h = port.h; medium.Xi = port.Xi; end DynamicVolume;
The local number of unknowns of DynamicVolume is:
resulting in 8+4*nXi unknowns; the local equation size is
Therefore, DynamicVolume is a locally balanced model. Note, when the DynamicVolume is used and the Medium model is redeclared to "SimpleAir", then a tool will try to select p,T as states, since these variables have StateSelect.prefer in the SimpleAir model (this means that the default states U,M are derived quantities). If this state selection is performed, all intrinsic medium variables are computed from medium.p and medium.T, although p and h are the input arguments to the medium model. This demonstrates that in Modelica input/output does not define the computational causality. Instead, it defines that equations have to be provided here for p,h,Xi, in order that the equation count is correct. The actual computational causality can be different as it is demonstrated with the SimpleAir model.
model FixedBoundary_pTX parameter SI.AbsolutePressure p "Predefined boundary pressure"; parameter SI.Temperature T "Predefined boundary temperature"; parameter SI.MassFraction Xi[medium.nXi] "Predefined boundary mass fraction"; replaceable model Medium = BaseProperties; FluidPort port(redeclare model Medium = Medium); Medium medium; equation port.p = p; port.H_flow = semiLinear(port.m_flow, port.h , medium.h); port.MXi_flow = semiLinear(port.m_flow, port.Xi, medium.Xi); // Equations binding to medium (note: T is not an input). medium.p = p; medium.T = T; medium.Xi = Xi; end FixedBoundary_pTX;
The number of local variables in FixedBoundary_pTX is:
resulting in 6+3*nXi unknowns, while the local equation size is
Therefore, FixedBoundary_pTX is a locally balanced model. The predefined boundary variables p and Xi are provided via equations to the input arguments medium.p and medium.Xi, in addition there is an equation for T in the same way " even though T is not an input. Depending on the flow direction, either the specific enthalpy in the port (port.h) or h is used to compute the enthalpy flow rate H_flow. "h" is provided as binding equation to the medium. With the equation "medium.T = T", the specific enthalpy "h" of the reservoir is indirectly computed via the medium equations. Again, this demonstrates, that an "input" just defines the number of equations have to be provided, but that it not necessarily defines the computational causality.
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Break lookup in hierarchy
encapsulated model Test import Modelica.Mechanics.Rotational; Rotational.Components.Inertia inertia; // lookup successful Modelica.Mechanics.Translational.SlidingMass slidingMass; // lookup fails equation ... end Test;
See section on class_definition
in the Modelica Grammar.
When an element, equation or algorithm is instantiated, any name is looked up sequentially in each member of the ordered set of parents until a match is found or a parent is encapsulated. In the latter case the lookup stops except for the predefined types, functions and operators defined in this specification. For these cases the lookup continues in the global scope, where they are defined. [E.g., abs is searched upwards in the hierarchy as usual. If an encapsulated boundary is reached, abs is searched in the global scope instead. The operator abs cannot be redefined in the global scope, because an existing class cannot be redefined at the same level.]
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Inheritance from base class
class A parameter Real a, b; end A; class B extends A(b=2); end B; class C extends B(a=1); end C;
From the example above we get the following instantiated class:
class Cinstance parameter Real a=1; parameter Real b=2; end Cinstance;
The ordering of the merging rules ensures that, given classes A and B defined above,
class C2 B bcomp(b=3); end C2;
yields an instance with bcomp.b=3
, which overrides b=2
.
See section on extends_clause
in the Modelica Grammar.
The name of the base class is looked up in the partially instantiated parent of the extends clause. The found base class is instantiated with a new environment and the partially instantiated parent of the extends clause. The new environment is the result of merging
in that order.
The elements of the instantiated base class become elements of the instantiated parent class.
The declaration elements of the instantiated base class shall either
Otherwise the model is incorrect.
Equations of the instantiated base class that are syntactically equivalent to equations in the instantiated parent class are discarded. [Note: equations that are mathematically equivalent but not syntactically equivalent are not discarded, hence yield an overdetermined system of equations.]
Since specialized classes of different kinds have different properties, only specialized classes that are "in some sense compatible" to each other can be derived from each other via inheritance. The following table shows which kind of specialized class can be used in an extends clause of another kind of specialized class (the "grey" cells mark the few exceptional cases, where a specialized class can be derived from a specialized class of another kind):
Base Class | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Derived Class | package | operator | function | operator function | type | record | operator record | expandable connector | connector | block | model | class |
package | yes | yes | ||||||||||
operator | yes | yes | ||||||||||
function | yes | yes | ||||||||||
operator function |
yes | yes | yes | |||||||||
type | yes | yes | ||||||||||
record | yes | yes | ||||||||||
operator record |
yes | yes | ||||||||||
expandable connector |
yes | yes | ||||||||||
connector | yes | yes | yes | yes | yes | yes | ||||||
block | yes | yes | yes | |||||||||
model | yes | yes | yes | yes | ||||||||
class | yes |
The specialized classes package
, operator
,
function
, type
, record
,
operator record
and expandable connector
can only be derived from their own kind
[(e.g., a package can only be base class for packages.
All other kinds of classes can use the import statement to use the contents
of a package)] and from class
.
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Declare flow (through) variable, which have to sum up to zero in connections
connector Pin Modelica.Units.SI.Voltage v; flow Modelica.Units.SI.Current i; end Pin; model A Pin p; end A; model Composition A a; A b; A c; equation connect(a.p, b.p); connect(a.p, c.p); end Composition;
From the connect statements in model Composition, the following connect equations are derived:
a.p.v = b.p.v; a.p.v = c.p.v; a.p.i + b.p.i + c.p.i = 0;
See section on type_prefix
in the Modelica Grammar.
The flow prefix is used in order to generate equations for through variables, which sum up to zero in connections, whereas variables without the flow prefix are identical in a connection.
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Repeat equations or statements a specific number of times
for clauses are mostly used in algorithm sections, such as
parameter Integer np=10; Real p[np], x, y; algorithm y := p[1]; for i in 2:np loop // i shall not be declared y := y*x + p[i]; end for;
Other forms of the for condition:
for i in 1:10 loop // i takes the values 1,2,3,...,10 for r in 1.0 : 1.5 : 5.5 loop // r takes the values 1.0, 2.5, 4.0, 5.5 for i in {1,3,6,7} loop // i takes the values 1, 3, 6, 7
In equation sections, for clauses are expanded at translation time in order that symbolic transformations can be applied. Typically, a for clause in an equation section is used on component arrays, e.g., to connect elements of an array of components together:
parameter Integer nR=10 "Number of resistances"; Modelica.Electrical.Analog.Basic.Resistor R[nR]; equation for i in 1:nR-1 loop connect(R[i].p R[i+1].n); // 9 connect equations end for;
In equation sections:
for for_indices loop { equation ";" } end for; for_indices : for_index {"," for_index} for_index : IDENT [ in expression ]
In algorithm sections:
for for_indices loop { algorithm ";" } end for; for_indices : for_index {"," for_index} for_index : IDENT [ in expression ]
A clause
for IDENT in expression loop
is one example of a for clause.
The expression of a for clause shall be a vector expression. It is evaluated once for each for clause, and is evaluated in the scope immediately enclosing the for clause. In an equation section, the expression of a for clause shall be a parameter expression (in order that the for clause can be expanded into equations during translation). The loop-variable is in scope inside the loop-construct and shall not be assigned to.
[Example:
The loop-variable may hide other variables as in the following example. Using another name for the loop-variable is, however, strongly recommended.
constant Integer j=4; Real x[j]; equation for j in 1:j loop // The loop-variable j takes the values 1,2,3,4 x[j]=j; // Uses the loop-variable j end for;
]
The notation with several iterators is a shorthand notation for nested for-clauses (or reduction-expressions). For
for-clauses it can be expanded into the usual form by replacing each "," by 'loop for'
and adding extra 'end
for'
. For reduction-expressions it can be expanded into the usual form by replacing each ',' by ') for'
and
prepending the reduction-expression with 'function-name('
.
[Example:
Real x[4,3]; equation for j, i in 1:2 loop // The loop-variable j takes the values 1,2,3,4 (due to use) // The loop-variable i takes the values 1,2 (given range) x[j,i]=j+i; end for;
]
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Declare equations or execute statements conditionally
parameter Boolean linear=true; parameter Boolean quadratic=false; Real x, y; equation if linear then y = x + 1; elseif quadratic then y = x^2 + x + 1; else y = Modelica.Math.sin(x) + 1; end if;
Integer i; Integer sign_of_i=if i<0 then -1 else if i==0 then 0 else 1;
In equation sections:
if expression then { equation ";" } { elseif expression then { equation ";" } } [ else { equation ";" } ] end if
In algorithm sections:
if expression then { algorithm ";" } { elseif expression then { algorithm ";" } } [ else { algorithm ";" } ] end if
The expression of an if and elseif-clause must be scalar Boolean expression. One if-clause, and zero or more elseif-clauses, and an optional else-clause together form a list of branches. One or zero of the bodies of these if-, elseif- and else-clauses is selected, by evaluating the conditions of the if- and elseif-clauses sequentially until a condition that evaluates to true is found. If none of the conditions evaluate to true the body of the else-clause is selected (if an else-clause exists, otherwise no body is selected). In an algorithm section, the selected body is then executed. In an equation section, the equations in the body are seen as equations that must be satisfied. The bodies that are not selected have no effect on that model evaluation.
If clauses in equation sections which do not have exclusively parameter expressions as switching conditions shall have an else clause and each branch shall have the same number of equations. [If this condition is violated, the single assignment rule would not hold, because the number of equations may change during simulation although the number of unknowns remains the same].
An expression
if expression1 then expression2 else expression3
is one example of if-expression. First expression1, which must be Boolean expression, is evaluated. If expression1 is true expression2 is evaluated and is the value of the if-expression, else expression3 is evaluated and is the value of the if-expression. The two expressions, expression2 and expression3, must be type compatible and give the type of the if-expression. If-expressions with elseif are defined by replacing elseif by else if.[Note: elseif is added for symmetry with if-clauses.]
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Import classes
class Lookup import SI = Modelica.Units.SI; // #1 (Try to avoid renaming imports!) import Modelica.Math.*; // #2 (Try to avoid wildcard imports!) import Modelica.Mechanics.Rotational; // #3 import Modelica.Units.SI.{Molality, Molarity}; // #4 SI.Torque torque; // due to #1 (Modelica.Units.SI.Torque) Rotational.Components.Inertia inertia; // due to #3 (Modelica.Mechanics.Rotational.Components.Inertia) Molarity c = 1; // due to #4 (Modelica.Units.SI.Molarity) equation torque = sin(time); // due to #2 (Modelica.Math.sin) ... end Lookup;
See section on import_clause
in the Modelica Grammar.
Using import statements extends the static name lookup to additional import names. The generated import names are:
C
for import A.B.C;
D
for import D = A.B.C;
C
and all other classes in B for import A.B.*;
Especially the renaming and wildcard import statements should be avoided since they might lead to name-lookup conflicts.
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Define causality and/or block diagram connection semantic (depending on context)
connector RealInput = input Real; connector RealOutput = output Real; block Integrator RealInput u; RealOutput y; protected Real x; equation der(x) = u; y = x; end Integrator;
See section on type_prefix
in the Modelica Grammar.
The prefixes input and output have a slightly different semantic meaning depending on the context where they are used:
The output prefix does not have a particular effect in a model or block component and is ignored.block FirstOrder input Real u; ... end FirstOrder; model UseFirstOrder FirstOrder firstOrder(u=time); // binding equation for u ... end UseFirstOrder;
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Define causality and/or block diagram connection semantic (depending on context)
connector RealInput = input Real; connector RealOutput = output Real; block Integrator RealInput u; RealOutput y; protected Real x; equation der(x) = u; y = x; end Integrator;
See section on type_prefix
in the Modelica Grammar.
The prefixes input and output have a slightly different semantic meaning depending on the context where they are used:
The output prefix does not have a particular effect in a model or block component and is ignored.block FirstOrder input Real u; ... end FirstOrder; model UseFirstOrder FirstOrder firstOrder(u=time); // binding equation for u ... end UseFirstOrder;
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Prohibit instantiation of components of the class
partial block PartialBlock input Real u; output Real y; protected Real x; equation x = y; end PartialBlock; block Integrator extends PartialBlock; equation der(x) = u; end Integrator; block Gain extends PartialBlock; parameter k = 1; equation x = k*u; end Gain; model Composition PartialBlock block1; // Illegal Integrator block2; // Legal Gain block3; // Legal end Composition;
See section on class_definition
in the Modelica Grammar.
The keyword partial defines that a class is incomplete and that it cannot be instantiated. For example, defining
PartialBlock block1;
is illegal. A partial class can only be used in an "extends" clause to inherit from it or in a "constrainedby" clause to define the constraints of a replaceable class.
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
The state machines defined in the Modelica Language are based on the synchronous language elements. Note that the state machines defined in the Modelica Standard Library are not based on this.
In this example we will start in increase and increase v until a limit, and then decrease it, and repeat.inner Integer v(start=0); block Increase outer output Integer v; equation v = previous(v) + 2; end Increase; Increase increase; block Decrease outer output Integer v; equation v = previous(v) - 1; end Decrease; Decrease decrease; equation initialState(increase); transition(increase, decrease, v>=6, immediate=false); transition(decrease, increase, v==0, immediate=false);
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Declare stream variable in a connector to describe bi-directional flow of matter
connector FluidPort replaceable package Medium = Modelica.Media.Interfaces.PartialMedium; Medium.AbsolutePressure p "Pressure in connection point"; flow Medium.MassFlowRate m_flow "> 0, if flow into component"; stream Medium.SpecificEnthalpy h_outflow "h close to port if m_flow < 0"; end FluidPort;
FluidPort is a stream connector, because a connector variable has the stream prefix. The Medium definition and the stream variables are associated with the only flow variable (m_flow) that defines a fluid stream. The Medium and the stream variables are transported with this flow variable. The stream variable h_outflow is the stream property inside the component close to the boundary, when fluid flows out of the component into the connection point. The stream properties for the other flow direction can be inquired with the built-in operator 'inStream()'. The value of the stream variable corresponding to the actual flow direction can be inquired through the built-in operator 'actualStream()'.
model IsenthalpicFlow "No energy storage/losses, e.g., pressure drop, valve, ..." replaceable package Medium=Modelica.Media.Interfaces.PartialMedium; FluidPort port_a, port_b: Medium.ThermodynamicState port_a_state_inflow "State at port_a if inflowing"; Medium.ThermodynamicState port_b_state_inflow "State at port_b if inflowing"; equation // Medium states for inflowing fluid port_a_state_inflow = Medium.setState_phX(port_a.p, inStream(port_a.h_outflow)); port_b_state_inflow = Medium.setState_phX(port_b.p, inStream(port_b.h_outflow)); // Mass balance 0 = port_a.m_flow + port_b.m_flow; // Instantaneous propagation of enthalpy flow between the ports with // isenthalpic state transformation (no storage and no loss of energy) port_a.h_outflow = inStream(port_b.h_outflow); port_b.h_outflow = inStream(port_a.h_outflow); // (Regularized) Momentum balance port_a.m_flow = f(port_a.p, port_b.p, Medium.density(port_a_state_inflow), Medium.density(port_b_state_inflow)); end IsenthalpicFlow;
When two or more FluidPort (inside) connectors are connected together, then no connection equations are generated for stream variables. Instead, these equations are constructed by the inStream(..) built-in operator (see example model IsenthalpicFlow) above. If two IsenthalpicFlow components are connected together:
IsenthalpicFlow dp1; IsenthalpicFlow dp2; equation connect(dp1, dp2);
Then, the following connection equations are generated
dp1.p = dp2.p; 0 = dp1.m_flow + dp2.m_flow;
Note, no equation for a stream variable is generated. However, the inStream(..) operators inside the components provide the "ideal mixing" equations:
// within dp1: inStream(dp1.port_b.h_outflow) := dp2.port_a.h_outflow; // within dp2: inStream(dp2.port_a.h_outflow) := dp1.port_b.h_outflow;
See section on type_prefix
in the Modelica Grammar.
A detailed description of the stream keyword and the inStream operator is given in Chapter 15 (Stream Connectors) and Appendix D (Derivation of Stream Equations) of the Modelica 3.4 specification. An overview and a rational is provided in a slide set.
The two basic variable types in a connector potential (or across) variable and flow (or through) variable are not sufficient to describe in a numerically sound way the bi-directional flow of matter with convective transport of specific quantities, such as specific enthalpy and chemical composition. The values of these specific quantities are determined from the upstream side of the flow, i.e., they depend on the flow direction. When using across and through variables, the corresponding models would include nonlinear systems of equations with Boolean unknowns for the flow directions and singularities around zero flow. Such equation systems cannot be solved reliably in general. The model formulations can be simplified when formulating two different balance equations for the two possible flow directions. This is not possible with across and through variables though.
This fundamental problem is addressed in Modelica 3.1 by introducing a third type of connector variable, called stream variable, declared with the prefix stream. A stream variable describes a quantity that is carried by a flow variable, i.e., a purely convective transport phenomenon. The value of the stream variable is the specific property inside the component close to the boundary, assuming that matter flows out of the component into the connection point. In other words, it is the value the carried quantity would have if the fluid was flowing out of the connector, irrespective of the actual flow direction.
The basic idea is sketched at hand of an example: Three connectors c1, c2, c3 with the definition
connector Demo Real p; // potential variable flow Real m_flow; // flow variable stream Real h; // stream variable end Demo;
are connected together with
connect(c1,c2); connect(c1,c3);
then this leads to the following equations:
// Potential variables are identical c1.p = c2.p; c1.p = c3.p; // The sum of the flow variables is zero 0 = c1.m_flow + c2.m_flow + c3.m_flow; /* The sum of the product of flow variables and upstream stream variables is zero (this implicit set of equations is explicitly solved when generating code; the "<undefined>" parts are defined in such a way that inStream(..) is continuous). */ 0 = c1.m_flow*(if c1.m_flow > 0 then h_mix else c1.h) + c2.m_flow*(if c2.m_flow > 0 then h_mix else c2.h) + c3.m_flow*(if c3.m_flow > 0 then h_mix else c3.h); inStream(c1.h) = if c1.m_flow > 0 then h_mix else <undefined>; inStream(c2.h) = if c2.m_flow > 0 then h_mix else <undefined>; inStream(c3.h) = if c3.m_flow > 0 then h_mix else <undefined>;
If at least one variable in a connector has the stream prefix, the connector is called stream connector and the corresponding variable is called stream variable. The following definitions hold:
For further details, see the definition of the 'inStream()' operator.
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Synchronous language elements are added to Modelica as an alternative to normal when-clauses to making modeling of complex sampled systems safer and easier.
In this example dc.xd and dc.ud are Clocked variables, and only defined when the Clock is active (every 3rd second). At time instants where the associated clock is not active, the value of a clocked variable can be inquired by using an explicit cast operator, e.g., hold.// Discrete controller when Clock() then E*dc.xd=A*previous(dc.xd)+B*dc.yd; dc.ud=C*previous(dc.xd)+D*dc.yd; end when; // hold controller output: plant.u=hold(dc.ud); // Plant 0=f(der(plant.x),plant.x,plant.u); plant.y=g(plant.x); // Sample continuous signal dc.yd=sample(plant.y, Clock(3));
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Built-in variable time
encapsulated model SineSource import Modelica.Math.sin; connector OutPort=output Real; OutPort y=sin(time); // Uses the built-in variable time. end SineSource;
time
All declared variables are functions of the independent variable time. Time is a built-in variable available in all classes, which is treated as an input variable. It is implicitly defined as:
input Real time (final quantity = "Time", final unit = "s");
The value of the start attribute of time is set to the time instant at which the simulation is started.
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Activate equations or statements when condition becomes true
equation when x > 2 then y3 = 2*x +y1+y2; // Order of y1 and y3 equations does not matter y1 = sin(x); end when; y2 = sin(y1);
In equation sections:
when expression then { equation ";" } { elsewhen expression then { equation ";" } } end when
In algorithm sections:
when expression then { algorithm ";" } { elsewhen expression then { algorithm ";" } } end when
The expression of a when clause shall be a discrete-time Boolean scalar or vector expression. The equations and algorithm statements within a when clause are activated when the scalar or any one of the elements of the vector expression becomes true. When-clauses in equation sections are allowed, provided the equations within the when-clause have one of the following forms:
A when clause shall not be used within a function class.
[Example:
Algorithms are activated when x becomes > 2:
when x > 2 then y1 := sin(x); y3 := 2*x + y1 + y2; end when;
Algorithms are activated when either x becomes > 2 or sample(0,2) becomes true or x becomes less than 5:
when {x > 2, sample(0,2), x < 5} then y1 := sin(x); y3 := 2*x + y1 + y2; end when;
For when in equation sections the order between the equations does not matter, e.g.,
equation when x > 2 then y3 = 2*x +y1+y2; // Order of y1 and y3 equations does not matter y1 = sin(x); end when; y2 = sin(y1);
The needed restrictions on equations within a when-clause becomes apparent with the following example:
Real x, y; equation x + y = 5; when condition then 2*x + y = 7; // error: not valid Modelica end when;
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; // fine end when;
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.
For when in algorithm sections the order is significant and it is advisable to have only one assignment within the when-clause and instead use several algorithms having when-clauses with identical conditions, e.g.,
algorithm when x > 2 then y1 := sin(x); end when; equation y2 = sin(y1); algorithm when x > 2 then y3 := 2*x + y1 + y2; end when;
Merging the when-clauses can lead to less efficient code and different models with different behaviour depending on the order of the assignment to y1 and y3 in the algorithm.]
A when clause
algorithm when {x>1, ..., y>p} then ... elsewhen x > y.start then ... end when;
is equivalent to the following special if-clause, where Boolean b1[N] and Boolean b2 are necessary because the edge() operator can only be applied to variables
Boolean b1[N](start={x.start>1, ..., y.start>p}); Boolean b2(start=x.start>y.start); algorithm b1:={x>1, ..., y>p}; b2:=x>y.start; if edge(b1[1]) or edge(b1[2]) or ... edge(b1[N]) then ... elseif edge(b2) then ... end if;
with "edge(A)= A and not pre(A)" and the additional guarantee, that the algorithms within this special if clause are only evaluated at event instants.
A when-clause
equation when x>2 then v1 = expr1 ; v2 = expr2 ; end when;
is equivalent to the following special if-expressions
Boolean b(start=x.start>2); equation b = x>2; v1 = if edge(b) then expr1 else pre(v1); v2 = if edge(b) then expr2 else pre(v2);
The start-values of the introduced Boolean variables are defined by the taking the start-value of the when-condition, as above where p is a parameter variable. The start-values of the special functions initial, terminal, and sample is false.
When clauses cannot be nested.
[Example:
The following when clause is invalid:
when x > 2 then when y1 > 3 then y2 = sin(x); end when; end when;
]
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Repeat statements as long as a condition is fulfilled
Integer i; algorithm i := 1; while i < 10 loop i := i + 1; ... end while;
while expression loop { algorithm ";" } end while
The expression of a while clause shall be a scalar Boolean expression. The while-clause corresponds to while-statements in programming languages, and is formally defined as follows
Extends from ModelicaReference.Icons.Information (Icon for general information packages).
Acknowledgements:
Extends from ModelicaReference.Icons.Contact (Icon for contact information).
Automatically generated Thu Oct 1 16:08:42 2020.