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.2 Revision 2 from 30th July 2013. Currently, not the whole Modelica language is documented in ModelicaReference (but a large subset).

Copyright © 2003-2019, 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 |

'stream' | stream |

'time' | time |

'when' | when |

'while' | while |

Contact | Contact |

Icons | Library of icons |

This is the grammar of Modelica 3.2 Revision 2 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.2 Revision 2 specification except for removal of some unnecessary parentheses, grouping of some common terms, and reformatting for easier readability. The following typographic conventions are used:

- Keywords are set in
**boldface**. - Literals other than keywords are "
`quoted-monospaced`" text. - Non-terminals are set in
*italics*, with*blue italics*used for links. - EBNF meta-characters are green.

*stored_definition:*
` `[` `**within**` `[` `*name*` `]` `"`;`"` `]` `{` `[` `**final**` `]` `*class_definition*` `"`;`"` `}

*class_definition:*
` `[` `**encapsulated**` `]` `*class_prefixes*` `*class_specifier*

*class_prefixes:*
` `[` `**partial**` `]
` `(` `**class**` `|` `**model**` `|` `**record**` `|` `**block**` `|` `[` `**expandable**` `]` `**connector**
` `|` `**type**` `|` `**package**` `|` `**function**` `|` `**operator**` `[` `**function**` `|` `**record**` `]` `)

*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*` `*name*` `[` `*array_subscripts*` `]` `[` `*class_modification*` `]` `*comment*
` `|` `*IDENT*` `"`=`"` `**enumeration**` `"`(`"` `(` `[` `*enum_list*` `]` `|` `"`:`"` `)` `"`)`"` `*comment*

*der_class_specifier:*
` `*IDENT*` `"`=`"` `**der**` `"`(`"` `*name*` `"`,`"` `*IDENT*` `{` `"`,`"` `*IDENT*` `}` `"`)`"` `*comment*

*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*` `]` `"`;`"` `]
` `[` `*annotation*` `"`;`"` `]

*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*` `[` `"`.`"` `"`*`"` `|` `"`.*`"` `]` `)` `*comment*

*extends_clause:*
` `**extends**` `*name*` `[` `*class_modification*` `]` `[` `*annotation*` `]

*constraining_clause:*
` `**constrainedby**` `*name*` `[` `*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*
` `|` `*name*` `*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*` `[` `*rel_op*` `*arithmetic_expression*` `]

*rel_op:*
` `"`<`"` `|` `"`<=`"` `|` `"`>`"` `|` `"`>=`"` `|` `"`==`"` `|` `"`<>`"

*arithmetic_expression:*
` `[` `*add_op*` `]` `*term*` `{` `*add_op*` `*term*` `}

*add_op:*
` `"`+`"` `|` `"`-`"` `|` `"`.+`"` `|` `"`.-`"

*term:*
` `*factor*` `{` `*mul_op*` `*factor*` `}

*mul_op:*
` `"`*`"` `|` `"`/`"` `|` `"`.*`"` `|` `"`./`"

*factor:*
` `*primary*` `[` `(` `"`^`"` `|` `"`.^`"` `)` `*primary*` `]

*primary:*
` `*UNSIGNED_NUMBER*
` `|` `*STRING*
` `|` `**false**
` `|` `**true**
` `|` `*component_reference*
` `|` `(` `*name*` `|` `**der**` `|` `**initial**` `)` `*function_call_args*
` `|` `"`(`"` `*output_expression_list*` `"`)`"
` `|` `"`[`"` `*expression_list*` `{` `"`;`"` `*expression_list*` `}` `"`]`"
` `|` `"`{`"` `*function_arguments*` `"`}`"
` `|` `**end**

*name:*
` `[` `"`.`"` `]` `*IDENT*` `{` `"`.`"` `*IDENT*` `}

*component_reference:*
` `[` `"`.`"` `]` `*IDENT*` `[` `*array_subscripts*` `]` `{` `"`.`"` `*IDENT*` `[` `*array_subscripts*` `]` `}

*function_call_args:*
` `"`(`"` `[` `*function_arguments*` `]` `"`)`"

*function_arguments:*
` `*function_argument*` `[` `"`,`"` `*function_arguments*` `|` `**for**` `*for_indices*` `]
` `|` `*named_arguments*

*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*` `]

*string_comment:*
` `[` `*STRING*` `{` `"`+`"` `*STRING*` `}` `]

*annotation:*
` `**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 modelBaseCorrelationinputReal x; Real y;endBaseCorrelation;modelSpecialCorrelation // correct in Modelica 2.2 and 3.0extendsBaseCorrelation(x=2);equationy=2/x;endSpecialCorrelation;modelUseCorrelation // correct according to Modelica 2.2 // not valid according to Modelica 3.0replaceable modelCorrelation=BaseCorrelation; Correlation correlation;equationcorrelation.y=time;endUseCorrelation;modelBroken // after redeclaration, there is 1 equation too much in Modelica 2.2 UseCorrelation example(redeclare Correlation=SpecialCorrelation);endBroken;

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:

- For each declared component of specialized class type (Real, Integer, String, Boolean, enumeration and arrays of those, etc.) or record, not declared as outer, it is the "number of unknown variables" inside it (i.e., excluding parameters and constants and counting the elements after expanding all records and arrays to a set of scalars of primitive types).
- Each declared component of specialized class type or record declared as outer is ignored [i.e., all variables inside the component are treated as known].
- For each declared component of specialized class connector component, it is the "number of unknown variables" inside it (i.e., excluding parameters and constants and counting the elements after expanding all records and arrays to a set of scalars of primitive types).
- For each declared component of specialized class block or model, it is the "sum of the number of inputs and flow variables" in the (top level) public connector components of these components (and counting the elements after expanding all records and arrays to a set of scalars of primitive types).

**Definition 2: Local Equation Size **

The local equation size of a model or block class is the sum of the following numbers:

- The number of equations defined locally (i.e., not in any model or block component), including binding equations, and equations generated from connect-equations. This includes the proper count for when-clauses, and algorithms, and is also used for the flat Hybrid DAE formulation.
- The number of input and flow-variables present in each (top-level) public connector component. [This represents the number of connection equations that will be provided when the class is used.]
- The number of (top level) public input variables that neither are connectors nor have binding equations [i.e., top-level inputs are treated as known variables. This represents the number of binding equations that will be provided when the class is used.].
[To clarify top-level inputs without binding equation (for non-inherited inputs binding equation is identical to declaration equation, but binding equations also include the case where another model extends M and has a modifier on "u" giving the value):
model M input Real u; input Real u2=2; end M;

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.]

**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 number of equations defined (included in any model or block component), including equations generated from connect-equations.
- The number of input and flow-variables present in each (top-level) public connector component.
- The number of (top level) public input variables that neither are connectors nor have binding equations [i.e., top-level inputs are treated as known variables].

The following restrictions hold:

- In a non-partial model or block, all non-connector inputs of model or block components must have binding equations. [E.g., if the model contains a component, firstOrder (of specialized class model) and firstOrder has "input Real u" then there must be a binding equation for firstOrder.u.]
- A component declared with the inner or outer prefix shall not be of a class having top-level public connectors containing inputs.
- Modifiers for components shall only contain redeclarations of replaceable elements and binding equations for parameters, constants (that do not yet have binding equations), inputs and variables having a default binding equation.
- All non-partial model and block classes must be locally balanced [this means that the local number of unknowns equals the local equation size].

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 SI = Modelica.SIunits; 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 = 287; constant SI.SpecificHeatCapacity cp = 1005.45; constant SI.Temperature T0 = 298.15 equation d = p/(R*T); h = cp*(T-T0); u = h " p/d; end SimpleAir;

The local number of unknowns in model SimpleAir (after flattening) is:

- 3 (T, d, u: variables defined in BaseProperties and inherited in SimpleAir), plus
- 2+nXi (p, h, Xi: variables inside connectors defined in BaseProperties and inherited in SimpleAir) resulting in 5+nXi unknowns.

The local equation size is:

- 3 (equations defined in SimpleAir), plus
- 2+nXi (input variables in the connectors inherited from BaseProperties)

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 SI = Modelica.SIunits 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:

- 4+2*nXi (inside the port connector), plus
- 2+nXi (variables U, M and MXi), plus
- 2+nXi (the input variables in the connectors of the medium model)

resulting in 8+4*nXi unknowns; the local equation size is

- 6+3*nXi from the equation section, plus
- 2+nXi flow variables in the port connector.

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:

- 4+2*nXi (inside the port connector), plus
- 2+nXi (the input variables in the connectors of the medium model)

resulting in 6+3*nXi unknowns, while the local equation size is

- 4+2*nXi from the equation section, plus
- 2+nXi flow variables in the port connector.

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 modelTestimportModelica.Mechanics.Rotational; Rotational.Components.Inertia inertia; // lookup successful Modelica.Mechanics.Translational.SlidingMass slidingMass; // lookup failsequation...endTest;

class_definition : [encapsulated] [partial] (class|model|record|block|connector|type|package|function) IDENT class_specifier

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

classAparameterReal a, b;endA;classBextendsA(b=2);endB;classCextendsB(a=1);endC;

From the example above we get the following instantiated class:

classCinstanceparameterReal a=1;parameterReal b=2;endCinstance;

The ordering of the merging rules ensures that, given classes A and B defined above,

classC2 B bcomp(b=3);endC2;

yields an instance with `bcomp.b=3`

, which overrides `b=2`

.

class_definition : [encapsulated] [partial] (class|model|record|block|connector|type|package|function) IDENT class_specifier class_specifier : string_comment compositionendIDENT | "=" base_prefix name [ array_subscripts ] [ class_modification ] comment | "="enumeration"(" ( [enum_list] | ":" ) ")" comment composition : element_list {publicelement_list |protectedelement_list | equation_clause | algorithm_clause } [external[ language_specification ] [ external_function_call ] [ annotation ";" ] [ annotation ";" ] ] element_list : { element ";" | annotation ";" } element : import_clause | extends_clause | [final] [inner|outer] ( ( class_definition | component_clause) |replaceable( class_definition | component_clause) [constraining_clause comment]) extends_clause :extendsname [ class_modification ]

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

- arguments of all parent environments that match names in the instantiated base class
- the optional class modification of the extends clause

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

- not already exist in the partially instantiated parent class
*[i.e., have different names]*. - be exactly identical to any element of the instantiated parent
class with the same name and the same level of protection
(
**public**or**protected**) and same contents. In this case, one of the elements is ignored (since they are identical it does not matter which one).

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 | ||||||||||

exapandable 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

connectorPin Modelica.SIunits.Voltage v;flowModelica.SIunits.Current i;endPin;modelA Pin p;endA;modelComposition A a; A b; A c;equation connect(a.p, b.p);connect(a.p, c.p);endComposition;

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;

class_definition : [encapsulated] [partial] (class|model|record|block|connector|type|package|function) IDENT class_specifier class_specifier : string_comment compositionendIDENT | "=" base_prefix name [ array_subscripts ] [ class_modification ] comment | "="enumeration"(" ( [enum_list] | ":" ) ")" comment base_prefix : type_prefix composition : element_list {publicelement_list |protectedelement_list | equation_clause | algorithm_clause } [external[ language_specification ] [ external_function_call ] [ annotation ";" ] [ annotation ";" ] ] element_list : { element ";" | annotation ";" } element : import_clause | extends_clause | [final] [inner|outer] ( ( class_definition | component_clause) |replaceable( class_definition | component_clause) [constraining_clause comment]) component_clause: type_prefix type_specifier [ array_subscripts ] component_list type_prefix : [flow|stream] [discrete|parameter|constant] [input|output]

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

parameterInteger np=10; Real p[np], x, y;algorithmy := p[1];foriin2:nploop// i shall not be declared y := y*x + p[i];end for;

Other forms of the **for** condition:

foriin1:10loop// i takes the values 1,2,3,...,10forrin1.0 : 1.5 : 5.5loop// r takes the values 1.0, 2.5, 4.0, 5.5foriin{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:

parameterInteger nR=10 "Number of resistances"; Modelica.Electrical.Analog.Basic.Resistor R[nR];equationforiin1:nR-1loopconnect(R[i].p R[i+1].n); // 9 connect equationsend for;

In equation sections:

forfor_indicesloop{ equation ";" }end for; for_indices : for_index {"," for_index} for_index : IDENT [ in expression ]

In algorithm sections:

forfor_indicesloop{ algorithm ";" }end for; for_indices : for_index {"," for_index} for_index : IDENT [ in expression ]

A clause

forIDENTinexpressionloop

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.*

constantInteger j=4; Real x[j];equationforjin1:jloop// The loop-variable j takes the values 1,2,3,4 x[j]=j; // Uses the loop-variable jend 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];equationforj, i in 1:2loop// 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

parameterBoolean linear=true;parameterBoolean quadratic=false; Real x, y;equationiflineartheny = x + 1;elseifquadratictheny = x^2 + x + 1;elsey = Modelica.Math.sin(x) + 1;end if;

Integer i; Integer sign_of_i=ifi<0then-1else ifi==0then0else1;

In equation sections:

ifexpressionthen{ equation ";" } {elseifexpressionthen{ equation ";" } } [else{ equation ";" } ]end if

In algorithm sections:

ifexpressionthen{ algorithm ";" } {elseifexpressionthen{ 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

ifexpression1thenexpression2elseexpression3

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

classLookupimportSI = Modelica.SIunits; // #1importModelica.Math.*; // #2 (Try to avoid wildcard imports, // consider using #1 or #3 instead!)importModelica.Mechanics.Rotational; // #3 SI.Torque torque; // due to #1 (Modelica.SIunits.Torque) Rotational.Components.Inertia inertia; // due to #3 (Modelica.Mechanics.Rotational.Components.Inertia)equationtorque = sin(time); // due to #2 (Modelica.Math.sin) ...endLookup;

class_definition : [encapsulated] [partial] (class|model|record|block|connector|type|package|function) IDENT class_specifier class_specifier : string_comment compositionendIDENT | "=" base_prefix name [ array_subscripts ] [ class_modification ] comment | "="enumeration"(" ( [enum_list] | ":" ) ")" comment composition : element_list {publicelement_list |protectedelement_list | equation_clause | algorithm_clause } [external[ language_specification ] [ external_function_call ] [ annotation ";" ] [ annotation ";" ] ] element_list : { element ";" | annotation ";" } element : import_clause | extends_clause | [final] [inner|outer] ( ( class_definition | component_clause) |replaceable( class_definition | component_clause) [constraining_clause comment]) import_clause :import( IDENT "=" name | name ["." "*"] ) comment

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 last wildcard import statement should be avoided since it 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)

connectorRealInput =inputReal;connectorRealOutput =outputReal;blockIntegrator RealInput u; RealOutput y;protectedReal x;equationder(x) = u; y = x;endIntegrator;

class_definition : [encapsulated] [partial] (class|model|record|block|connector|type|package|function) IDENT class_specifier class_specifier : string_comment compositionendIDENT | "=" base_prefix name [ array_subscripts ] [ class_modification ] comment | "="enumeration"(" ( [enum_list] | ":" ) ")" comment base_prefix : type_prefix composition : element_list {publicelement_list |protectedelement_list | equation_clause | algorithm_clause } [external[ language_specification ] [ external_function_call ] [ annotation ";" ] [ annotation ";" ] ] element_list : { element ";" | annotation ";" } element : import_clause | extends_clause | [final] [inner|outer] ( ( class_definition | component_clause) |replaceable( class_definition | component_clause) [constraining_clause comment]) component_clause: type_prefix type_specifier [ array_subscripts ] component_list type_prefix : [flow] [discrete|parameter|constant] [input|output]

The prefixes **input** and **output** have a slightly different semantic meaning depending on the context where they are used:

- In functions, these prefixes define the computational causality of the
function body, i.e., given the variables declared as input,
the variables declared as output are computed in the function body.

- In simulation models and blocks (i.e., on the top level of a model or
block that shall be simulated), these prefixes define the interaction
with the environment where the simulation model or block is used.
Especially, the input prefix defines that values for such a variable
have to be provided from the simulation environment and the output
prefix defines that the values of the corresponding variable
can be directly utilized in the simulation environment.

- In component models and blocks, the input prefix defines that a
binding equation has to be provided for the corresponding variable
when the component is utilized in order to guarantee a locally
balanced model (i.e., the number of local equations is identical
to the local number of unknowns). Example:
**block**FirstOrder**input**Real u; ...**end**FirstOrder;**model**UseFirstOrder FirstOrder firstOrder(u=time); // binding equation for u ...**end**UseFirstOrder;

- In connectors, prefixes input and output define that the
corresponding connectors can only be connected according
to block diagram semantics (e.g., a connector with an output
variable can only be connected to a connector where the
corresponding variable is declared as input). There is the
restriction that connectors which have at least one variable
declared as input must be externally connected
(in order to get a locally balanced model, where the number
of local unknowns is identical to the number of unknown equations).
Together with the block diagram semantics rule this means,
that such connectors must be connected exactly once externally.

- In records, prefixes input and output are not allowed, since otherwise a record could not be, e.g., passed as input argument to a function.

Extends from ModelicaReference.Icons.Information (Icon for general information packages).

Define causality and/or block diagram connection semantic (depending on context)

connectorRealInput =inputReal;connectorRealOutput =outputReal;blockIntegrator RealInput u; RealOutput y;protectedReal x;equationder(x) = u; y = x;endIntegrator;

class_definition : [encapsulated] [partial] (class|model|record|block|connector|type|package|function) IDENT class_specifier class_specifier : string_comment compositionendIDENT | "=" base_prefix name [ array_subscripts ] [ class_modification ] comment | "="enumeration"(" ( [enum_list] | ":" ) ")" comment base_prefix : type_prefix composition : element_list {publicelement_list |protectedelement_list | equation_clause | algorithm_clause } [external[ language_specification ] [ external_function_call ] [ annotation ";" ] [ annotation ";" ] ] element_list : { element ";" | annotation ";" } element : import_clause | extends_clause | [final] [inner|outer] ( ( class_definition | component_clause) |replaceable( class_definition | component_clause) [constraining_clause comment]) component_clause: type_prefix type_specifier [ array_subscripts ] component_list type_prefix : [flow] [discrete|parameter|constant] [input|output]

The prefixes **input** and **output** have a slightly different semantic meaning depending on the context where they are used:

- In functions, these prefixes define the computational causality of the
function body, i.e., given the variables declared as input,
the variables declared as output are computed in the function body.

- In simulation models and blocks (i.e., on the top level of a model or
block that shall be simulated), these prefixes define the interaction
with the environment where the simulation model or block is used.
Especially, the input prefix defines that values for such a variable
have to be provided from the simulation environment and the output
prefix defines that the values of the corresponding variable
can be directly utilized in the simulation environment.

- In component models and blocks, the input prefix defines that a
binding equation has to be provided for the corresponding variable
when the component is utilized in order to guarantee a locally
balanced model (i.e., the number of local equations is identical
to the local number of unknowns). Example:
**block**FirstOrder**input**Real u; ...**end**FirstOrder;**model**UseFirstOrder FirstOrder firstOrder(u=time); // binding equation for u ...**end**UseFirstOrder;

- In connectors, prefixes input and output define that the
corresponding connectors can only be connected according
to block diagram semantics (e.g., a connector with an output
variable can only be connected to a connector where the
corresponding variable is declared as input). There is the
restriction that connectors which have at least one variable
declared as input must be externally connected
(in order to get a locally balanced model, where the number
of local unknowns is identical to the number of unknown equations).
Together with the block diagram semantics rule this means,
that such connectors must be connected exactly once externally.

- In records, prefixes input and output are not allowed, since otherwise a record could not be, e.g., passed as input argument to a function.

Extends from ModelicaReference.Icons.Information (Icon for general information packages).

Prohibit instantiation of components of the class

partial blockPartialBlockinputReal u;outputReal y;protectedReal x;equationx = y;endPartialBlock;blockIntegratorextendsPartialBlock;equation der(x) = u;endIntegrator;blockGainextendsPartialBlock;parameterk = 1;equationx = k*u;endGain;modelComposition PartialBlock block1; // Illegal Integrator block2; // Legal Gain block3; // LegalendComposition;

class_definition : [encapsulated] [partial] (class|model|record|block|connector|type|package|function) IDENT class_specifier class_specifier : string_comment compositionendIDENT | "=" base_prefix name [ array_subscripts ] [ class_modification ] comment | "="enumeration"(" ( [enum_list] | ":" ) ")" comment

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 "constrained" clause to define the constraints of a replaceable class.

Extends from ModelicaReference.Icons.Information (Icon for general information packages).

Declare stream variable in a connector to describe bi-directional flow of matter

connectorFluidPortreplaceable packageMedium = Modelica.Media.Interfaces.PartialMedium; Medium.AbsolutePressure p "Pressure in connection point";flowMedium.MassFlowRate m_flow "> 0, if flow into component";streamMedium.SpecificEnthalpy h_outflow "h close to port if m_flow < 0";endFluidPort;

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()'.

modelIsenthalpicFlow "No energy storage/losses, e.g., pressure drop, valve, ..."replaceable packageMedium=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));endIsenthalpicFlow;

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;equationconnect(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;

class_definition : [encapsulated] [partial] (class|model|record|block|connector|type|package|function) IDENT class_specifier class_specifier : string_comment compositionendIDENT | "=" base_prefix name [ array_subscripts ] [ class_modification ] comment | "="enumeration"(" ( [enum_list] | ":" ) ")" comment base_prefix : type_prefix composition : element_list {publicelement_list |protectedelement_list | equation_clause | algorithm_clause } [external[ language_specification ] [ external_function_call ] [ annotation ";" ] [ annotation ";" ] ] element_list : { element ";" | annotation ";" } element : import_clause | extends_clause | [final] [inner|outer] ( ( class_definition | component_clause) |replaceable( class_definition | component_clause) [constraining_clause comment]) component_clause: type_prefix type_specifier [ array_subscripts ] component_list type_prefix : [flow|stream] [discrete|parameter|constant] [input|output]

A detailed description of the stream keyword and the inStream operator is given in Chapter 15 and Appendix D of the Modelica Language Specification version 3.2 Revision 1. 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

connectorDemo Real p; // potential variableflowReal m_flow; // flow variablestreamReal h; // stream variableendDemo;

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*(ifc1.m_flow > 0thenh_mixelsec1.h) + c2.m_flow*(ifc2.m_flow > 0thenh_mixelsec2.h) + c3.m_flow*(ifc3.m_flow > 0thenh_mixelsec3.h);inStream(c1.h) =ifc1.m_flow > 0thenh_mixelse<undefined>;inStream(c2.h) =ifc2.m_flow > 0thenh_mixelse<undefined>;inStream(c3.h) =ifc3.m_flow > 0thenh_mixelse<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:

- The stream prefix can only be used in a connector declaration.
- A stream connector must have exactly one scalar variable with the flow prefix.
[
*The idea is that all stream variables of a connector are associated with this flow variable*]. - For every outside connector, one equation is generated for every variable
with the stream prefix [
*to describe the propagation of the stream variable along a model hierarchy*]. For the exact definition, see the end of section 15.2. - For inside connectors, variables with the stream prefix do not lead to connection equations.
- Connection equations with stream variables are generated in a model when using the inStream() operator or the actualStream() operator.

For further details, see the definition of the 'inStream()' operator.

Extends from ModelicaReference.Icons.Information (Icon for general information packages).

Built-in variable time

encapsulated modelSineSourceimportModelica.Math.sin;connectorOutPort=outputReal; OutPort y=sin(time); // Uses the built-in variable time.endSineSource;

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:

inputReal time (finalquantity = "Time",finalunit = "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 whenx > 2theny3 = 2*x +y1+y2; // Order of y1 and y3 equations does not matter y1 = sin(x);end when; y2 = sin(y1);

In equation sections:

whenexpressionthen{ equation ";" } {elsewhenexpressionthen{ equation ";" } }end when

In algorithm sections:

whenexpressionthen{ algorithm ";" } {elsewhenexpressionthen{ 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:

- v = expr;
- (out1, out2, out3, ...) = function_call(in1, in2, ...);
- operators
**assert**(),**terminate**(),**reinit**() **For**and**if**-clause if the equations within the**for**and**if**-clauses satisfy these requirements.- In an equation section, the different branches of when/elsewhen must have the same set of component references on the left-hand side.
- In an equation section, the branches of an if-then-else clause inside when-clauses must have the same set of component references on the left-hand side, unless the if-then-else have exclusively parameter expressions as switching conditions.

A when clause shall not be used within a function class.

*[Example:*

*Algorithms are activated when x becomes > 2:*

whenx > 2theny1 := 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}theny1 := 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 whenx > 2theny3 = 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;equationx + y = 5;whenconditionthen2*x + y = 7; // error: not valid Modelicaend 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;equationx + y = 5;whenconditiontheny = 7 - 2*x; // fineend 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.,*

algorithmwhenx > 2theny1 := sin(x);end when;equationy2 = sin(y1);algorithmwhenx > 2theny3 := 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 ... elsewhenx > y.startthen ... 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);algorithmb1:={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 whenx>2thenv1 = expr1 ; v2 = expr2 ;end when;

is equivalent to the following special if-expressions

Boolean b(start=x.start>2);equationb = x>2; v1 =if edge(b)thenexpr1else pre(v1); v2 =if edge(b)thenexpr2else 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:*

whenx > 2then wheny1 > 3theny2 = 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;algorithmi := 1;whilei < 10loopi := i + 1;... end while;

whileexpressionloop{ 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

- The expression of the while clause is evaluated.
- If the expression of the while-clause is false, the execution continues after the while-clause.
- If the expression of the while-clause is true, the entire body of the while clause is executed (except if a break statement or return statement is executed), and then execution proceeds at step 1.

Extends from ModelicaReference.Icons.Information (Icon for general information packages).

**Library Officers:**- Dietmar Winkler and Hans Olsson

**Acknowledgements:**

- The initial version of ModelicaReference is from Christian Schweiger (DLR) who provided it up to Modelica version 2.2.
- Martin Otter (DLR) updated ModelicaReference for Modelica 3.0.
- Dietmar Winkler (DWE) updated ModelicaReference for Modelica 3.1 and 3.2
- Stefan Vorkoetter (Maplesoft) provided ModelicaReference.ModelicaGrammar for Modelica 3.2.

Extends from ModelicaReference.Icons.Contact (Icon for contact information).

Automatically generated Thu Jan 24 11:19:38 2019.