diff --git a/chapters/functions.tex b/chapters/functions.tex index 87bf5a57b..961f34834 100644 --- a/chapters/functions.tex +++ b/chapters/functions.tex @@ -171,7 +171,7 @@ \section{Function as a Specialized Class}\label{function-as-a-specialized-class} \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. + Components of a function follow special variability rules where the \lstinline!GenerateEvents! annotation plays a central role, see \cref{discrete-time-expressions} for details. \end{itemize} Modelica functions have the following enhancements compared to a general Modelica \lstinline!class!: @@ -1762,6 +1762,75 @@ \section{Function Inlining and Event Generation}\label{function-inlining-and-eve If the function is called in a context where events will not be generated (e.g., inside another function without {\lstinline!GenerateEvents = true!}) no special action is needed. \end{nonnormative} +\begin{example} +\lstinline!GenerateEvents! impacts variability according to \cref{variability-of-expressions}. +The following is an illustration of a trivial case. +\begin{lstlisting}[language=modelica] +function greaterEqual + input Real x1; + input Real x2; + output Boolean b; +algorithm + b := x1 >= x2; + annotation(GenerateEvents=true, LateInline=true); +end greaterEqual; + +function greaterEqualWO + input Real x1; + input Real x2; + output Boolean b; +algorithm + b := x1 >= x2; + annotation(LateInline=true); +end greaterEqualWO; + +model M + Boolean b1 = greaterEqual(time, 1); + Boolean b2 = greaterEqualWO(time, 1) "Illegal"; + Boolean b3 = noEvent(greaterEqual(time, 1)) "Illegal"; + Boolean b4 = greaterEqualWO(if b1 then 2 else 0, 1); + Real z = if greaterEqualWO(time, 1) then 2 else 1; +end M; + +function bad + input Real x1; + output Integer i; +algorithm + i := greaterEqualWO(x1, 1) then 2 else 1; + annotation(GenerateEvents=true, LateInline=true); +end bad; +\end{lstlisting} + +In \lstinline!M!, there will be an event when \lstinline!time! becomes greater or equal to \lstinline!1!, and thus the discrete-time variable \lstinline!b1! can be bound to this function call even though it involves the non-discrete time variable \lstinline!time!. +Both \lstinline!b2! and \lstinline!b3! are illegal, since the right hand sides have non-discrete-time variability. +The variable \lstinline!z! is legal, since a \lstinline!Real! variable can have non-discrete time variability. +The variable \lstinline!b4! is legal, since the function inputs have discrete-time variability. +The function \lstinline!bad! demonstrates that similar restrictions (as for \lstinline!b2! and \lstinline!b3!) apply inside functions with {\lstinline!GenerateEvents = true!}. +\begin{lstlisting}[language=modelica] +function saturatedSquare + input Real x2; + output Real y; +algorithm + if x2 > 1 then + y := 1; + else + y := x2^2; + end if; +end saturatedSquare; + +function isBelowSat + input Real x1, x2; + output Boolean b; +algorithm + b : = x1 < saturatedSquare(x2); + annotation (GenerateEvents=true, LateInline=true); +end isBelowSat; +\end{lstlisting} +The function \lstinline!isBelowSat! demonstrates that it is possible to call functions that do not generate events (like \lstinline!saturatedSquare!) inside functions with {\lstinline!GenerateEvents = true!}. +Combined, the last two examples demonstrate that {\lstinline!GenerateEvents = true!} does not propagate to called functions. + +The annotation \lstinline!LateInline=true! is not needed, but makes the issue more obvious in tools that normally inline function before checking variability. +\end{example} \end{semantics} \end{annotationdefinition} diff --git a/chapters/operatorsandexpressions.tex b/chapters/operatorsandexpressions.tex index 6f55a2efb..d8a9f2c9c 100644 --- a/chapters/operatorsandexpressions.tex +++ b/chapters/operatorsandexpressions.tex @@ -1582,7 +1582,7 @@ \subsection{Evaluable Expressions}\label{evaluable-expressions} \item Evaluable parameter variables, see \cref{component-variability}. \item - Input variables in functions behave as though they were evaluable expressions. + Input variables in functions not having annotation \lstinline!GenerateEvents = true! (\cref{modelica:GenerateEvents}) behave as though they were evaluable expressions. \item Except for the special built-in operators \lstinline!initial!, \lstinline!terminal!, \lstinline!der!, \lstinline!edge!, \lstinline!change!, \lstinline!sample!, and \lstinline!pre!, a function or operator with evaluable subexpressions is an evaluable expression. \item @@ -1593,7 +1593,7 @@ \subsection{Evaluable Expressions}\label{evaluable-expressions} \item \lstinline!cardinality(c)!, see restrictions for use in \cref{cardinality-deprecated}. \item - \lstinline!size(A)! (including \lstinline!size(A, j)! where \lstinline!j! is an evaluable expression) if \lstinline!A! is variable declared in a non-function class. + \lstinline!size(A)! (including \lstinline!size(A, j)! where \lstinline!j! is an evaluable expression) if \lstinline!A! is variable declared in a non-function class). \item \lstinline!Connections.isRoot(A.R)! \item @@ -1644,10 +1644,13 @@ \subsection{Discrete-Time Expressions}\label{discrete-time-expressions} Note that \lstinline!rem! and \lstinline!mod! generate events but are not discrete-time expressions. In other words, relations inside \lstinline!noEvent!, such as \lstinline!noEvent(x>1)!, are not discrete-time expressions. \end{nonnormative} +\item + Unless inside \lstinline!noEvent!: Function calls where the function has annotation \lstinline!GenerateEvents = true! (\cref{modelica:GenerateEvents}), the output does not contain a subtype of \lstinline!Real!, and any non-\lstinline!Real! inputs have discrete-time variability. + For a function call returning multiple return values (see \cref{output-formal-parameters-of-functions}) the variability is decided separately for each output. \item The functions \lstinline!pre!, \lstinline!edge!, and \lstinline!change! result in discrete-time expressions. \item - Expressions in functions behave as though they were discrete-time expressions. + Expressions in functions not having annotation \lstinline!GenerateEvents = true! (\cref{modelica:GenerateEvents}), behave as though they were discrete-time expressions. \end{itemize} Inside an \lstinline!if!-expression, \lstinline!if!-clause, \lstinline!while!-statement or \lstinline!for!-clause, that is controlled by a non-discrete-time (that is continuous-time, but not discrete-time) switching expression and not in the body of a \lstinline!when!-clause, it is not legal to have assignments to discrete-time variables, equations between discrete-time expressions, or real elementary relations/functions that should generate events.