Open modelica-trac-importer opened 6 years ago
Comment by kurzbach on 26 Mar 2013 14:13 UTC From my point of view, event generating functions are another kind of impure functions (as specified in MLS 3.3) with different properties:
they are not pure anymore ( because they have access and may change the simulation state) but also not impure, because they have well known side effects.
they might be also marked as impure, but then they are completely impure and can not generate events anymore (only callable the body of when clauses), so it would be sufficient to have a third alternative to the keywords pure and impure.
might be called anywhere in blocks and models ( it makes no sense, to restrict them to when equations/ algorithms because then they would not generate events)
might be called from other event generating functions only This is the hardest restriction because of the propagation effect, but it is driven from the implementation of passing an additional context argument. Each call of such a function has to have its own unique context ( and has to refer to its parent context to make it globally unique) to be able to identifiy the zero crossing functions belonging to that during runtime.
A possible solution for that would need a gobal accessible context, where a stack (a tree which behaves like a stack to have a permanent storage of call contexts) of call contexts (with ids) is explicitely maintained: every call to an event generating function creates a new frame on the stack (if it already exists in the tree, it is reused). At the end of the call, the current frame is removed from the stack (but kept in the tree). With this implementation the restriction would not be necessary, but having global objects is also a serious restriction /source of problems, especially in parallel computing environments. Further discussion is needed.
it is allowed to apply optimizations on calls to such functions (e.g. removing such calls when not really called) and the functions itself
calling such functions inside of while loops or for loops with unkown iteration number should be forbidden
inside such functions when clauses and calls to pre(*),edge(*),change(*) should also be allowed, to be able to take real benefit from it
Comment by fcasella on 26 Mar 2013 19:20 UTC It is not clear to me how pre() etc. could be handled in this context. For example:
function f
input Real x;
output Real y;
algoritm
y := x;
y := y+3;
if pre(y) < 4 then y :=6 else y:=2 end if;
end f;
what would be the meaning of pre(y)?
More in general, unless we want to define the semantics in terms of inlining, I think we should specify the crossing functions explicitly, because in general it is not easy (or maybe even theoretically impossible) to tell it from the algorithm. For example:
function g
input Real x;
output Real y;
algorithm
y:=if x>0 then x else -1-x;
y:=2*x;
y:=if y<2 then y else 2*y;
end g;
what should be the crossing function in this case?
Comment by otter on 27 Mar 2013 07:43 UTC Replying to [comment:2 fcasella]:
More in general, unless we want to define the semantics in terms of inlining, I think we should specify the crossing functions explicitly, because in general it is not easy (or maybe even theoretically impossible) to tell it from the algorithm. For example:
function g input Real x; output Real y; algorithm y:=if x>0 then x else -1-x; y:=2\*x; y:=if y<2 then y else 2\*y; end g;
what should be the crossing function in this case?
Defining the crossing function by a modeler is very error prone and will lead to a mess (the compiler can do a much more reliable job). Defining the crossing function in the example above by a tool is similar as in a model (positiveCrossing(..) is a tool-specific function that returns false or true depending on the simulation state; e.g. during continuous integration is always returns the value from the last event instant; at an event instant, it returns crossing![..] > 0 with the actual crossing value).
function g input Real x; input Integer id_crossing[2] // hidden argument introduced by translator output Real y; output Real crossing[2]; // hidden argument introduced by translator algorithm crossing[1] := x; y:=if positiveCrossing(id_crossing[1], crossing[1]) then x else -1-x; y:=2*x; crossing[2] := 2 - y; y:=if positiveCrossing(id_crossing[2], crossing[2]) then y else 2*y; end g;
}}}
Comment by fcasella on 27 Mar 2013 13:00 UTC Replying to [comment:3 otter]:
Defining the crossing function by a modeler is very error prone and will lead to a mess (the compiler can do a much more reliable job).
I agree with the principle, if this is indeed possible
Defining the crossing function in the example above by a tool is similar as in a model (positiveCrossing(..) is a tool-specific function that returns false or true depending on the simulation state; e.g. during continuous integration is always returns the value from the last event instant; at an event instant, it returns crossing![..] > 0 with the actual crossing value).
function g input Real x; input Integer id_crossing[2] // hidden argument introduced by translator output Real y; output Real crossing[2]; // hidden argument introduced by translator algorithm crossing[1] := x; y:=if positiveCrossing(id_crossing[1], crossing[1]) then x else -1-x; y:=2\*x; crossing[2] := 2 - y; y:=if positiveCrossing(id_crossing[2], crossing[2]) then y else 2\*y; end g;
As far as I understand, this approach cannot be applied in general. Consider the two following functions:
function h
input Real x;
output Real y;
algorithm
y:=x;
while abs(y)>1 loop
y:=if y>10 then y/4 else y/2;
end while;
end h;
function p
input Real x;
input Integer N;
output Real y;
algorithm
for i in 1:N loop
y:=if y>10 then y/4 else y/2;
end for;
end p;
In both cases, the size of the crossing[] vector can change every time the function is called, and it is even unknown a priori in the case of function h. I understand ODE/DAE solvers with event handling need a fixed number of crossing functions to monitor, which should always be well defined and consistent at each time step - this won't be possible in these cases.
If we want to automatically generate the crossing functions, I guess we need to restrict the algorithm section quite a bit (e.g., no for/while loops).
Comment by kurzbach on 27 Mar 2013 15:15 UTC Replying to [comment:4 fcasella]:
In both cases, the size of the crossing[] vector can change every time the function is called, and it is even unknown a priori in the case of function h. I understand ODE/DAE solvers with event handling need a fixed number of crossing functions to monitor, which should always be well defined and consistent at each time step - this won't be possible in these cases.
I agree.
If we want to automatically generate the crossing functions, I guess we need to restrict the algorithm section quite a bit (e.g., no for/while loops).
And therefore I would not generate any crossing functions inside loops with unknown (during compile time) iteration number, and it should be forbidden to call event generating functions in it. This may change the behavior of such loops in blocks and models, but then it works only ba accident and are not portable. The problem here is, that the change of the iteration number of a loop from a parameter expression to a variable changes the semantics of the whole loop.
Comment by hansolsson on 23 Sep 2013 16:14 UTC Language group: Too much work for 3.3r1.
Reported by fcasella on 13 Mar 2013 22:23 UTC There are cases (e.g. in Modelica.Media) where some functions are known to be discontinuous, potentially causing trouble to the ODE integration algorithms. It would be nice to handle the corresponding zero crossing functions, so that events can be generated, allowing to handle the discontinuity in a clean way.
In Modelica 3.2r2 and 3.3, functions cannot generate events, except when the GenerateEvents = true annotation is set. This is a kind of a hack, because an annotation actually changes the semantics of the model using this function.
A more proper way should be found to handle this case. SimulationX already has some built-in mechanism for this purpose, it could be used as a basis for discussion.
Migrated-From: https://trac.modelica.org/Modelica/ticket/1026