3

The Modelica model below passes validation:

model TestController
  parameter Real off[4] = fill(20, 4) "Radiator turn off threshold";
  parameter Real on[4] = fill(19, 4) "Radiator turn on threshold";
  discrete Modelica.Blocks.Interfaces.RealInput x[4];
  output Modelica.Blocks.Interfaces.BooleanOutput h[4];
protected
  Boolean has_heater[4];
equation
  has_heater = {false, true, true, false};
algorithm
  for j in 1:4 loop
    h[j] := has_heater[j] and ((not h[j] and x[j] <= on[j]) or (h[j] and x[j] < off[j]));
  end for;
end TestController;

But when I try to simulate it, I get an error in the compiled code:

sme.12.0.0_1575385723_1403176131_main.cpp: In function ‘int function_zeroCrossing(f2c_integer*, double*, double*, f2c_integer*, double*, double*, f2c_integer*)’:
sme.12.0.0_1575385367_109695398_main.cpp:347:35: error: ‘$i1_j’ was not declared in this scope
  349 |   base_array_range_check1(&$tmp0, $i1_j - 1, "[:0:0-0:0]", "x[$i1_j]");
      |        

There must be something fundamental I'm not understanding, why doesn't this loop simulate? If I remove the second clause for the value of h and make it simply h[j] := has_heater[j] the simulation works.

Sameer Puri
  • 987
  • 8
  • 20

2 Answers2

2

It is in general a good idea to avoid algorithms in Modelica, and instead use equations. I believe this is likely to work in System Modeler (both this and the original works in Dymola).

model TestController
  parameter Real off[4] = fill(20, 4) "Radiator turn off threshold";
  parameter Real on[4] = fill(19, 4) "Radiator turn on threshold";
  discrete Modelica.Blocks.Interfaces.RealInput x[4];
  output Modelica.Blocks.Interfaces.BooleanOutput h[4];
protected
  Boolean has_heater[4];
equation
  has_heater = {false, true, true, false};
  for j in 1:4 loop
    h[j] := has_heater[j] and ((not pre(h[j]) and x[j] <= on[j]) or (pre(h[j]) and x[j] < off[j]));
  end for;
end TestController;

In this case it is not entirely trivial, since you have to use pre(h[j]) in the right-hand side, whereas that it is handled sort of automatically for algorithms.

Hans Olsson
  • 11,123
  • 15
  • 38
  • 1
    You're right, it could've just been an equation. I have some more complex imperative code, so I was just trying to show a trivialized case where the simulation fails to run. From what I can tell, SystemModeler just doesn't support for loops in the algorithm section at all. If I unroll the loop it works perfectly. – Sameer Puri Dec 03 '19 at 18:12
2

Just an idea, posting as answer because it is too long for a comment: Maybe inline for loops work a bit better, instead of

  for j in 1:4 loop
    h[j] := has_heater[j] and ((not h[j] and x[j] <= on[j]) or (h[j] and x[j] < off[j]));
  end for;

try it like

  h := {has_heater[j] and ((not h[j] and x[j] <= on[j]) or (h[j] and x[j] < off[j])) for j in 1:4};

Also see https://github.com/mtiller/ModelicaBook/issues/338

matth
  • 2,568
  • 2
  • 21
  • 41
  • 1
    The inline loop simulates successfully with SystemModeler. It's still not clear to me why the original would not simulate, but I can use this syntax instead. – Sameer Puri Dec 04 '19 at 15:36