我正在尝试建立一个模型,该模型将根据是否存在某些组件(在我的情况下为流体端口)具有略微不同的方程。
如下代码将不起作用:
parameter Boolean use_component=false;
Component component if use_component;
equation
if use_component then
component.x = 0;
end if;
我该如何解决这个问题?
我正在尝试建立一个模型,该模型将根据是否存在某些组件(在我的情况下为流体端口)具有略微不同的方程。
如下代码将不起作用:
parameter Boolean use_component=false;
Component component if use_component;
equation
if use_component then
component.x = 0;
end if;
我该如何解决这个问题?
如果要使用条件组件,则需要注意一些限制。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
)之后,您得出的结论是它们都不起作用。如果是这种情况,那么我会谦虚地建议您对如何设计组件有疑问。出现这些限制的原因与必须自行检查组件的正确性有关。这要求组件是完整的(规范术语中的“平衡”)。
如果您无法使用我上面提到的方法解决问题,那么我怀疑您确实存在平衡问题,并且您可能需要以某种方式重新定义组件的边界。如果是这种情况,我建议您在此处打开另一个问题,详细说明您正在尝试做什么。
我认为这不起作用的原因是解析器将查找变量“component.x”的声明,如果组件不活动,则该声明不存在。即使您在注释中插入“Evaluate=true”,它也不起作用。在我看来,最干净的解决方案是在方程级别工作,并在同一块中启用不同的方程组。您可以使用正确的连接器和参数创建一个包装模型,然后如果它是一个因果模型,例如,您可以使用可替换的类来将模型参数化为函数,或者在非因果模型的情况下,将方程放入其中if 语句。另一种可能的解决方法是将两个不同的模型放在一个块中,这样您就可以将它们的变量用于方程部分,然后建立条件连接,以启用具有所选行为的块的使用。换句话说,您可以建立一个内部有两个块的“包装模型”,然后将连接方程放置在 if 语句中的包装模型的连接器上。请记住建立模型,以便即使对于未使用的块也会有一个一致的方程系统。但这不是最好的解决方案,因为如果块很大,您将不得不等待更长的时间进行编译,因为所有内容都会被编译。请记住建立模型,以便即使对于未使用的块也会有一个一致的方程系统。但这不是最好的解决方案,因为如果块很大,您将不得不等待更长的时间进行编译,因为所有内容都会被编译。请记住建立模型,以便即使对于未使用的块也会有一个一致的方程系统。但这不是最好的解决方案,因为如果块很大,您将不得不等待更长的时间进行编译,因为所有内容都会被编译。
我希望这个能帮上忙,
马可
您还可以制作一个在图形层中不可见的虚拟组件:
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);
这样,如果存在热端口,就会使用该热端口,但不会导致错误。