以下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;
函数inRegionCheck()返回一个布尔值,这里是一个简化版本:
function inRegionCheck
input Real a;
input Real b;
output Boolean c;
algorithm
c := a>b;
end inRegionCheck;
在实际代码中,函数有更多的输入和更长的名称,并且有几行长,并且多次使用相同的检查,因此为了便于阅读,我想引入一个中间变量,如注释的受保护部分所示,但结果错误“连续时间内的非实数方程式不合法”。
有关优雅解决方法的任何建议吗?
如果函数inRegionCheck由annotation(GenerateEvents=true);
注释,则在SimulationX中工作(带有受保护的布尔变量isInReg)。在Dymola中,您需要设置annotation(Inline=true,GenerateEvents=true);
才能使其正常工作。
函数调用在noEvent
的等式中引入了isInReg
。
如果使用布尔值,这就是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;