【问题标题】:Modelica Boolean variable in continuous timeModelica 连续时间的布尔变量
【发布时间】:2019-03-08 12:49:46
【问题描述】:

以下 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;

在实际代码中,该函数有更多的输入和更长的名称,并且有几行长,并且多次使用相同的检查,所以为了便于阅读,我想引入一个中间变量,如注释保护部分所示,但这会导致错误“连续时间中的非实数方程不合法”。

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

【问题讨论】:

    标签: time boolean modelica continuous


    【解决方案1】:

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

    【讨论】:

    • 不错。不知道 GenerateEvents 注释。 Modelica 参考包不包含它。但它链接到 trac.modelica.org/Modelica/ticket/1048 并说它已在 Modelica 3.2 rev2 中删除!?
    • 请注意,Modelica 3.2r2 是在 Modelica 3.3 之后发布的。 GenerateEvents 最初是在 Modelica 3.3 中引入的。在将 Modelica 3.3 的功能向后移植到 Modelica 3.2r2 时,首先考虑了它,但后来又被删除了。这就是github.com/modelica/ModelicaSpecification/issues/1048 的意义所在。由于 ModelicaReference 是基于 Modelica 3.2r2 的,所以它还没有。
    【解决方案2】:

    函数调用在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;
    

    【讨论】:

      【解决方案3】:

      基于没有函数可以转换为布尔值而只有一个块的事实,我建议马可的答案是要走的路。

      使用变通方法,您仍然可以在函数内部执行此操作,但不能使用 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;
      

      【讨论】:

        猜你喜欢
        • 2023-04-01
        • 2021-10-08
        • 1970-01-01
        • 1970-01-01
        • 2021-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-22
        相关资源
        最近更新 更多