Opened 4 years ago

Last modified 3 years ago

#6181 new defect

Boolean incorrectly evaluated and asserts, implying negative time?

Reported by: craig.fletcher@… Owned by: Andreas Heuermann
Priority: high Milestone:
Component: Run-time Version: v1.17.0-dev
Keywords: Cc: Karim Adbdelhak

Description (last modified by Per Östlund)

The following asserts time is less than zero. Did not assert in previous versions of OMC

model DebugInitialValue
  
  model BooleanPulse
    input Real width(start=0.5);
    output Boolean y;
  equation
    y = time < width;
  end BooleanPulse;

  class DayNightCycle
    parameter Real earth_day_period=24;
    Real daylight_ratio;
    BooleanPulse daylight(width=daylight_ratio);
  end DayNightCycle;

  parameter Real ratio_start=0;
  Real _ratio;
  DayNightCycle cycle(daylight_ratio=_ratio); //FAILS.  Will work if changed to daylight_ratio=0 here.

algorithm
  _ratio := ratio_start;
  if not initial() then 
    assert(cycle.daylight.y==false,"oops",level=AssertionLevel.warning);
  end if;

end DebugInitialValue;

Change History (13)

comment:1 by Per Östlund, 4 years ago

Component: *unknown*Run-time
Description: modified (diff)
Owner: changed from somebody to Andreas Heuermann

comment:2 by Andreas Heuermann, 4 years ago

The model get's flattened out to:

class DebugInitialValue
  parameter Real ratio_start = 0.0;
  Real _ratio;
  parameter Real cycle.earth_day_period = 24.0;
  Real cycle.daylight_ratio = _ratio;
  Real cycle.daylight.width(start = 0.5) = cycle.daylight_ratio;
  Boolean cycle.daylight.y;
equation
  cycle.daylight.y = time < cycle.daylight.width;
algorithm
  _ratio := ratio_start;
  if not initial() then
    assert(cycle.daylight.y == false, "oops", AssertionLevel.warning);
  end if;
end DebugInitialValue;

and here we can see the dilemma. If we evaluate the algorithm section first cycle.daylight.width is set to the start value and the assert muss trigger.
If we evaluate the equations section first _ratio is not set to _ratio_start.

From the backend we will get this DAE-system:

1/1 (1): algorithm
  _ratio := $START._ratio;
  _ratio := ratio_start;
  assert(cycle.daylight.y == false, "oops");
   [dynamic |0|0|0|0|]
2/2 (1): cycle.daylight.y = time < cycle.daylight.width   [dynamic |0|0|0|0|]
3/3 (1): cycle.daylight_ratio = _ratio   [binding |0|0|0|0|]
4/4 (1): _ratio = cycle.daylight.width   [dynamic |0|0|0|0|]

So we first try to evaluate the algorithm section.

But I'm not sure if this behavior is wrong. Not sure why older omc versions behave different here though.
I could imagine to get the correct code one would need to use an initial algorithm section to set a start value for _ratio.

comment:3 by Andreas Heuermann, 4 years ago

This model will work:

model DebugInitialValue
  model BooleanPulse
    input Real width(start=0.5);
    output Boolean y;
  equation
    y = time < width;
  end BooleanPulse;

  class DayNightCycle
    parameter Real earth_day_period=24;
    Real daylight_ratio;
    BooleanPulse daylight(width=daylight_ratio);
  end DayNightCycle;

  parameter Real ratio_start=0;
  Real _ratio;
  DayNightCycle cycle(daylight_ratio=_ratio); //FAILS.  Will work if changed to daylight_ratio=0 here.

equation
  _ratio = ratio_start;
algorithm
  if not initial() then 
    assert(cycle.daylight.y==false,"oops",level=AssertionLevel.warning);
  end if;

end DebugInitialValue;

comment:4 by Andreas Heuermann, 4 years ago

Cc: Karim Adbdelhak added
Milestone: 1.16.11.17.0
Version: v1.16.0-devv1.17.0-dev

@kabdelhak What is your opinion? Is the initial version of the model from the ticket description valid Modelica code?
I think using an algorithm section in such a way prevents the compiler from ordering the equations correctly.
I think it is not allowed to do anything in between steps of an algorithm section at all. We have to treat it as is.

Last edited 4 years ago by Andreas Heuermann (previous) (diff)

comment:5 by Andreas Heuermann, 4 years ago

following asserts time is less than zero

Btw, my assert time is 0:

messages = "assert            | warning | The following assertion has been violated during initialization at time 0.000000
|                 | |       | cycle.daylight.y == false
assert            | warning | oops

@craig.fletcher What OS and version are you using?

Last edited 4 years ago by Andreas Heuermann (previous) (diff)

in reply to:  4 ; comment:6 by Karim Adbdelhak, 4 years ago

Replying to AnHeuermann:

I think it is not allowed to do anything in between steps of an algorithm section at all. We have to treat it as is.

Yes we are not allowed to split up algorithms. If you define an algorithm it will be executed exactly how you defined it (sometimes it will be inverted as a whole, but that is very rare. And the order still is kept, just in reverse).

If you want the order to be determined by the tool, you have to use equations.

in reply to:  2 comment:7 by Francesco Casella, 4 years ago

I'm sorry but there are several things I don't understand about this example.

First of all, we are checking an assert during initialization even though the assert statement is found in an if clause with not initial() conditions. So, the assert condition shouldn't be checked (and possibly triggered) during initialization in the first place.

Second, "An algorithm section is treated as an atomic vector-equation, which is sorted together with all other equations. For the sorting process (BLT), every algorithm section with N different left-hand side variables, is treated as an atomic N-dimensional vector-equation containing all variables appearing in the algorithm section." (Section 11.1.2 of the Specification).

During simulation, the algorithm section (which must conceptually be kept together!) computes _ratio and needs cycle.daylight.y to compute the condition of the assert statement, so it should be computed after computing cycle.daylight.y, not before.

Do I miss something?

in reply to:  6 comment:8 by Francesco Casella, 4 years ago

Replying to Karim.Abdelhak:

Yes we are not allowed to split up algorithms. If you define an algorithm it will be executed exactly how you defined it (sometimes it will be inverted as a whole

Yes, using some Newton iteration

And the order still is kept, just in reverse

I'm not sure what do you mean by "in reverse". The order is kept, and an iterative strategy will be used to solve it backwards. Is that what you mean?

For example 10 = myfunction(x) will actually invert the function, but it will basically do it by (smart) trial and error, adjusting x and computing myfunction(x) at each step until the output matches 10.

in reply to:  5 comment:9 by anonymous, 4 years ago

Replying to AnHeuermann:

following asserts time is less than zero

Btw, my assert time is 0:

messages = "assert            | warning | The following assertion has been violated during initialization at time 0.000000
|                 | |       | cycle.daylight.y == false
assert            | warning | oops

@craig.fletcher What OS and version are you using?

Details as follows:
Distributor ID: Ubuntu
Description: Ubuntu 18.04.5 LTS
Release: 18.04
Codename: bionic

libomc_1.16.0-1_amd64.deb
libomcsimulation_1.16.0-1_amd64.deb
omc_1.16.0-1_amd64.deb
omc-common_1.16.0-1_all.deb
omc-doc_1.12.0-1_all.deb
omlib-complex-3.2.3_3.2.3~20201013~234009~git~OM~maint~3.2.3-1_all.deb
omlib-modelica-3.2.3_3.2.3~20201013~234009~git~OM~maint~3.2.3-1_all.deb
omlib-modelicaservices-3.2.3_3.2.3~20201013~234009~git~OM~maint~3.2.3-1_all.deb
omshell-terminal_1.16.0-1_amd64.deb

comment:10 by Andreas Heuermann, 4 years ago

@casella You are right. We are missing the not initial() part in the C code.

I created a new ticket for this because this is not the root problem for this ticket (I guess at least): #6186

in reply to:  10 comment:11 by Francesco Casella, 4 years ago

Replying to AnHeuermann:

@casella You are right. We are missing the not initial() part in the C code.

I created a new ticket for this because this is not the root problem for this ticket (I guess at least): #6186

Excellent, thanks!

comment:12 by Francesco Casella, 4 years ago

Milestone: 1.17.01.18.0

Retargeted to 1.18.0 because of 1.17.0 timed release.

comment:13 by Francesco Casella, 3 years ago

Milestone: 1.18.0

Ticket retargeted after milestone closed

Note: See TracTickets for help on using tickets.