Search code examples
modelicadymolaopenmodelica

Why "time==0.5" isn't a discrete expression in Modelica language?


I build a simple model to understand the concept of "Discrete expressions", here is the code:

model Trywhen
  parameter Real B[ :] =   {1.0, 2.0, 3.0};
algorithm 
    when time>=0.5 then
      Modelica.Utilities.Streams.print("message");
    end when;
  annotation (uses(Modelica(version="3.2.3")));
end Trywhen;

But when checking the model, I got an error showing that "time==0.5" isn't a discrete expression. enter image description here

enter image description here

If I change time==0.5 to time>=0.5, the model would pass the check.

enter image description here

And if I use if-clause to when-clause, the model works fine but with a warning showing that "Variables of type Real cannot be compared for equality."

enter image description here

My questions are:

  1. Why time==0.5 is NOT a discrete expression?
  2. Why Variables of type Real cannot be compared for equality? It seems common when comparing two variables of type Real.

Solution

  • The first question is not important, since time==0.5 is not allowed.

    The second question is the important one: Comparing reals for equality is common in other languages, and also a common source of errors - unless special care is taken.

    Merely using the floating point compare of the processor is a really bad idea on idea on some processors (like Intel) that mix 80-bit and 64-bit floating point numbers (or comes with a performance penalty), and also in other cases it may not work as intended. In this case 0.5 can be represented as a floating point number, but 0.1 and 0.2 cannot.

    Often abs(x-y)<eps is a good alternative, but it depends on the intended use and the eps depends on additional factors; not only machine precision but also which algorithm is used to compute x and y and its error propagation.

    In Modelica the problems are worse than in many other languages, since tools are allowed to optimize expressions a lot more (including symbolic manipulations) - which makes it even harder to figure out a good value for eps.

    All those problems mean that it was decided to not allow comparison for equality - and require something more appropriate.

    In particular if you know that you will only approach equality from one direction you can avoid many of the problems. In this case time is increasing, so if it has been >0.5 at an event it will not be <=0.5 at a later event, and when will only trigger the first time the expression becomes true.

    Therefore when time>=0.5 will only trigger once, and will trigger about when time==0.5, so it is a good alternative. However, there might be some numerical inaccuracies and thus it might trigger at 0.500000000000001.