matth
matth

Reputation: 2696

Modelica Boolean variable in continuous time

The following Modelica model checks and simulates.

model boolCheck_OK1
  Real a = sin(time);
  Real b = cos(time);
  Real c;
//protected 
//  Boolean isInReg = inRegionCheck(a, b);
equation 
  c = if inRegionCheck(a, b) then 1.3*a^b else 0.7*b^a;
end boolCheck_OK1;

The function inRegionCheck() returns a Boolean, here is a simplified version:

function inRegionCheck
  input Real a;
  input Real b;
  output Boolean c;
algorithm 
   c := a>b;
end inRegionCheck;

In the actual code, the function has more inputs and a longer name and is several lines long and the same check is used several times, so for readability I would like to introduce an intermediate variable as shown in the commented protected section, but that results in an error "Non-real equation in continuous time are not legal".

Any suggestions for an elegant workaround?

Upvotes: 1

Views: 829

Answers (3)

tbeu
tbeu

Reputation: 1349

Works in SimulationX (with protected Boolean variable isInReg) if the function inRegionCheck is annotated by annotation(GenerateEvents=true);. In Dymola, you need to set annotation(Inline=true,GenerateEvents=true); to make it working.

Upvotes: 4

f.wue
f.wue

Reputation: 847

Based on the fact that there is no function to convert to boolean but only a block, i would suggest marco's answer is the way to go.

With a workaround you can still do it inside a function, but not with the type Boolean. Instead use Real and compare in the if-clause if it's greater zero. For showing the switching behaviour of the boolean this works fine. If you rely on the function and don't use the boolean too often, this could be an option.

model boolCheck_OK1
  Real a = sin(time);
  Real b = cos(time);
  Real c;

function inRegionCheck
  input Real a;
  input Real b;
  output Real c;
algorithm 
  c := if a>b then 1 else 0;
end inRegionCheck;
protected
  Real isInReg = inRegionCheck(a, b);

equation 
  c = if inRegionCheck(a, b)>Modelica.Constants.eps then 1.3*a^b else 0.7*b^a;
end boolCheck_OK1;

Upvotes: 1

marco
marco

Reputation: 6655

The function call introduces a noEvent in your equation for isInReg.

This is what Dymola 2019 FD01 reports if the boolean is used:

Non-real equation in continuous time are not legal:
isInReg = noEvent(a > b);

Hence, your equation reduces to

isInReg = noEvent(a > b)

which is not allowed, as boolean values can only change on events. You have to get rid of the function call and thus the noEvent.

Maybe there is a better solution, but you could try to define the check in a block instead of a function. At least for your minimal example it works perfectly fine.

Then your code could look like this:

model boolCheck_OK1
  Real a = sin(time);
  Real b = cos(time);
  Real c;
protected 
  InRegionCheck check(a=a, b=b);
  Boolean isInReg=check.c;
equation 
  c = if isInReg then 1.3*a^b else 0.7*b^a;
end boolCheck_OK1;

block InRegionCheck
  input Real a;
  input Real b;
  output Boolean c;
equation 
   c = a>b;
end InRegionCheck;

Upvotes: 1

Related Questions