1
votes

I need to assert that a variable (a in the MWE below) is bigger than another (b).

I noticed that an assertion a>b inside an imported model behaved like a>=b. I tried to work around that problem to assert for a>(b+Constants.small) instead. Changing the assertion, even when asserting for a>(b+someBiggerNumber) still doesn' works as expected for a=b. If a!=b the assertion works as expected.

Is this a bug or am I doing something wrong? If it"s a bug, is there a workaround?

MWE:

model MWE

  model SomeModel
    parameter Real a(start=1);
    parameter Real b(start=1);
  protected
    Real c=5/(a-b);
  equation
    assert(a > b, "a has to be bigger than b. However, a (=" + String(a) +") < b (=" + String(b) + ")");
    //assert(a > (b + 1), "a has to be bigger than b+1. However, a (=" + String(a) +") < b (=" + String(b) + ")");
  end SomeModel;

  SomeModel sm(a = 5, b = 5);
  Real var;

equation
  var = sm.c;

end MWE;

// assert a > b
// a=5, b=4 no fail, as expected, same for b<4
// a=5, b=5 no fail
// a=5, b=6 fail, as expected, same for b>3

// assert a > (b + 1)
// a=5, b=3 no fail, as expected, same for b<3
// a=5, b=4 fail, as expected
// a=5, b=5 no fail
// a=5, b=6 fail, as expected, same for b>3
4

4 Answers

4
votes

If you want to get a predictable order, use one algorithm:

  protected
    Real c;
algorithm
    assert(a > b, "a has to be bigger than b. However, a (=" + String(a) +") <= b (=" + String(b) + ")");
    c:=5/(a-b);

Alternatively turn this into a function and have the assert inside the function.

0
votes

You can check Real variables for equality with Modelica.Math.isEqual(a,b) and combine it like this: (a > b) or Modelica.Math.isEqual(a,b)

0
votes

As usual the problem is sitting in front of the keyboard :/

I couldn't wrap my head around the problem by stepping through it in my head. The assertion works fine, but Modelica doesn't step through the equations sequentially like most programming languages do and therefore runs into a division by zero error before asserting anything.

Changing the sequence like this

  protected
    Real c;
  initial equation
    assert(a > b, "a has to be bigger than b. However, a (=" + String(a) +") < b (=" + String(b) + ")");
  algorithm
    assert(a > b, "a has to be bigger than b. However, a (=" + String(a) +") < b (=" + String(b) + ")");
  equation
    assert(a > b, "a has to be bigger than b. However, a (=" + String(a) +") < b (=" + String(b) + ")");
    c=5/(a-b);

doesn't change that.

If anyone knows how to run the assertion first to get cleaner error messages your input woud be welcome :)

0
votes

you have to do the part you want to have control over in the algorithm section such as:

model MWE

  model SomeModel
    parameter Real a(start=1);
    parameter Real b(start=1);
  protected
    Real c;
  algorithm
      assert(a > b, "a has to be bigger than b. However, a (=" + String(a) +") < b (=" + String(b) + ")");
    //assert(a > (b + 1), "a has to be bigger than b+1. However, a (=" + String(a) +") < b (=" + String(b) + ")");
    c := 5/(a-b);
  end SomeModel;

  SomeModel sm(a = 5, b = 5);
  Real var;

equation
  var = sm.c;

end MWE;

If you put two assignments in an algorithm, they will for sure be executed in that exact order. The compiler is free to change order of other equations though and if i am not incorrect asserts are treated as "removed equations" which do not have any output value contributing to the simulation, those are computed after a full step. So it will always be after the equation got evaluated. It is done this way because asserts are usually tested at the end of a step to prevent the next one from happening.

EDIT: ah i just saw that @Hans Olson posted the same solution, sorry!