-
Notifications
You must be signed in to change notification settings - Fork 41
/
functions.tex
2645 lines (2334 loc) · 110 KB
/
functions.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
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\chapter{Functions}\label{functions}
This chapter describes the Modelica function construct.
\section{Function Declaration}\label{function-declaration}
A Modelica \firstuse{function}\index{function} is a specialized class (\cref{function-as-a-specialized-class}) using the keyword \lstinline!function!.
The body of a Modelica function is an algorithm section that contains procedural algorithmic code to be executed when the function is called, or alternatively an external function specifier (\cref{external-function-interface}).
Formal parameters are specified using the \lstinline!input!\indexinline{input} keyword, whereas results are denoted using the \lstinline!output!\indexinline{output} keyword.
This makes the syntax of function definitions quite close to Modelica class definitions, but using the keyword \lstinline!function! instead of \lstinline!class!.
\begin{nonnormative}
The structure of a typical function declaration is sketched by
the following schematic function example:
% TODO: Can't have angle brackets and \emph in the same mathescape due to LaTeXML issue:
% - https://github.com/brucemiller/LaTeXML/issues/1477
% Once we cut the MathJax dependency, change to single mathescape for better character spacing.
\begin{lstlisting}[language=modelica]
function $\mathit{functionname}$
input TypeI1 in1;
input TypeI2 in2;
input TypeI3 in3 = $\mathit{defaultExpr}_{1}$ "Comment" annotation($\ldots$);
$\ldots$
output TypeO1 out1;
output TypeO2 out2 = $\mathit{defaultExpr}_{2}$;
$\ldots$
protected
$\langle$$\mbox{\emph{local variables}}$$\rangle$
$\ldots$
algorithm
$\langle$$\mbox{\emph{statements}}$$\rangle$
$\ldots$
end $\mathit{functionname}$;
\end{lstlisting}
\end{nonnormative}
Optional explicit default values can be associated with any input or output formal parameter through binding equations. Comment strings
and annotations can be given for any formal parameter declaration, as usual in Modelica declarations.
\begin{nonnormative}
Explicit default values are shown for the third input parameter and the second output parameter in the example above.
\end{nonnormative}
\begin{nonnormative}
All internal parts of a function are optional; i.e., the following is also a legal function:
\begin{lstlisting}[language=modelica]
function $\mathit{functionname}$
end $\mathit{functionname}$;
\end{lstlisting}
\end{nonnormative}
\subsection{Ordering of Formal Parameters}\label{ordering-of-formal-parameters}
The relative ordering between input formal parameter declarations is
significant since that determines the matching between actual arguments
and formal parameters at function calls with positional parameter
passing. Likewise, the relative ordering between the declarations of the
outputs is significant since that determines the matching with receiving
variables at function calls of functions with multiple results. However,
the declarations of the inputs and outputs can be intermixed as long as
these internal orderings are preserved.
\begin{nonnormative}
Mixing declarations in this way is not recommended, however, since it makes the code hard to read.
\end{nonnormative}
\begin{example}
\begin{lstlisting}[language=modelica]
function $\mathit{functionname}$
output TypeO1 out1; // Intermixed declarations of inputs and outputs
input TypeI1 in1; // not recommended since code becomes hard to read
input TypeI2 in2;
$\ldots$
output TypeO2 out2;
input TypeI3 in3;
$\ldots$
end $\mathit{functionname}$;
\end{lstlisting}
\end{example}
\subsection{Function return-statements}\label{function-return-statements}
The return-statement\indexinline{return} terminates the current function call, see \cref{function-call}.
It can only be used in an algorithm section of a function.
It has the following form:
\begin{lstlisting}[language=modelica]
return;
\end{lstlisting}
\begin{example}
(Note that this could alternatively use \lstinline!break!:)
\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
for i in 1:size(x,1) loop
if x[i] == val then
index := i;
return;
end if;
end for;
index := 0;
return;
end findValue;
\end{lstlisting}
\end{example}
\subsection{Inheritance of Functions}\label{inheritance-of-functions}
It is allowed for a function to inherit and/or modify another function
following the usual rules for inheritance of classes (\cref{inheritance-modification-and-redeclaration}).
\begin{nonnormative}
For example, it is possible to modify and extend a \lstinline!function! class to add default values for input variables.
\end{nonnormative}
\section{Function as a Specialized Class}\label{function-as-a-specialized-class}
The function concept in Modelica is a specialized class (\cref{specialized-classes}).
\begin{nonnormative}
The syntax and semantics of a function have many similarities to those of the \lstinline!block! specialized class. A function has many of the properties
of a general class, e.g.\ being able to inherit other functions, or to redeclare or modify elements of a function declaration.
\end{nonnormative}
Modelica functions have the following restrictions compared to a general
Modelica \lstinline!class!:
\begin{itemize}
\item
Only input and output formal parameters are allowed in the function's public variable section.
\item
Input formal parameters are read-only after being bound to the actual
arguments or default values, i.e., they shall not be assigned values in
the body of the function.
\item
A function shall \emph{not be used in connections}, shall not have
\emph{equations}, shall not have \emph{initial algorithms}.
\item
A function can have at most \emph{one algorithm} section or \emph{one
external function interface} (not both), which, if present, is the
body of the function.
\item
A function may only contain components of the specialized classes \lstinline!type!, \lstinline!record!, \lstinline!operator record!, and \lstinline!function!; and it must not contain, e.g., \lstinline!model!, \lstinline!block!, \lstinline!operator! or \lstinline!connector! components.
\item
A function may not contain components of type \lstinline!Clock!.
\item
The elements of a function shall not have prefixes \lstinline!inner!, or \lstinline!outer!.
\item
A function may have zero or one external function interface, which, if
present, is the external definition of the function.
\item
For a function to be called in a simulation model, the function shall
not be partial, and the output variables must be assigned inside the
function either in binding equations or in an algorithm section,
or have an external function interface as its body, or be defined as a
function partial derivative. The output variables of a function should
be computed.
\begin{nonnormative}
It is a quality of implementation how much analysis a tool performs in order to determine if the output variables are computed.
\end{nonnormative}
A function \emph{cannot contain} calls to the Modelica \emph{built-in operators} \lstinline!der!, \lstinline!initial!, \lstinline!terminal!, \lstinline!sample!, \lstinline!pre!, \lstinline!edge!, \lstinline!change!, \lstinline!reinit!, \lstinline!delay!, \lstinline!cardinality!, \lstinline!inStream!, \lstinline!actualStream!, to the operators of the built-in package \lstinline!Connections!, to the operators defined in \cref{synchronous-language-elements} and \cref{state-machines}, and is not allowed to contain when-statements.
\item
The dimension \emph{sizes} not declared with colon (\lstinline!:!) of each array result or array local variable (i.e., a non-input component) of a function must be either given by the input formal parameters, or given by constant or parameter expressions, or by expressions containing combinations of those (\cref{initialization-and-binding-equations-of-components-in-functions}).
\item
For initialization of local variables of a function see \cref{initialization-and-binding-equations-of-components-in-functions}).
\item
Components of a function will inside the function behave as though
they had discrete-time variability.
\end{itemize}
Modelica functions have the following enhancements compared to a general
Modelica \lstinline!class!:
\begin{itemize}
\item
Functions can be called, \cref{function-call}.
\begin{itemize}
\item
The calls can use a mix of positional and named arguments, see
\cref{positional-or-named-input-arguments-of-functions}.
\item
Instances of functions have a special meaning, see \cref{functional-input-arguments-to-functions}.
\item
The lookup of the \lstinline!function! class to be called is extended, see \cref{composite-name-lookup}.
\end{itemize}
\item
A function can be \emph{recursive}.
\item
A formal parameter or local variable may be initialized through a
\emph{binding} (=) of a default value in its declaration,
see \cref{initialization-and-binding-equations-of-components-in-functions}.
Using assignment (:=) is deprecated. If a non-input component in the
function uses a record class that contain one or more binding
equations they are viewed as initialization of those component of the
record component.
\item
A function is dynamically instantiated when it is called rather than
being statically instantiated by an instance declaration, which is the
case for other kinds of classes.
\item
A function may have an external function interface specifier as its
body.
\item
A function may have a \lstinline!return! statement in its algorithm section body.
\item
A function allows dimension sizes declared with colon (\lstinline!:!) to be resized for non-input array variables, see \cref{flexible-array-sizes-and-resizing-of-arrays-in-functions}.
\item
A function may be defined in a short function definition to be a
function partial derivative.
\end{itemize}
\section{Pure Modelica Functions}\label{pure-modelica-functions}
Modelica functions are normally \emph{pure} which makes it easy for
humans to reason about the code since they behave as mathematical
functions, and possible for compilers to optimize.
\begin{itemize}
\item
\emph{Pure} Modelica functions always give the same output values or
errors for the same input values and only the output values influence
the simulation result, i.e.\ is seen as equivalent to a mathematical
map from input values to output values. Some input values may map to
errors. Pure functions are thus allowed to fail by calling \lstinline!assert!, or
\lstinline[language=C]!ModelicaError! in C code, or dividing by zero. Such errors will only be
reported when and if the function is called. \emph{Pure} Modelica
functions are not assumed to be thread-safe.
\item
A Modelica function which does not have the \emph{pure} function
properties is \emph{impure}.
\end{itemize}
The declaration of functions follow these rules:
\begin{itemize}
\item
Functions defined in Modelica (non-external) are \emph{normally} assumed to be pure (the exception is the deprecated case below), if they are impure they shall be marked with the \lstinline!impure! keyword.
They can be explicitly marked as \lstinline!pure!\indexinline{pure}.
\begin{nonnormative}
However, since functions as default are pure it is not recommended to explicitly declare them as \lstinline!pure!.
\end{nonnormative}
\item
External functions must be explicitly declared with \lstinline!pure! or \lstinline!impure!.
\item
If a function is declared as \lstinline!impure! any function extending from it shall be declared as \lstinline!impure!.
\item
A deprecated semantics is that external functions (and functions defined in Modelica directly or indirectly calling them) without \lstinline!pure! or \lstinline!impure! keyword are assumed to be
impure, but without any restriction on calling them. Except for the function \lstinline!Modelica.Utilities.Streams.print!, diagnostics must be given if called in a simulation model.
\end{itemize}
Calls of pure functions used inside expression may be skipped if the
resulting expression will not depend on the possible returned value;
ignoring the possibility of the function generating an error.
A call to a function with no declared outputs is assumed to have desired
side-effects or assertion checks.
\begin{nonnormative}
A tool shall thus not remove such function calls, with exception of non-triggered assert calls. A pure function, used in an expression or used with
a non-empty left hand side, need not be called if the output from the function call do not mathematically influence the simulation result, even if
errors would be generated if it were called.
\end{nonnormative}
\begin{nonnormative}
Comment 1: This property enables writing declarative
specifications using Modelica. It also makes it possible for Modelica
compilers to freely perform algebraic manipulation of expressions
containing function calls while still preserving their semantics. For
example, a tool may use common subexpression elimination to call a pure
function just once, if it is called several times with identical input
arguments. However, since functions may fail we can e.g.\ only move a
common function call from inside a loop to outside the loop if the loop
is run at least once.
\end{nonnormative}
\begin{nonnormative}
Comment 2: The Modelica translator is responsible for
maintaining this property for pure non-external functions. Regarding
external functions, the external function implementor is responsible.
Note that external functions can have side-effects as long as they do
not influence the internal Modelica simulation state, e.g.\ caching
variables for performance or printing trace output to a log file.
\end{nonnormative}
With the prefix keyword \lstinline!impure!\indexinline{impure} it is stated that a Modelica function is \emph{impure} and it is only allowed to call such a function from within:
\begin{itemize}
\item
Another function marked with the prefix \lstinline!impure!.
\item
A when-equation.
\item
A when-statement.
\item
\lstinline!pure(impureFunctionCall($\ldots$))! -- which allows calling impure functions in any pure context.
\item
Initial equations and initial algorithms.
\item
Binding equations for components declared as parameter -- which is seen as syntactic sugar for having a parameter with \lstinline!fixed=false! and the binding as an initial equation.
\begin{nonnormative}
Thus, evaluation of the same function call at a later time during simulation is not guaranteed to result in the same value as when the parameter
was initialized, seemingly breaking the declaration equation.
\end{nonnormative}
\item
Binding equations for external objects.
\end{itemize}
For initial equations, initial algorithms, and bindings it is an error
if the function calls are part of systems of equations and thus have to
be called multiple times.
\begin{nonnormative}
A tool is not allowed to perform any optimizations on function
calls to an impure function, e.g., reordering calls from different
statements in an algorithm or common subexpression elimination is not
allowed.
\end{nonnormative}
By \cref{function-compatibility-or-function-subtyping-for-functions}, it follows that an impure function can only be passed as argument to a function formal parameter of impure type.
A function having a formal function parameter that is \lstinline!impure! must be marked \lstinline!pure! or \lstinline!impure!.
\begin{nonnormative}
Comment: The semantics are undefined if the function call of an
impure function is part of an algebraic loop.
\end{nonnormative}
\begin{example}
\begin{lstlisting}[language=modelica]
function evaluateLinear // pure function
input Real a0;
input Real a1;
input Real x;
output Real y;
algorithm
y := a0 + a1*x;
end evaluateLinear;
impure function receiveRealSignal // impure function
input HardwareDriverID id;
output Real y;
external "C"
y = receiveSignal(id);
end receiveRealSignal;
\end{lstlisting}
Examples of allowed optimizations of pure functions:
\begin{lstlisting}[language=modelica]
model M // Assume sin, cos, asin are pure functions with normal derivatives.
input Real x[2];
input Real w;
Real y[2] = [cos(w), sin(w); -sin(w), cos(w)] * x;
Real z[2] = der(y);
Real a = 0 * asin(w);
end M;
\end{lstlisting}
A tool only needs to generate one call of the pure function \lstinline!cos(w)! in the model \lstinline!M! -- a single call used for both the two elements of the matrix, as well as for the derivative
of that matrix. A tool may also skip the possible error for \lstinline!asin(w)! and assume that \lstinline!a! is zero.
Examples of restrictions on optimizing pure functions:
\begin{lstlisting}[language=modelica]
Real x =
if noEvent(abs(x)) < 1 then
asin(x) // Cannot move asin(x) out of if-branch.
else
0;
algorithm
assertCheck(p, T); // Must call function
algorithm
if b then
y := 2 * someOtherFunction(x);
end if;
y := y + asin(x);
y := y + someOtherFunction(x);
// Cannot evaluate someOtherFunction(x) before asin(x) - unless b is true
// The reason is that asin(x) may fail and someOtherFunction may hang,
// and it might be possible to recover from this error.
\end{lstlisting}
\end{example}
\section{Function Call}\label{function-call}
Function classes and record constructors (\cref{record-constructor-functions}) and enumeration type
conversions (\cref{type-conversion-of-integer-to-enumeration-values}) can be called as described in this section.
\subsection{Positional or Named Input Arguments of Functions}\label{positional-or-named-input-arguments-of-functions}
A function call has optional positional arguments followed by zero, one
or more named arguments, such as
\begin{lstlisting}[language=modelica]
f(3.5, 5.76, arg3=5, arg6=8.3);
\end{lstlisting}
The formal syntax of a function call (simplified by removing reduction
expression, \cref{reduction-expressions}):
\begin{lstlisting}[language=grammar]
primary :
component-reference function-call-args
function-call-args :
"(" [ function-arguments ] ")"
function-arguments :
function-argument [ "," function-arguments]
| named-arguments
named-arguments: named-argument [ "," named-arguments ]
named-argument: IDENT "=" function-argument
function-argument : function-partial-application | expression
\end{lstlisting}
The interpretation of a function call is as follows: First, a list of unfilled slots is created for all formal input parameters. If there are $N$ positional arguments, they are placed in the first
$N$ slots, where the order of the parameters is given by the order of the component declarations in the function definition. Next, for each named argument \lstinline!identifier = expression!, the
\lstinline!identifier! is used to determine the corresponding slot. The value of the argument is placed in the slot, filling it (it is an error if this slot is already filled). When all arguments
have been processed, the slots that are still unfilled are filled with the corresponding default value of the function definition. The default values may depend on other inputs (these dependencies
must be acyclical in the function) -- the values for those other inputs will then be substituted into the default values (this process may be repeated if the default value for that input depend on another input). The default values for inputs shall not depend on non-input variables in the function. The list of filled slots is used as the argument list for the call (it is an error if any
unfilled slots still remain).
Special purpose operators with function syntax defined in the
specification shall not be called with named arguments, unless otherwise
noted.
The type of each argument must agree with the type of the corresponding
parameter, except where the standard type coercion, \cref{standard-type-coercion}, can be used to make
the types agree. (See also \cref{scalar-functions-applied-to-array-arguments} on applying scalar functions
to arrays.)
\begin{example}
Assume a function \lstinline!RealToString! is defined as follows to
convert a \lstinline!Real! number to a \lstinline!String!:
\begin{lstlisting}[language=modelica]
function RealToString
input Real number;
input Real precision = 6 "number of significantdigits";
input Real length = 0 "minimum length of field";
output String string "number as string";
$\ldots$
end RealToString;
\end{lstlisting}
Then the following applications are equivalent:
\begin{lstlisting}[language=modelica]
RealToString(2.0);
RealToString(2.0, 6, 0);
RealToString(2.0, 6);
RealToString(2.0, precision=6);
RealToString(2.0, length=0);
RealToString(2.0, 6, precision=6); // error: slot is used twice
\end{lstlisting}
\end{example}
\subsection{Functional Input Arguments to Functions}\label{functional-input-arguments-to-functions}
A functional input argument to a function is an argument of function
type. The declared type of such an input formal parameter in a function
can be the type-specifier of a partial function that has no replaceable
elements. It cannot be the type-specifier of a record or enumeration
(i.e., record constructor functions and enumeration type
conversions are not allowed in this context). Such an input formal
parameter of function type can also have an optional functional default
value.
\begin{example}
\begin{lstlisting}[language=modelica]
function quadrature "Integrate function y=integrand(x) from x1 to x2"
input Real x1;
input Real x2;
input Integrand integrand; // Integrand is a partial function,
see below
// With default: input Integrand integrand =
Modelica.Math.sin;
output Real integral;
algorithm
integral :=(x2-x1)*(integrand(x1) + integrand(x2))/2;
end quadrature;
partial function Integrand
input Real u;
output Real y;
end Integrand;
\end{lstlisting}
\end{example}
A functional argument can be provided in one of the following forms to
be passed to a scalar formal parameter of function type in a function
call:
\begin{enumerate}
\def\labelenumi{\alph{enumi})}
\item
as a function type-specifier (\lstinline!Parabola! example below),
\item
as a function partial application (\cref{function-partial-application} below),
\item
as a function that is a component (i.e., a formal parameter of function type of the enclosing function),
\item
as a function partial application of a function that is a component
(example in \cref{function-partial-application} below).
\end{enumerate}
In all cases the provided function must be function-compatible (\cref{function-compatibility}) with the corresponding formal parameter of function type.
\begin{example}
A function as a positional input argument according to case (a):
\begin{lstlisting}[language=modelica]
function Parabola
extends Integrand;
algorithm
y := x*x;
end Parabola;
area = quadrature(0, 1, Parabola);
\end{lstlisting}
The \lstinline!quadrature2! example below uses a function \lstinline!integrand! that is a
component as input argument according to case (c):
\begin{lstlisting}[language=modelica]
function quadrature2 "Integrate function y=integrand(x) from x1 to x2"
input Real x1;
input Real x2;
input Integrand integrand; // Integrand is a partial function type
output Real integral;
algorithm
integral := quadrature(x1, (x1+x2)/2, integrand)+ quadrature((x1+x2)/2, x2, integrand);
end quadrature2;
\end{lstlisting}
\end{example}
\subsubsection{Function Partial Application}\label{function-partial-application}
A function partial application is similar to a function call with
certain formal parameters bound to expressions, the specific rules are
specified in this section and are not identical to the ones for function
call in \cref{positional-or-named-input-arguments-of-functions}. A function partial application returns a partially
evaluated function that is also a function, with the remaining not bound
formal parameters still present in the same order as in the original
function declaration. A function partial application is specified by the
\lstinline!function! keyword followed by a function call to \lstinline!func_name!
giving named formal parameter associations for the formal parameters to
be bound, e.g.:
\begin{lstlisting}[language=modelica]
function func_name($\ldots$, formal_parameter_name = expr, $\ldots$)
\end{lstlisting}
\begin{nonnormative}
Note that the keyword \lstinline!function! in a function partial
application differentiates the syntax from a normal function call
where some parameters have been left out, and instead supplied via
default values.
\end{nonnormative}
The function created by the function partial application acts as the original function but with the bound formal input parameters(s) removed, i.e., they cannot be supplied arguments at function call.
The binding occurs when the partially evaluated function is created.
A partially evaluated function is function-compatible (\cref{function-compatibility}) with the same function where all bound arguments are removed.
\begin{nonnormative}
Thus, for checking function type compatibility, bound formal parameters are ignored.
\end{nonnormative}
\begin{example}
Function partial application as argument, positional argument passing, according to case (b) above:
\begin{lstlisting}[language=modelica]
model Test
parameter Integer N;
Real area;
algorithm
area := 0;
for i in 1:N loop
area := area + quadrature(0, 1, function Sine(A=2, w=i*time));
end for;
end Test;
function Sine "y = Sine(x,A,w)"
extends Integrand;
input Real A;
input Real w;
algorithm
y:=A*Modelica.Math.sin(w*x);
end Sine;
\end{lstlisting}
Call with function partial application as named input argument:
\begin{lstlisting}[language=modelica]
area := area + quadrature(0, 1, integrand = function Sine(A=2, w=i*time));
\end{lstlisting}
\end{example}
\begin{example}
Function types are matching after removing the bound arguments \lstinline!A! and \lstinline!w! in a function partial
application:
\begin{lstlisting}[language=modelica]
function Sine2 "y = Sine2(A,w,x)"
input Real A;
input Real w;
input Real x; // Note: x is now last in argument list.
output Real y;
algorithm
y:=A*Modelica.Math.sin(w*x);
end Sine2;
area = quadrature(0, 1, integrand = function Sine2(A=2, w=3));
\end{lstlisting}
The partially evaluated \lstinline!Sine2! has only one argument: \lstinline!x! -- and is thus type compatible with \lstinline!Integrand!.
\end{example}
\begin{example}
Function partial application of a function that is a component, according to case (d) above:
\begin{lstlisting}[language=modelica]
partial function SurfaceIntegrand
input Real x;
input Real y;
output Real z;
end SurfaceIntegrand;
function quadratureOnce
input Real x;
input Real y1;
input Real y2;
input SurfaceIntegrand integrand;
output Real z;
algorithm
z := quadrature(y1, y2, function integrand(y=x));
// This is according to case (d) and needs to bind the 2nd argument
end quadratureOnce;
function surfaceQuadrature
input Real x1;
input Real x2;
input Real y1;
input Real y2;
input SurfaceIntegrand integrand;
output Real integral;
algorithm
integral := quadrature(x1, x2,
function quadratureOnce(y1=y1, y2=y2, integrand=integrand));
// Case (b) and (c)
end surfaceQuadrature;
\end{lstlisting}
\end{example}
\subsection{Output Formal Parameters of Functions}\label{output-formal-parameters-of-functions}
A function may have more than one output component, corresponding to
multiple return values. The only way to use more than the first return
value of such a function is to make the function call the right hand
side of an equation or assignment. In this case, the left hand side of
the equation or assignment shall contain a list of component references
within parentheses:
\lstinline!(out1, out2, out3) = f($\ldots$);!
The component references are associated with the output components
according to their position in the list. Thus output component i is set
equal to, or assigned to, component reference i in the list, where the
order of the output components is given by the order of the component
declarations in the function definition. The type of each component
reference in the list must agree with the type of the corresponding
output component.
A function application may be used as expression whose value and type is
given by the value and type of the first output component, if at least
one return result is provided.
It is possible to omit left hand side component references and/or
truncate the left hand side list in order to discard outputs from a
function call.
\begin{nonnormative}
Optimizations to avoid computation of unused output results can
be automatically deduced by an optimizing compiler.
\end{nonnormative}
\begin{example}
Function \lstinline!eigen! to compute eigenvalues and optionally
eigenvectors may be called in the following ways:
\begin{lstlisting}[language=modelica]
ev = eigen(A); // calculate eigenvalues
x = isStable(eigen(A)); // used in an expression
(ev, vr) = eigen(A) // calculate eigenvectors
(ev,vr,vl) = eigen(A) // and also left eigenvectors
(ev,,vl) = eigen(A) // no right eigenvectors
\end{lstlisting}
The function may be defined as:
\begin{lstlisting}[language=modelica]
function eigen "calculate eigenvalues and optionally eigenvectors"
input Real A[:, size(A,1)];
output Real eigenValues[size(A,1),2];
output Real rightEigenVectors[size(A,1),size(A,1)];
output Real leftEigenVectors [size(A,1),size(A,1)];
algorithm
// The output variables are computed separately (and not, e.g., by one
// call of a Fortran function) in order that an optimizing compiler can
// remove unnecessary computations, if one or more output arguments are
// missing
// compute eigenvalues
// compute right eigenvectors using the computed eigenvalues
// compute left eigenvectors using the computed eigenvalues
end eigen;
\end{lstlisting}
\end{example}
The only permissible use of an expression in the form of a list of
expressions in parentheses, is when it is used as the left hand side of
an equation or assignment where the right hand side is an application of
a function.
\begin{example}
The following are illegal:
\begin{lstlisting}[language=modelica]
(x+1, 3.0, z/y) = f(1.0, 2.0); // Not a list of component references.
(x, y, z) + (u, v, w) // Not LHS of suitable eqn/assignment.
\end{lstlisting}
\end{example}
\subsection{Initialization and Binding Equations of Components in Functions}
\label{initialization-and-binding-equations-of-components-in-functions}
\label{initialization-and-declaration-assignments-of-components-in-functions}
Components in a function can be divided into three groups:
\begin{itemize}
\item
Public components which are input formal parameters.
\item
Public components which are output formal parameters.
\item
Protected components which are local variables, parameters, or
constants.
\end{itemize}
When a function is called components of a function do not have start-attributes.
However, a binding equation\index{binding equation!in function} (\lstinline!= expression!) with an expression may be present for a component.
\begin{nonnormative}
\firstuse{Declaration assignments}\index{declaration assignment (deprecated)} of the form \lstinline!:= expression! are deprecated, but otherwise identical to binding equations.
\end{nonnormative}
A binding equation for a non-input component initializes the
component to this \lstinline!expression! at the start of every function invocation
(before executing the algorithm section or calling the external
function). These bindings must be executed in an order where a variable
is not used before its binding equations has been executed; it is
an error if no such order exists (i.e.\ the binding must be acyclic).
% The first sentence below needs clarification: clearly, binding equation can also be used for components outside functions.
Binding equations can only be used for components of a function.
If no binding equation is given for a non-input component the variable is uninitialized (except for record components where modifiers may also initialize that component).
It is an error to use (or return) an uninitialized variable in a function.
Binding equations for input formal parameters are interpreted as default arguments, as described in
\cref{positional-or-named-input-arguments-of-functions}.
\begin{nonnormative}
It is recommended to check for use of uninitialized variables statically -- if this is not possible a warning is recommended
combined with a run-time check.
\end{nonnormative}
\begin{nonnormative}
The properties of components in functions described in this
section are also briefly described in \cref{function-as-a-specialized-class}.
\end{nonnormative}
\subsection{Flexible Array Sizes and Resizing of Arrays in Functions}\label{flexible-array-sizes-and-resizing-of-arrays-in-functions}
\begin{nonnormative}
Flexible setting of array dimension sizes of arrays in
functions is also briefly described in \cref{function-as-a-specialized-class}.
\end{nonnormative}
A dimension size not specified with colon (\lstinline!:!) for a non-input array component of a function must be given by the inputs or be constant.
\begin{example}
\begin{lstlisting}[language=modelica]
function joinThreeVectors
input Real v1[:],v2[:],v3[:];
output Real vres[size(v1,1)+size(v2,1)+size(v3,1)];
algorithm
vres := cat (1,v1,v2,v3);
end joinThreeVectors;
\end{lstlisting}
\end{example}
A non-input array component declared in a function with a dimension size specified by colon (\lstinline!:!) and no binding equation, can change size according to these special rules:
\begin{itemize}
\item
Prior to execution of the function algorithm the dimension size is zero.
\item
The entire array (without any subscripts) may be assigned with a corresponding array with arbitrary dimension size (the array variable is re-sized).
\end{itemize}
These rules also apply if the array component is an element of a record
component in a function.
\begin{example}
A function to collect the positive elements in a vector:
\begin{lstlisting}[language=modelica]
function collectPositive
input Real x[:];
output Real xpos[:];
algorithm
for i in 1 : size(x, 1) loop
if x[i] > 0 then
xpos := cat(1, xpos, x[i:i]);
end if;
end for;
end collectPositive;
\end{lstlisting}
\end{example}
\subsection{Scalar Functions Applied to Array Arguments}\label{scalar-functions-applied-to-array-arguments}
Functions with one scalar return value can be applied to arrays element-wise, e.g.\ if \lstinline!A! is a vector of reals, then \lstinline!sin(A)! is a vector where each element is the result of applying the function \lstinline!sin! to the corresponding element in \lstinline!A!. Only \lstinline!function! classes that are transitively non-replaceable (\cref{transitively-non-replaceable} and \cref{restrictions-on-base-classes-and-constraining-types-to-be-transitively-non-replaceable}) may be called vectorized.
Consider the expression \lstinline!f(arg1, $\ldots$, argn)!, an application of the function \lstinline!f! to the arguments \lstinline!arg1!, \ldots, \lstinline!argn!.
Potential vectorization of this call is defined as follows.
For each passed argument, the type of the argument is checked against the type of the corresponding formal parameter of the function:
\begin{enumerate}
\item\label{argument-type-check-match}
If the types match, nothing is done.
\item
If the types do not match, and a type conversion can be applied, it is
applied. Continue with step~\ref{argument-type-check-match}.
\item
If the types do not match, and no type conversion is applicable, the passed argument type is checked to see if it is an $n$-dimensional array of the formal parameter type. If it is not, the function call is invalid. If it is, we call this a \emph{foreach argument}.
\item
For all foreach arguments, the number and sizes of dimensions must
match. If they do not match, the function call is invalid.
\item
If no foreach argument exists, the function is applied in the normal
fashion, and the result has the type specified by the function
definition.
\item
The result of the function call expression is an $n$-dimensional array \lstinline!e! with the same dimension sizes as the foreach arguments.
Each element \lstinline!e[$i$, $\ldots$, $j$]! is the result of applying \lstinline!f! to arguments constructed from the original arguments in the following way:
\begin{itemize}
\item
If the argument is not a foreach argument, it is used as-is.
\item
If the argument is a foreach argument, the element at index \lstinline![$i$, $\ldots$, $j$]! is used.
\end{itemize}
\end{enumerate}
If more than one argument is an array, all of them have to be the same
size, and they are traversed in parallel.
\begin{example}
\begin{lstlisting}[language=modelica]
sin({a, b, c}) = {sin(a), sin(b), sin(c)} // argument is a vector
sin([a, b, c]) = [sin(a), sin(b), sin(c)] // argument may be a matrix
atan2({a, b, c}, {d, e, f}) = {atan2(a, d), atan2(b, e), atan2(c, f)}
\end{lstlisting}
This works even if the function is declared to take an array as
one of its arguments. If \lstinline!pval! is defined as a function that takes
one argument that is a \lstinline!Real! vector and returns a \lstinline!Real!, then it can
be used with an actual argument which is a two-dimensional array (a
vector of vectors). The result type in this case will be a vector of
\lstinline!Real!.
\begin{lstlisting}[language=modelica]
pval([1,2;3,4]) = [pval([1,2]); pval([3,4])]
sin([1,2;3,4]) = [sin({1,2}); sin({3,4})]
= [sin(1), sin(2); sin(3), sin(4)]
\end{lstlisting}
\begin{lstlisting}[language=modelica]
function Add
input Real e1, e2;
output Real sum1;
algorithm
sum1 := e1 + e2;
end Add;
\end{lstlisting}
\lstinline!Add(1, [1,2,3])! adds one to each of the elements of the second
argument giving the result \lstinline![2,3,4]!. However, it is illegal to
write \lstinline!1 + [1,2,3]!, because the rules for the built-in
operators are more restrictive.
\end{example}
\subsection{Empty Function Calls}\label{empty-function-calls}
An \emph{empty} function call is a call that does not return any results.
\begin{nonnormative}
An empty call is of limited use in Modelica since a function call without results does not contribute to the simulation,
but it is useful to check assertions and in certain cases for desired side-effects, see \cref{pure-modelica-functions}.
\end{nonnormative}
An empty call can occur either as a kind of ``null equation'' or ``null statement''.
\begin{example}
The empty calls to \lstinline!eigen()! are examples of a ``null equation'' and a ``null statement'':
\begin{lstlisting}[language=modelica]
equation
Modelica.Math.Matrices.eigen(A); // Empty function call as an equation
algorithm
Modelica.Math.Matrices.eigen(A); // Empty function call as a statement
\end{lstlisting}
\end{example}
\section{Built-in Functions}\label{built-in-functions}
There are basically four groups of built-in functions in Modelica:
\begin{itemize}
\item
Intrinsic mathematical and conversion functions, see \cref{numeric-functions-and-conversion-functions}.
\item
Derivative and special operators with function syntax,
see \cref{derivative-and-special-purpose-operators-with-function-syntax}.
\item
Event-related operators with function syntax, see \cref{event-related-operators-with-function-syntax}.
\item
Built-in array functions, see \cref{built-in-array-functions}.
Note that when the specification references a function having the name
of a built-in function it references the built-in function, not a
user-defined function having the same name.
\end{itemize}
\section{Record Constructor Functions}\label{record-constructor-functions}
Whenever a record is defined, a record constructor function with the
same name and in the same scope as the record class is implicitly
defined according to the following rules:
% Warning: 'partial flatteing' doesn't seem to be defined. See 'partial instantitation'.
The declaration of the record is partially flattened including inheritance, modifications, redeclarations, and expansion of all names referring to declarations outside of the scope of the record to their fully qualified names.
\begin{nonnormative}
The partial flattening is performed in order to remove potentially conflicting import-clauses in the record constructor function due to flattening the inheritance tree.
\end{nonnormative}
All record elements (i.e., components and local class
definitions) of the partially flattened record declaration are used
as declarations in the record constructor function with the following
exceptions:
\begin{itemize}
\item
Component declarations which do not allow a modification (such
as \lstinline!final parameter Real!) are declared
as protected components in the record constructor function.
\item
Prefixes (\lstinline!constant!, \lstinline!parameter!, \lstinline!final!, \lstinline!discrete!, \ldots) of the remaining
record components are removed.
\item
The prefix \lstinline!input! is added to the public components of the record
constructor function.
\end{itemize}
An instance of the record is declared as output parameter using
a name not appearing in the record, together with a modification. In
the modification, all input parameters are used to set the corresponding
record variables.
A record constructor can only be called if the referenced record class
is found in the global scope, and thus cannot be modified.
\begin{nonnormative}
This allows constructing an instance of a record, with an
optional modification, at all places where a function call is allowed.
Examples:
\begin{lstlisting}[language=modelica]
record Complex "Complex number"
Real re "real part";
Real im "imaginary part";
end Complex;
function add
input Complex u, v;
output Complex w(re=u.re + v.re, im=u.im+v.re);
end add;
Complex c1, c2;
equation
c2 = add(c1, Complex(sin(time), cos(time));
\end{lstlisting}
In the following example, a convenient data sheet library of
components is built up:
\begin{lstlisting}[language=modelica]
package Motors
record MotorData "Data sheet of a motor"
parameter Real inertia;
parameter Real nominalTorque;
parameter Real maxTorque;
parameter Real maxSpeed;
end MotorData;
model Motor "Motor model" // using the generic MotorData
MotorData data;
$\ldots$
equation
$\ldots$
end Motor;
record MotorI123 = MotorData( // data of a specific motor
inertia = 0.001,
nominalTorque = 10,
maxTorque = 20,
maxSpeed = 3600) "Data sheet of motor I123";
record MotorI145 = MotorData( // data of another specific motor
inertia = 0.0015,
nominalTorque = 15,
maxTorque = 22,
maxSpeed = 3600) "Data sheet of motor I145";
end Motors
model Robot
import Motors.*;
Motor motor1(data = MotorI123()); // just refer to data sheet