连续时间内的 Modelica 布尔变量

Modelica Boolean variable in continuous time

下面的Modelica模型检查和模拟。

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;

RegionCheck()中的函数returns一个布尔值,这里是简化版:

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

在实际代码中,该函数的输入较多,名称较长,有几行长,并且多次使用相同的检查,因此为了可读性,我想引入一个中间变量,如注释中的protected部分,但这会导致错误 "Non-real equation in continuous time are not legal".

对优雅的解决方法有什么建议吗?

函数调用在 isInReg 的等式中引入了 noEvent

这是 Dymola 2019 FD01 在使用布尔值时报告的内容:

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

因此,您的等式简化为

isInReg = noEvent(a > b)

这是不允许的,因为布尔值只能根据事件发生变化。 您必须摆脱函数调用,从而摆脱 noEvent。

也许有更好的解决方案,但您可以尝试在块而不是函数中定义检查。至少对于您的最小示例,它工作得很好。

那么您的代码可能如下所示:

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;

基于没有函数可以转换为布尔值而只有一个块的事实,我建议 marco 的答案是可行的方法。

通过变通方法,您仍然可以在函数内执行此操作,但不能使用 Boolean 类型。而是使用 Real 并在 if 子句中比较它是否大于零。为了显示布尔值的切换行为,这很好用。如果您依赖函数并且不经常使用布尔值,这可能是一个选项。

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;

如果函数 inRegionCheck 由 annotation(GenerateEvents=true); 注释,则在 SimulationX 中工作(使用受保护的布尔变量 isInReg)。在 Dymola 中,您需要设置 annotation(Inline=true,GenerateEvents=true); 才能使其正常工作。