forked from modelica/ModelicaSpecification
-
Notifications
You must be signed in to change notification settings - Fork 2
/
statements.tex
509 lines (433 loc) · 22.2 KB
/
statements.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
\chapter{Statements and Algorithm Sections}\label{statements-and-algorithm-sections}
Whereas equations are very well suited for physical modeling, there are
situations where computations are more conveniently expressed as
algorithms, i.e., sequences of statements. In this chapter we describe
the algorithmic constructs that are available in Modelica.
Statements are imperative constructs allowed in algorithm sections.
\section{Algorithm Sections}\label{algorithm-sections}
An \firstuse{algorithm section}\index{algorithm!section} is a part of a class definition comprised of the keyword \lstinline!algorithm!\index{algorithm@\robustinline{algorithm}} followed by a sequence of statements.
The formal syntax is as follows:
\begin{lstlisting}[language=grammar]
algorithm-section :
[ initial ] algorithm { statement ";" | annotation ";" }
\end{lstlisting}
Like an equation, an algorithm section relates variables, i.e., constrains the values that these variables can take simultaneously.
In contrast to an equation section, an algorithm section distinguishes inputs from outputs:
An algorithm section specifies how to compute output variables as a function of given input variables.
A Modelica tool may actually invert an algorithm section, i.e., compute inputs from given outputs, e.g., by search (generate and test), or by deriving an inverse algorithm symbolically.
Equation equality \lstinline!=! or any other kind of equation (see \cref{equations}) shall not be used in an algorithm section.
\subsection{Initial Algorithm Sections}\label{initial-algorithm-sections}
See \cref{initialization-initial-equation-and-initial-algorithm} for a description of both initial algorithm sections and
initial equation sections.
\subsection{Execution of an algorithm in a model}\label{execution-of-an-algorithm-in-a-model}
An algorithm section is conceptually a code fragment that remains
together and the statements of an algorithm section are executed in the
order of appearance. Whenever an algorithm section is invoked, all
variables appearing on the left hand side of the assignment operator
\lstinline!:=! are initialized (at least conceptually):
\begin{itemize}
\item
A continuous-time variable is initialized with its start value (i.e.\ the
value of the \lstinline!start! attribute).
\item
A discrete-time variable \lstinline!v! is initialized with \lstinline!pre(v)!.
\item
If at least one element of an array appears on the left hand side of
the assignment operator, then the complete array is initialized in
this algorithm section.
\item
A parameter assigned in an initial algorithm, \cref{initialization-initial-equation-and-initial-algorithm},
is initialized with its start-value (i.e.\ the value of the \lstinline!start! attribute).
\end{itemize}
\begin{nonnormative}
Initialization is performed, in order that an algorithm section
cannot introduce a ``memory'' (except in the case of discrete-time variables assigned in the algorithm), which could invalidate the assumptions of a
numerical integration algorithm. Note, a Modelica tool may change the
evaluation of an algorithm section, provided the result is identical to
the case, as if the above conceptual processing is performed.
An algorithm section is treated as an atomic vector-equation,
which is sorted together with all other equations. For the sorting
process (BLT), every algorithm section with N different left-hand side
variables, is treated as an atomic N-dimensional vector-equation
containing all variables appearing in the algorithm section. This
guarantees that all N equations end up in an algebraic loop and the
statements of the algorithm section remain together.
Example:
\begin{lstlisting}[language=modelica]
model Test // wrong Modelica model (has 4 equations for 2 unknowns)
Real x[2](start={-11, -22});
algorithm // conceptually: x = {1,-22}
x[1] := 1;
algorithm // conceptually: x = {-11,2}
x[2] := 2;
end Test;
\end{lstlisting}
The conceptual part indicate that if the variable is assigned unconditionally
in the algorithm before it is used the initialization can be omitted.
This is usually the case, except for algorithms with when-statements,
and especially for initial algorithms.
\end{nonnormative}
\subsection{Execution of the algorithm in a function}\label{execution-of-the-algorithm-in-a-function}
See \crefnameref{initialization-and-binding-equations-of-components-in-functions}.
\section{Statements}\label{statements}
Statements are imperative constructs allowed in algorithm sections. A
flattened statement is identical to the corresponding nonflattened
statement.
Names in statements are found as follows:
\begin{itemize}
\item
If the name occurs inside an expression: it is first found among the
lexically enclosing reduction functions (see \cref{reduction-functions-and-operators}) in order
starting from the inner-most, and if not found it proceeds as if it
were outside an expression:
\item
Names in a statement are first found among the lexically enclosing
for-statements in order starting from the inner-most, and if not
found:
\item
Names in a statement shall be found by looking up in the partially
flattened enclosing class of the algorithm section.
\end{itemize}
The syntax of statements is as follows:
\begin{lstlisting}[language=grammar]
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
\end{lstlisting}
\subsection{Simple Assignment Statements}\label{simple-assignment-statements}
The syntax of \firstuse{simple assignment statement}\index{assignment statement!simple} is as follows:
\begin{lstlisting}[language=grammar]
component-reference ":=" expression
\end{lstlisting}
The \lstinline[language=grammar]!expression! is evaluated.
The resulting value is stored into the variable denoted by \lstinline[language=grammar]!component-reference!.
The \lstinline!expression! must not have higher variability than the assigned component, see \cref{variability-of-expressions}.
Assignment to array variables with subscripts is described in \cref{array-indexing}.
\subsubsection{Assignments from Called Functions with Multiple Results}\label{assignments-from-called-functions-with-multiple-results}
There is a special form of assignment statement that is used only when
the right-hand side contains a call to a function with multiple results.
The left-hand side contains a parenthesized, comma-separated list of
variables receiving the results from the function call. A function with
\emph{n} results needs \emph{m\textless{}=n} receiving variables on the
left-hand side, and the variables are assigned from left to right.
\begin{lstlisting}[language=modelica]
(out1, out2, out3) := function_name(in1, in2, in3, in4);
\end{lstlisting}
It is possible to omit receiving variables from this list:
\begin{lstlisting}[language=modelica]
(out1, , out3) := function_name(in1, in2, in3, in4);
\end{lstlisting}
\begin{example}
The function \lstinline!f! called below has three results and two inputs:
\begin{lstlisting}[language=modelica]
(a, b, c) := f(1.0, 2.0);
(x[1], x[2], x[1]) := f(3, 4);
\end{lstlisting}
In the second example above \lstinline!x[1]! is assigned twice: first with the first output, and then with the third output. For that case the following will give the same result:
\begin{lstlisting}[language=modelica]
(, x[2], x[1]) := f(3,4);
\end{lstlisting}
\end{example}
The syntax of an assignment statement with a call to a function with
multiple results is as follows:
\begin{lstlisting}[language=grammar]
"(" output-expression-list ")" ":=" component-reference function-call-args
\end{lstlisting}
\begin{nonnormative}
Also see \cref{simple-equality-equations} regarding calling functions with
multiple results within equations.
\end{nonnormative}
\subsubsection{Restrictions on assigned variables}\label{restrictions-on-assigned-variables}
Only components of the specialized classes \lstinline!type!, \lstinline!record!, \lstinline!operator record!, and \lstinline!connector! may appear as left-hand-side in algorithms.
This applies both to simple assignment statements, and the parenthesized, comma-separated list of variables for functions with multiple results.
\subsection{For-statement}\label{for-statement}
The syntax of a for-statement\index{for@\robustinline{for}!statement}\index{loop@\robustinline{loop}!for-statement} is as follows:
\begin{lstlisting}[language=grammar]
for for-indices loop
{ statement ";" }
end for
\end{lstlisting}
For-statements may optionally use several iterators (\lstinline!for-indices!), see
\cref{nested-for-loops-and-reduction-expressions-with-multiple-iterators} for more information:
\begin{lstlisting}[language=grammar]
for-indices:
for-index {"," for-index}
for-index:
IDENT [ in expression ]
\end{lstlisting}
The following is an example of a prefix of a for-statement:
\begin{lstlisting}[language=modelica]
for IDENT in expression loop
\end{lstlisting}
The rules for for-statements are the same as for for-expressions in \cref{explicit-iteration-ranges-of-for-equations} -- except that the \lstinline!expression! of a for-statement is not restricted to a parameter expression.
\begin{example}
\begin{lstlisting}[language=modelica]
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
for i in TwoEnums loop // i takes the values TwoEnums.one, TwoEnums.two
// for TwoEnums = enumeration(one, two)
\end{lstlisting}
The loop-variable may hide other variables as in the following example. Using another name for the loop-variable is, however, strongly recommended.
\begin{lstlisting}[language=modelica]
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;
\end{lstlisting}
\end{example}
\subsubsection{Implicit Iteration Ranges}\label{implicit-iteration-ranges}
An iterator \lstinline!IDENT in range-expr! without the \lstinline!in range-expr! requires that the \lstinline!IDENT! appears as the subscript of one or several subscripted expressions, where the expressions are not part of an array in a component of an expandable connector. The dimension size of the array expression in the indexed position is used to deduce the \lstinline!range-expr! as \lstinline!1:size(array-expression,indexpos)! if the indices are a subtype of \lstinline!Integer!, or as \lstinline!E.e1:E.en! if the indices are of an enumeration type \lstinline!E = enumeration(e1, $\ldots$, en)!, or as \lstinline!false:true! if the indices are of type \lstinline!Boolean!. If it is used to subscript several expressions, their ranges must be identical. The \lstinline!IDENT! may also, inside a reduction-expression, array constructor expression, for-statement, or for-equation, occur freely outside of subscript positions, but only as a reference to the variable \lstinline!IDENT!, and not for deducing ranges.
The \lstinline!IDENT! may also be used as a subscript for an array in a component of an expandable connector
but it is only seen as a reference to the variable \lstinline!IDENT! and cannot be used for deducing ranges.
\begin{example}
\begin{lstlisting}[language=modelica]
Real x[4];
Real xsquared[:] = {x[i] * x[i] for i};
// Same as: {x[i] * x[i] for i in 1 : size(x, 1)}
Real xsquared2[size(x, 1)];
Real xsquared3[size(x, 1)];
equation
for i loop // Same as: for i in 1 : size(x, 1) loop ...
xsquared2[i] = x[i]^2;
end for;
algorithm
for i loop // Same as: for i in 1 : size(x, 1) loop ...
xsquared3[i] := x[i]^2;
end for;
\end{lstlisting}
\begin{lstlisting}[language=modelica]
type FourEnums = enumeration(one, two, three, four);
Real xe[FourEnums] = x;
Real xsquared3[FourEnums] = {xe[i] * xe[i] for i};
Real xsquared4[FourEnums] = {xe[i] * xe[i] for i in FourEnums};
Real xsquared5[FourEnums] = {x[i] * x[i] for i};
\end{lstlisting}
\end{example}
The size of an array -- the iteration range -- is evaluated on entry to the for-loop and the array size shall not change during the execution of the for-loop.
\subsubsection{Types as Iteration Ranges}\label{types-as-iteration-ranges}
The iteration range can be specified as \lstinline!Boolean! or as an enumeration type. This means iteration over the type from min to max, i.e.\ for \lstinline!Boolean! it is the same as \lstinline!false:true! and for an enumeration \lstinline!E! it is the same as \lstinline!E.min:E.max!. This can be used for \lstinline!for! loops and reduction expressions.
\begin{example}
\begin{lstlisting}[language=modelica]
type FourEnums = enumeration(one, two, three, four);
Real xe[FourEnums];
Real xsquared1[FourEnums];
Real xsquared2[FourEnums] = {xe[i] * xe[i] for i in FourEnums};
equation
for i in FourEnums loop
xsquared1[i] = xe[i]^2;
end for;
\end{lstlisting}
\end{example}
\subsubsection{Nested For-Loops and Reduction Expressions with Multiple Iterators}\label{nested-for-loops-and-reduction-expressions-with-multiple-iterators}
The notation with several iterators is a shorthand notation for nested
for-statements or for-equations (or reduction-expressions). For
for-statements or for-equations it can be expanded into the usual form
by replacing each `\lstinline!,!' by ``\lstinline!loop for!'' and adding extra ``\lstinline!end for!''. For
reduction-expressions it can be expanded into the usual form by
replacing each `\lstinline!,!' by ``\lstinline!) for!'' and prepending the reduction-expression
with ``\lstinline!functionName(!''.
\begin{example}
\begin{lstlisting}[language=modelica]
Real x[4,3];
algorithm
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;
\end{lstlisting}
\end{example}
\subsection{While-Statement}\label{while-statement}
The while-statement\index{while@\robustinline{while}!statement}\index{loop@\robustinline{loop}!while-statement} has the following syntax:
\begin{lstlisting}[language=grammar]
while expression loop
{ statement ";" }
end while
\end{lstlisting}
The \lstinline!expression! of a while-statement shall be a scalar \lstinline!Boolean! expression. The while-statement corresponds to while-statements in programming languages, and is formally defined as follows:
\begin{enumerate}
\item The \lstinline!expression! of the while-statement is evaluated.
\item If the \lstinline!expression! of the while-statement is false, the execution
continues after the while-statement.
\item If the \lstinline!expression! of the while-statement is true, the entire body of
the while-statement is executed (except if a break-statement, see
\cref{break-statement}, or a return-statement, see \cref{return-statements}, is executed),
and then execution proceeds at step 1.
\end{enumerate}
\subsection{Break-Statement}\label{break-statement}
The break-statement\index{break@\robustinline{break}} breaks the execution of the innermost while- or for-loop enclosing the break-statement and continues execution after the while- or for-loop.
It can only be used in a while- or for-loop in an algorithm section.
It has the following syntax:
\begin{lstlisting}[language=modelica]
break;
\end{lstlisting}
\begin{example}
(Note that this could alternatively use \lstinline!return!).
\begin{lstlisting}[language=modelica]
function findValue "Returns position of val or 0 if not found"
input Integer x[:];
input Integer val;
output Integer index;
algorithm
index := size(x, 1);
while index >= 1 loop
if x[index] == val then
break;
else
index := index - 1;
end if;
end while;
end findValue;
\end{lstlisting}
\end{example}
\subsection{Return-Statements}\label{return-statements}
Can only be used inside functions, see \cref{function-return-statements}.
\subsection{If-Statement}\label{if-statement}
If-statements\index{if@\robustinline{if}!statement}\index{then@\robustinline{then}!if-statement}\index{else@\robustinline{else}!if-statement}\index{elseif@\robustinline{elseif}!if-statement} have the following syntax:
\begin{lstlisting}[language=grammar]
if expression then
{ statement ";" }
{ elseif expression then
{ statement ";" }
}
[ else
{ statement ";" }
]
end if;
\end{lstlisting}
The \lstinline!expression! of an if- or elseif-clause must be scalar \lstinline!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. The bodies that are not selected have no effect on that model evaluation.
\subsection{When-Statements}\label{when-statements}
A when-statement\index{when@\robustinline{when}!statement}\index{then@\robustinline{then}!when-statement}\index{elsewhen@\robustinline{elsewhen}!when-statement} has the following syntax:
\begin{lstlisting}[language=grammar]
when expression then
{ statement ";" }
{ elsewhen expression then
{ statement ";" } }
end when
\end{lstlisting}
The \lstinline!expression! of a when-statement shall be a discrete-time \lstinline!Boolean! scalar or vector expression.
The statements within a when-statement are known as \emph{instantaneous statements}\index{instantaneous!statement}, and are activated only at the instant when the scalar or any one of the elements of the vector-expression becomes true.
\begin{example}
Algorithms are activated when \lstinline!x! becomes \textgreater{} 2:
\begin{lstlisting}[language=modelica]
when x > 2 then
y1 := sin(x);
y3 := 2*x + y1+y2;
end when;
\end{lstlisting}
The statements inside the when-statement are activated on the positive edge of any of the expressions
\lstinline!x > 2!, \lstinline!sample(0, 2)!, or \lstinline!x < 5!:
\begin{lstlisting}[language=modelica]
when {x > 2, sample(0,2), x < 5} then
y1 := sin(x);
y3 := 2*x + y1+y2;
end when;
\end{lstlisting}
For when-statements in algorithm sections the order is significant
and it is advisable to have only one assignment within the
when-statement and instead use several algorithm sections having
when-statements with identical conditions, e.g.:
\begin{lstlisting}[language=modelica]
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;
\end{lstlisting}
Merging the when-statements can lead to less efficient code and
different models with different behavior depending on the order of the
assignment to \lstinline!y1! and \lstinline!y3! in the algorithm.
\end{example}
\subsubsection{Restrictions on Where a When-statement may occur}\label{restrictions-on-where-a-when-statement-may-occur}
\begin{itemize}
\item
A when-statement shall not be used within a function.
\item
When-statements shall not occur inside initial algorithms.
\item
When-statements cannot be nested.
\item
When-statements shall not occur inside while, if, and for-clauses in
algorithms.
\end{itemize}
\begin{example}
The following nested when-statement is invalid:
\begin{lstlisting}[language=modelica]
when x > 2 then
when y1 > 3 then
y2 := sin(x);
end when;
end when;
\end{lstlisting}
\end{example}
\subsubsection{Restrictions on Statements within When-Statements}\label{restrictions-on-statements-within-when-statements}
\begin{nonnormative}
In contrast to when-equations, \cref{restrictions-on-equations-within-when-equations},
there are no additional restrictions within when-statements:
\begin{itemize}
\item
In algorithms, all assignment statements are already restricted to left-hand-side variables.
\item
If at least one element of an array appears on the left-hand-side of the assignment operator inside
a when-statement, it is as if the entire array appears in the left-hand-side
according to \cref{execution-of-an-algorithm-in-a-model}.
Thus, there is no need to restrict the indices to parameter expressions.
\item
For-clauses and if-clauses are not problematic inside when-statements in algorithms, since
all left-hand-side variables inside when-statements are assigned to their pre-values
before the start of the algorithm, according to \cref{execution-of-an-algorithm-in-a-model}.
\end{itemize}
\end{nonnormative}
\subsubsection{Defining When-Statements by If-Statements}\label{defining-when-statements-by-if-statements}
A when-statement:
\begin{lstlisting}[language=modelica]
algorithm
when {x>1, ..., y>p} then
...
elsewhen x > y.start then
...
end when;
\end{lstlisting}
is similar to the following special if-statement, where \lstinline!Boolean b1[N];! and \lstinline!Boolean b2;! are necessary because \lstinline!edge! can
only be applied to variables
\begin{lstlisting}[language=modelica]
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;
\end{lstlisting}
with \lstinline!edge(A)= A and not pre(A)! and the additional guarantee, that the
statements within this special if-statement are only evaluated at event
instants. The difference compared to the when-statements is that e.g.\ \lstinline!pre! may only be used on continuous-time real variables inside the body
of a when-clause and not inside these if-statements.
\subsection{Special Statements}\label{special-statements}
These special statements have the same form and semantics as the
corresponding equations, apart from the general difference in semantics
between equations and statements.
\subsubsection{Assert Statement}\label{assert-statement}
See \cref{assert}. A failed \lstinline!assert!\index{assert@\robustinline{assert}!statement} stops the execution of the current algorithm.
\subsubsection{Terminate Statement}\label{terminate-statement}
See \cref{terminate}. The \lstinline!terminate!\index{terminate@\robustinline{terminate}!statement} statement shall not be in functions. In an algorithm outside a function it does not stop the execution of the current algorithm.