7

我正在尝试建立一个模型,该模型将根据是否存在某些组件(在我的情况下为流体端口)具有略微不同的方程。

如下代码将不起作用:

parameter Boolean use_component=false;
Component component if use_component;
equation
if use_component then
  component.x = 0;
end if;

我该如何解决这个问题?

4

3 回答 3

10

如果要使用条件组件,则需要注意一些限制。Modelica 3.3 规范的第 4.4.5 节很好地总结了它。它说“如果条件为假,则删除组件、其修饰符以及任何涉及该组件的连接方程”。我将在一秒钟内向您展示如何使用它来解决您的问题,但首先我想解释一下为什么您的解决方案不起作用。

这个问题与检查模型有关。在你的情况下,很明显方程component.x和分量component要么都存在,要么都不存在。那是因为您已将它们绑定到同一个布尔变量。但是如果你没有这个怎么办:

parameter Real some_number;
Component component if some_number*some_number>4.0;
equation
if some_number>=-2 and some_number<=2 then
  component.x = 0;
end if;

我们可以看到这在逻辑上与您的情况相同。component.x不在的时候就没有存在的机会component但是我们能普遍证明这些事情吗?不。

因此,当引入条件组件时,实现了保守语义,它总是可以轻松确保所涉及的变量和方程组永远不会“不同步”。

让我们回到规范所说的内容:“如果条件为假,则删除组件、其修饰符以及任何涉及该组件的连接方程”

对于您的情况,解决方案可能非常简单。根据您声明“x”的方式,您可以只添加修改component,即

parameter Boolean use_component=false;
Component component(x=0) if use_component;

这样做的好处是修改仅适用于component并且如果component不存在,则修改(方程式)也不是。所以变量x和它的相关方程是“同步的”。但这并不适用于所有情况(IIRC,x必须有一个input限定符才能工作......也许在你的情况下这是可能的?)。

还有两个选择。首先,将方程component.x放入component. 第二个是在那个上面引入一个连接器component,如果连接了,就会生成你想要的方程。与修改案例(这不是巧合)一样,您可以x与某种输入连接器关联,然后执行以下操作:

parameter Boolean use_component;
Component component if use_component;
Constant zero(k=0);
equation
connect(k.y, component.x);

现在,我可以想象,在考虑了所有三种情况(修改、内化方程和使用connect)之后,您得出的结论是它们都不起作用。如果是这种情况,那么我会谦虚地建议您对如何设计组件有疑问。出现这些限制的原因与必须自行检查组件的正确性有关。这要求组件是完整的(规范术语中的“平衡”)。

如果您无法使用我上面提到的方法解决问题,那么我怀疑您确实存在平衡问题,并且您可能需要以某种方式重新定义组件的边界。如果是这种情况,我建议您在此处打开另一个问题,详细说明您正在尝试做什么。

于 2013-02-04T13:56:16.187 回答
1

我认为这不起作用的原因是解析器将查找变量“component.x”的声明,如果组件不活动,则该声明不存在。即使您在注释中插入“Evaluate=true”,它也不起作用。在我看来,最干净的解决方案是在方程级别工作,并在同一块中启用不同的方程组。您可以使用正确的连接器和参数创建一个包装模型,然后如果它是一个因果模型,例如,您可以使用可替换的类来将模型参数化为函数,或者在非因果模型的情况下,将方程放入其中if 语句。另一种可能的解决方法是将两个不同的模型放在一个块中,这样您就可以将它们的变量用于方程部分,然后建立条件连接,以启用具有所选行为的块的使用。换句话说,您可以建立一个内部有两个块的“包装模型”,然后将连接方程放置在 if 语句中的包装模型的连接器上。请记住建立模型,以便即使对于未使用的块也会有一个一致的方程系统。但这不是最好的解决方案,因为如果块很大,您将不得不等待更长的时间进行编译,因为所有内容都会被编译。请记住建立模型,以便即使对于未使用的块也会有一个一致的方程系统。但这不是最好的解决方案,因为如果块很大,您将不得不等待更长的时间进行编译,因为所有内容都会被编译。请记住建立模型,以便即使对于未使用的块也会有一个一致的方程系统。但这不是最好的解决方案,因为如果块很大,您将不得不等待更长的时间进行编译,因为所有内容都会被编译。

我希望这个能帮上忙,

马可

于 2013-02-04T10:56:34.760 回答
0

您还可以制作一个在图形层中不可见的虚拟组件:

connector DummyHeatPort 
  "Dummy heatport to facilitate optional heatport.  Use this with a conditional heatport by connecting it to the heatport.  Then use the -DummyHeatPort.Q_flow in the thermal energy balance."
  Modelica.SIunits.Temperature T "Port temperature";
  flow Modelica.SIunits.HeatFlowRate Q_flow 
    "Heat flow rate (positive if flowing from outside into the component)";
end DummyHeatPort;

然后当它在两端口模型中使用时

 Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatport if use_heat_port;
 DummyHeatPort dummy_heatport;

...

 equation
 flowport_a.H_flow + flowport_b.H_flow - dummy_heatport.Q_flow = storage 
    "thermal energy balance";
  connect(dummy_heatport, heatport);  

这样,如果存在热端口,就会使用该热端口,但不会导致错误。

于 2014-02-12T14:43:06.587 回答