【问题标题】:NON linear error because of WHEN statement in OPEN MODELICA由于 OPEN MODELICA 中的 WHEN 语句导致的非线性错误
【发布时间】:2020-12-01 09:33:05
【问题描述】:

我正在使用 OpenModelica 对复杂系统进行建模,但遇到了一个尴尬的错误 错误出现在when 语句中,正如您在图像 中看到的那样 我正在使用when 语句来确定膨胀阀中的质量流量 为了确认错误出现在when 语句中,我将其删除,并将质量流量等于计算质量流量的公式并且它起作用了,这意味着问题出现在when 语句中 如果有人可以帮助我,请

【问题讨论】:

  • 你是如何声明port_e.dbM的?它是声明为离散变量还是连续变量?它是否涉及“何时”之外的其他方程式?
  • 我使用了一个流连接器,我将它命名为连接器,所以它的 :.连接器 port_e , port_s;
  • 变量 dbM 怎么样。我的印象是它是一个连续变量而不是离散变量,即它被声明为 Real dbM 而不是离散的 Real dbM?。在这种情况下,我怀疑您需要使用“if”语句而不是“when”语句。
  • 这就是 dbM 的声明方式 connector connector_A 可替换包 Medium = Modelica.Media.Interfaces.PartialMedium;流量 Medium.MassFlowRate dbM;中.绝对压力 p ;流 Medium.SpecificEnthalpy h;结束连接器_A;

标签: modelica openmodelica


【解决方案1】:

使用when 循环的通常解决方案是在离散值变量上引入pre。不幸的是没有,所以我们必须介绍一个。

所以不是

  when level<min_level then 
    port.e_dbM=0.12;
  end when;

应该是:

   Boolean belowMin=level<min_level;
 equation
  when pre(belowMin) then
    port.e_dbM=0.12;
  end when;

(对于 elsewhen 也是如此。)

这是Problems understanding a dymola error message 中问题的答案的副本,和错误消息 - 我们可能需要一个更通用的问题和答案作为规范。

【讨论】:

  • 感谢您抽出宝贵时间回答我,我尝试了您的建议,但仍然遇到相同的错误,我不明白
  • 您是否完全添加了以下内容 - 如果是,我不知道: Boolean belowMin=levelmax_level;当 pre(belowMin) 然后 port.e_dbM=0.12 时的方程; elsewhen pre(aboveMax) then port.e_dbM=0.0;结束时间;
【解决方案2】:

根据您的描述,我看到变量 dbM 是一个连续变量。我认为使用when-statement 是不正确的。让我们先解决这个问题。

推理:when-statement 中的条件仅在条件指示器开始改变其符号的时间点触发事件一次,即幅度liquid_level_valve - min_value 在被触发后变为负数积极的。数值求解器通常成功地识别出发生这种符号变化的时间点。在这个时间点,比如说 t_e,触发了一个事件。

一旦触发事件,when-statement 中的等式将在时间 t_e 进行评估。对于以下仿真时间步长,即 t > t_e,不再评估该方程。相反,connect 语句产生的等式作为默认等式而不是when-语句中的等式。

因此,尝试使用if 语句而不是when 语句来表达边界条件。 if-statement 类似于我们所知的 Calculus 中的分支函数,这就是这里的情况。

我认为if 也可能发生其他答案所解决的相同情况。您可能需要遵循此处所述的类似方法。

如果if 语句的错误仍然存​​在,那么可以尝试noEvent 运算符,请参阅description。这不是完全正确的数字,但仍然是缩小此类错误的可能原因的一种方法。

更新:如何使用if 代替when: 为了用简单的用例说明这个想法,假设主方程如下所示:

myMassFlowRate = port_e.dbM; 

为了表达边界条件,可以引入一个辅助变量:

if liquid_level_value < min_value then 
  tmp = 0.012;
elseif liquid_level_value > max_value then
  tmp = 0; 
else
  tmp = port_e.dbM;
end if;
myMassFlowRate = tmp;

这适用于没有connect-statement 的平面代码。这种方式需要一些修改来处理跨组件通信信息的端口,但想法是相同的,例如如果需要,您可以通过端口传达离散的布尔值。例如,

type LiquidLevel = enumeration(above,normal,below);
discrete LiqidLevel level(start = normal); // assumption 
... 
// using when is now correct 
when(liquid_level_value < min_value) then 
    level = below; 
elsewhen (liquid_level > max_value) then
    level = above;
elsewhen (....) 
    level = normal; 
end when; 

可变液位可通过 I/O 端口进行通信以设置流速:

if level == normal then 
   myMassFlowRate = port_e.dbM; 
elseif level == below then
   myMassFlowRate = 0; 
else 
   myMassFlowRate = 0.012; 
end if; 

这与您的描述相符。直接使用when设置一个实变量只是重新初始化。

【讨论】:

  • 更多细节我使用when语句来控制进入罐的质量流量,质量流量由when语句控制,当罐中的液位低于a时一定的最小值,质量流量将用一个确定的方程计算,一个罐中的液位达到最大液位,质量流量将等于零,我不能使用 IF 语句,
  • 这是我从描述中了解到的,我发现使用when 是错误的。明确不能在if 语句中直接设置dbM,否则方程组将不一致,即方程多于未知数。需要一个额外的辅助变量,后面的想法见答案更新。
【解决方案3】:

花了很多天试图解决发布的问题后,我找到了解决非线性错误的解决方案 我在 WHEN 语句中使用了布尔值,该布尔值将使用 IF 语句控制质量流量,如下所示:

 when liquid_level_valve < min_valve then
 open_valve = true;
elsewhen liquid_level_valve > max_valve then
 open_valve = false;
end when;
port_e.dbM = if open_tev then dbM_valve else 1 / 100000;

其中 dbM 是使用对应于阀门的方程计算的。 现在我的系统可以正常工作了

感谢任何试图帮助我的人

【讨论】:

    猜你喜欢
    • 2020-04-21
    • 1970-01-01
    • 2020-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多