ModelicaSpecification
ModelicaSpecification copied to clipboard
Clocked algorithm variables: Unspecified behavior in case of missing equations
For algorithm sections the Modelica Specification requires in general all variables, which are assigned somewhere in the algorithm section, to be initialized always when the algorithm is called (Modelica specification 3.5, Section 11.1.2). Concretely:
- Continuous signals: Initialise to start value
- Discrete signals: Initialise to pre value
However variables of clocked variability are not listed here.
Note, that clocked variability is different to discrete variability: Modelica specification 3.5, Section 16.8.1:
If not explicitly stated otherwise, an expression with a variability such as continuous-time or discrete-time means that the expression is inside a partition that is not associated to a clock. If an expression is present in a partition that is not a continuous-time partition, it is a clocked expression and has clocked variability.
Natural suggestions for initialization would be the previous value or the start value.
Our Questions:
- Are we right, that the Modelica Specification in fact leaves the initialization of clocked variables during calls to clocked algorithms unspecified?
- If we are wrong:
- What is then the correct understanding of initial values during calls to the clocked algorithm section?
- According to the Modelica Specification, how is a clocked algorithm required to treat variables, which are not assigned during the clocked algorithm (as in examples Model1, Model2, Model3 below).
- If we are right, and the Modelica Specification in fact leaves this unspecified:
- Has this issue stayed unspecified on purpose?
- Is there any intent to close this gap?
- Which choices for the initial values inside a clocked algorithm are allowed? (previous value / start value?)
For the follwing three examples, the behavior of signal ‘internal’ seems not to be specified:
Model1: Missing equations for ‘internal’ after first tick.
model model1
parameter Real p = 5;
Real internal (start = 2);
parameter Real Ts = 0.001;
Clock cl = Clock(Ts);
algorithm
if firstTick(cl) then
internal := 5;
end if;
end model1;
or
Model2: Missing equation for ‘internal’ at first tick.
model model2
parameter Real p = 5;
Real internal (start = 2);
parameter Real Ts = 0.001;
Clock cl = Clock(Ts);
algorithm
if not firstTick(cl) then
internal := 5;
end if;
end model2;
Model3: Missing equations for ‘internal’ at first tick and after time 0.5
model model3
parameter Real p = 5;
Real internal (start = 2);
parameter Real Ts = 0.001;
Clock cl = Clock(Ts);
algorithm
if not firstTick(cl) then
if time < 0.5 then
internal := 5;
end if;
end if;
end model3;
Are we right, that the Modelica Specification in fact leaves the initialization of clocked variables during calls to clocked algorithms unspecified?
I think so, good point.
Has this issue stayed unspecified on purpose?
I think this was probably an oversight. Clocked variable semantics is based on synchronous system theory, which is based on equations, algorithms were probably not considered back then, when Modelica 3.3 was written. Maybe @HildingElmqvist, @MartinOtter and @HansOlsson who worked on the original proposal and its implementation can comment on that.
Clocked variables can describe the behaviour of digital controllers where algorithms are run at each clock tick, so algorithms in clocked models are probably useful. For sure a lot more useful than algorithms for continuous variables, which I find pretty confusing. If algorithms involving continuous variables are allowed, it would be odd not to do so for algorithms including clocked variables.
In this case the obvious semantics is that any clocked variable v is initialized at its previous(v) value, similarly to discrete variables, and we could add this to Section 1.11.2.
You are right, this should be clarified in the spec, something like:
- If a clocked discrete-time variable is not assigned at a clock tick, it is implicitly assigned to its previous value. [Note, at the first clock tick, the previous-value is the start value of the variable.]
Dear all,
thank you very much for your quick response. And we will be glad if this is added to the upcoming version of the specification.
We are as well convinced, that the previous value will be the best choice for this purpose:
- It is inline with the ‘pre’ for continuous time discrete variables,
- for discrete controls, it is usually the expectation of the user, that the variable stays with the previous value, if it is untouched.
Let us also hint to the circumstance, that several Modelica tools behave unconsistently in this situation. (Some using the start value, others using previous value.)
Clocked variables can describe the behaviour of digital controllers where algorithms are run at each clock tick, so algorithms in clocked models are probably useful. For sure a lot more useful than algorithms for continuous variables, which I find pretty confusing. If algorithms involving continuous variables are allowed, it would be odd not to do so for algorithms including clocked variables.
We agree on this. Clocked systems are quite a useful way for modelling discrete controls.
Let us also hint to the circumstance, that several Modelica tools behave unconsistently in this situation. (Some using the start value, others using previous value.)
That's too bad, but consistent with the current status of unspecified behaviour 😄
@HansOlsson I guess this could be processed by the MAP-LANG group without too much effort.
This is a bit more complicated.
If the model is just a normal clocked model I agree that previous(...) seems like the best choice (see also #3014 for the difference to pre(...)).
However, if the model was continuous and is then clocked discretized (see #3091 for a discussion of having better names for that) it becomes less clear. Since the goal is that clocked discretization should be possible for every continuous model (and obviously give a result close to the original), it seems that we should preserve that semantics and in those cases initialize to the start-value. However, I am not sure if there's a simple definition of those cases (as we also want to clock discretization of discrete parts of that model).
Related to that the clarification in #3090 requires some minor changes in model3.
It is also unclear how much this will matter in practice for a continuous variable.
For a discrete variable doing x:=a*x+u; (as a short-hand for x:=a*pre(x)+u;) makes sense, but for a truly continuous equation it doesn't make sense to re-use the previous value as the equation will not converge, and it is more that you can write something like:
Real mySum1=sum(cos(i*time) for i in 0:10);
Real mySum(start=1.0); // Using algorithm to get same result as mySum1
algorithm
for i in 1:10 loop
mySum:=mySum+cos(i*time);
end for;
// The value for i=0 is handled by the start-value of mySum
However, if the model was continuous and is then clocked discretized (see #3091 for a discussion of having better names for that) it becomes less clear. Since the goal is that clocked discretization should be possible for every continuous model (and obviously give a result close to the original), it seems that we should preserve that semantics and in those cases initialize to the start-value.
I agree. I remain with my personal conviction that algorithms in continuous time models are fishy, and that algorithms in continuous time models that do not initialize all their variables explicitly are even more fishy. You can imagin what I think of the case where the latter ones are turned into clocked models, maybe using an implicit integration algorithm that required iterations. My head spins... 😄
Maybe would could at least bar this specific case. Honestly, I can't think of any sensible application of it.
However, I am not sure if there's a simple definition of those cases (as we also want to clock discretization of discrete parts of that model).
And therein lies the rub.
It is also unclear how much this will matter in practice for a continuous variable. For a discrete variable doing
x:=a*x+u;(as a short-hand forx:=a*pre(x)+u;) makes sense, but for a truly continuous equation it doesn't make sense to re-use the previous value as the equation will not converge, and it is more that you can write something like:Real mySum1=sum(cos(i*time) for i in 0:10); Real mySum(start=1.0); // Using algorithm to get same result as mySum1 algorithm for i in 1:10 loop mySum:=mySum+cos(i*time); end for; // The value for i=0 is handled by the start-value of mySum
With my proposal, one would be forced to write
algorithm
mySum := 0;
for i in 1:10 loop
mySum:=mySum+cos(i*time);
end for;
which IMHO is way clearer and less ambiguous than relying on a start value, which is declared elsewhere.
Note that I explicitly did set the start-value of mySum to 1.0 - to skip adding cos(0*time).
That's precisely what I mean, this formulation is fishy 😄
It's a bit like writing
a = ++b + (c = d / b) – 1;
in C. For sure it is legal C code, but why would one want to write something that is deliberately obscure?
For sure it is legal C code, but why would one want to write something that is deliberately obscure?
Code golf
It's a bit like writing
a = ++b + (c = d / b) – 1;in C. For sure it is legal C code, but why would one want to write something that is deliberately obscure?
Such C-code would likely be the result of using macros - especially if the code pre-dates proper inline functions; I've seen similar one. Not very relevant for Modelica.
Yeah, what I mean is that the initialization with the start attribute is a bit tricky and not very easily readable.