modelica / ModelicaSpecification

Specification of the Modelica Language
https://specification.modelica.org
Creative Commons Attribution Share Alike 4.0 International
98 stars 42 forks source link

Clocked algorithm variables: Unspecified behavior in case of missing equations #3107

Open d-model opened 2 years ago

d-model commented 2 years ago

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:

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:

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;
casella commented 2 years ago

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.

MartinOtter commented 2 years ago

You are right, this should be clarified in the spec, something like:

d-model commented 2 years ago

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:

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.

casella commented 2 years ago

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.

HansOlsson commented 2 years ago

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
casella commented 2 years ago

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 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

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.

HansOlsson commented 2 years ago

Note that I explicitly did set the start-value of mySum to 1.0 - to skip adding cos(0*time).

casella commented 2 years ago

That's precisely what I mean, this formulation is fishy 😄

casella commented 2 years ago

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?

sjoelund commented 2 years ago

For sure it is legal C code, but why would one want to write something that is deliberately obscure?

Code golf

HansOlsson commented 2 years ago

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.

casella commented 2 years ago

Yeah, what I mean is that the initialization with the start attribute is a bit tricky and not very easily readable.