Skip to content

Rational behind sample operator not ending event iteration on "fixed point" #3847

@AnHeuermann

Description

@AnHeuermann

The event iteration of the sample operator (operator 3.23 sample) is different if an additional alias variable is introduced to replace it inside the condition expression of a when-equation.
Only discrete variables changing allow for another event iteration. So a changing expression within a when condition is not triggering another event iteration.

What is the rational behind this behavior?

Example

Consider the following two models SampleEventIterationA and SampleEventIterationB:

model SampleEventIterationA
  Boolean sampleIsActive;
equation
  sampleIsActive = sample(0, 0.1);
  when not sampleIsActive then
    Modelica.Utilities.Streams.print("A: time = " + String(time));
  end when;
  annotation(experiment(StopTime = 0.3, Interval = 0.01));
end SampleEventIterationA;
model SampleEventIterationB
equation
  when not sample(0, 0.1) then
    Modelica.Utilities.Streams.print("B: time = " + String(time));
  end when;
  annotation(experiment(StopTime = 0.3, Interval = 0.01));
end SampleEventIterationB;

My naive expectation would be that both models behave exactly the same and both would output something like:

A: time = 0.1 
A: time = 0.2 
A: time = 0.3

and

B: time = 0.1 
B: time = 0.2 
B: time = 0.3

But according to a comment by @casella

A time event is triggered at time = 0.1 by the sample() operator. The value of sample(0, 0.1) right before the event is false, so not sample(0, 0.1) returns true right before the event. During the first (time) event iteration, sample(0, 0.1) returns true, so not sample(0, 0.1) is false. Thus, the condition of the when clause "becomes false". Since when-equations are activated when their condition "becomes true", this is not activated. No discrete variables change, so z == pre(z) and m == pre(m), hence the event iteration algorithm should exit during the first iteration, without printing anything.

and 3.7.5 Event-Related Operators with Function Syntax

The first value of pre(y) is determined in the initialization phase.
A new event is triggered if there is at least for one variable v such that pre(v) <> v after the active model equations are evaluated at an event instant. In this case the model is at once reevaluated. This evaluation sequence is called event iteration. The integration is restarted once pre(v) == v for all v appearing inside pre(…).

the expression not sample(0, 0.1) is not a variable, so the print for SampleEventIterationB is only performed at the terminal event:

B: time = 0.3

And indeed this is what e.g Dymola is doing.

My preferred behavior

I find it strange that performing another event iteration at the end of a handled event (here the event from sample operator) will change the behavior of the model. In a sense the event iteration is not on a fixed-point solution yet. I would prefer a formulation where performing an additional event iteration never changes the behavior of a model, while it may be a bit inefficient to compute the same values twice.

What are tools doing?

We tested model SampleEventIterationB with:

  • OpenModelica (v1.27.0-dev-165): Prints at simulation time events at t=0.0, 0.1, 0.2, 0.3, but not on terminal event.

    B: time = 0 // Ignore this, it's probably wrong, see https://github.com/modelica/ModelicaSpecification/issues/3843
    B: time = 0.1 
    B: time = 0.2 
    B: time = 0.3
    
  • Dymola (2026x): Only prints at terminal event after the simulation is done:

    B: time = 0.3
    

Further consideration

What about model SampleEventIterationC:

model SampleEventIterationC
equation
  when not sample(0, 0.1) then
    Modelica.Utilities.Streams.print("C: time = " + String(time));
  end when;

  when time >= 0.15 then
    Modelica.Utilities.Streams.print("C: Unrelated event time = " + String(time));
  end when;
  annotation(experiment(StopTime = 0.3, Interval = 0.01));
end SampleEventIterationC;

Here an unrelated (time/state) event at time 0.15 triggers. Does condition not sample(0, 0.1) become true? Clearly sample(0, 0.1) should return false, so not sample(0, 0.1) is now true.


From OpenModelica/OpenModelica#14472.

Off-topic: not sample() is a formulation I would consider confusing and would avoid at all costs, but apparently some users of OpenModelica are using this in Modelica libraries.

Metadata

Metadata

Assignees

No one assigned

    Labels

    tool-issueIssue in tool(s) - not the specification itself

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions