Modelica:如何使用可替换组件?
Modelica: how to use replaceable components?
我正在尝试构建一个模型,该模型可以在同一范围内使用两个不同的组件(取自现有库):特别是带有热交换器的系统;这种热交换器可以基于不同的技术,例如管道或板材。
然后我想定义一个带有默认可更换交换器的模型,并说明可以使用哪些其他技术。
这是我尝试过的一个非常简单的例子:
package Test
// Component 1 original definition in the library
model COMP1
parameter Real p1=1 "";
Real v "";
equation
v=p1*time;
end COMP1;
// Component 2 original definition in the library
model COMP2
parameter Real p2=1 "";
Real v "";
equation
v=p2*time;
end COMP2;
// Main module (system)
model MAIN
parameter Real pm=100 "";
Real vm "";
// Redefinition of the component modifing the default values
model call1 = COMP1(p1=10);
model call2 = COMP2(p2=20);
replaceable call1 OBJ
annotation(choices(
choice(redeclare call1 OBJ "Default"),
choice(redeclare call2 OBJ "Variant")));
equation
vm = OBJ.v+pm;
end MAIN;
// Application model, using the main model
model APP
MAIN mAIN;
end APP;
end Test;
模型APP运行成功。但是,如果我打开 APP.mAIN 的参数并更改 OBJ(选择 "Default" 或 "Variant"),则会导致修改 APP 模型如下:
model APP
MAIN mAIN(redeclare call1 OBJ "Default");
end APP;
我收到以下错误:
Component type specifier call1 not found
我不明白我做错了什么,请帮助。
出现与错误相关的问题,因为您没有在选择注释中使用正确的 class 路径。
如果你在APP
中select"Default",你会得到以下代码:
model APP
MAIN mAIN(redeclare call1 OBJ "Default");
end APP;
这里我们看到 class 路径 call1
无效。 APP只能通过相对class路径MAIN.call1
或绝对class路径Test.MAIN.call1
访问call1
。
所以你可以通过使用下面的注解来解决这个问题:
replaceable call1 OBJ
annotation(choices(
choice(redeclare MAIN.call1 OBJ "Default"),
choice(redeclare MAIN.call2 OBJ "Variant")));
然而,在 Dymola 中,模型仍然没有检查,显然是由于 MAIN
中的本地 class 定义,在 下修改默认值的组件的重新定义。
在这里您创建新的 classes call1
和 call2
。这可能是 Dymola 错误,因为它在 OpenModelica 中有效 - 但新的 classes 不是必需的。相反,您可以使用原始 classes 并在 redeclare
语句中使用修饰符方程设置参数,如下所示:
model MAIN
parameter Real pm=100 "";
Real vm "";
replaceable COMP1 OBJ
annotation(choices(
choice(redeclare Test.COMP1 OBJ(p1=10) "Default"),
choice(redeclare Test.COMP2 OBJ(p2=10) "Variant")));
equation
vm = OBJ.v+pm;
end MAIN;
现在该模型不适用 selection 和 "Default",但是当 "Variant" 被 selected 时,Dymola 抱怨重新声明的 class不包含与原始变量相同的变量。
这是使用可替换 classes 时的限制之一(同样,OpenModelica 没有问题,但 Dymola 警告您这不符合 Modelica 语言规范)
替代方法:带接口的 MSL 样式
我建议像 Modelica 库通常那样创建一个接口模型(例如 Modelica.Electrical.Analog.Interfaces.OnePort
):
- 您创建了一个
partial
基础模型,其中包含所有变体共有的所有内容,称为接口
- 变体扩展了现有库的接口和模型之一
- 使用变体的class实例化其中一个变体并使用constrainedby
将重新声明约束到接口
- 您现在可以使用注释 choicesAllMatching
自动创建它,而不是手动创建选择注释
这就是您的示例的样子。第三方组件 COMP1
和 COMP2
被移动到包 ReadOnlyLibrary
.
package Test
// Original definition of Component 1 and 2 in the external library
package ReadOnlyLibrary
model COMP1
parameter Real p1=1 "";
Real v "";
equation
v=p1*time;
end COMP1;
model COMP2
parameter Real p2=1 "";
Real v "";
equation
v=p2*time;
end COMP2;
end ReadOnlyLibrary;
// Interface and variants with modified default values
partial model Call_Interface
Real v "";
end Call_Interface;
model Call1 "Default"
extends Call_Interface;
extends ReadOnlyLibrary.COMP1(p1=10);
end Call1;
model Call2 "Variant"
extends Call_Interface;
extends ReadOnlyLibrary.COMP2(p2=20);
end Call2;
// Main module (system)
model Main
parameter Real pm=100 "";
Real vm "";
replaceable Test.Call1 OBJ constrainedby Test.Call_Interface annotation (choicesAllMatching);
equation
vm = OBJ.v+pm;
end Main;
// Application model, using the main model
model App
Main main annotation (Placement(transformation(extent={{-12,10},{8,30}})));
end App;
end Test;
我正在尝试构建一个模型,该模型可以在同一范围内使用两个不同的组件(取自现有库):特别是带有热交换器的系统;这种热交换器可以基于不同的技术,例如管道或板材。
然后我想定义一个带有默认可更换交换器的模型,并说明可以使用哪些其他技术。
这是我尝试过的一个非常简单的例子:
package Test
// Component 1 original definition in the library
model COMP1
parameter Real p1=1 "";
Real v "";
equation
v=p1*time;
end COMP1;
// Component 2 original definition in the library
model COMP2
parameter Real p2=1 "";
Real v "";
equation
v=p2*time;
end COMP2;
// Main module (system)
model MAIN
parameter Real pm=100 "";
Real vm "";
// Redefinition of the component modifing the default values
model call1 = COMP1(p1=10);
model call2 = COMP2(p2=20);
replaceable call1 OBJ
annotation(choices(
choice(redeclare call1 OBJ "Default"),
choice(redeclare call2 OBJ "Variant")));
equation
vm = OBJ.v+pm;
end MAIN;
// Application model, using the main model
model APP
MAIN mAIN;
end APP;
end Test;
模型APP运行成功。但是,如果我打开 APP.mAIN 的参数并更改 OBJ(选择 "Default" 或 "Variant"),则会导致修改 APP 模型如下:
model APP
MAIN mAIN(redeclare call1 OBJ "Default");
end APP;
我收到以下错误:
Component type specifier call1 not found
我不明白我做错了什么,请帮助。
出现与错误相关的问题,因为您没有在选择注释中使用正确的 class 路径。
如果你在APP
中select"Default",你会得到以下代码:
model APP
MAIN mAIN(redeclare call1 OBJ "Default");
end APP;
这里我们看到 class 路径 call1
无效。 APP只能通过相对class路径MAIN.call1
或绝对class路径Test.MAIN.call1
访问call1
。
所以你可以通过使用下面的注解来解决这个问题:
replaceable call1 OBJ
annotation(choices(
choice(redeclare MAIN.call1 OBJ "Default"),
choice(redeclare MAIN.call2 OBJ "Variant")));
然而,在 Dymola 中,模型仍然没有检查,显然是由于 MAIN
中的本地 class 定义,在 下修改默认值的组件的重新定义。
在这里您创建新的 classes call1
和 call2
。这可能是 Dymola 错误,因为它在 OpenModelica 中有效 - 但新的 classes 不是必需的。相反,您可以使用原始 classes 并在 redeclare
语句中使用修饰符方程设置参数,如下所示:
model MAIN
parameter Real pm=100 "";
Real vm "";
replaceable COMP1 OBJ
annotation(choices(
choice(redeclare Test.COMP1 OBJ(p1=10) "Default"),
choice(redeclare Test.COMP2 OBJ(p2=10) "Variant")));
equation
vm = OBJ.v+pm;
end MAIN;
现在该模型不适用 selection 和 "Default",但是当 "Variant" 被 selected 时,Dymola 抱怨重新声明的 class不包含与原始变量相同的变量。 这是使用可替换 classes 时的限制之一(同样,OpenModelica 没有问题,但 Dymola 警告您这不符合 Modelica 语言规范)
替代方法:带接口的 MSL 样式
我建议像 Modelica 库通常那样创建一个接口模型(例如 Modelica.Electrical.Analog.Interfaces.OnePort
):
- 您创建了一个
partial
基础模型,其中包含所有变体共有的所有内容,称为接口 - 变体扩展了现有库的接口和模型之一
- 使用变体的class实例化其中一个变体并使用constrainedby 将重新声明约束到接口
- 您现在可以使用注释 choicesAllMatching 自动创建它,而不是手动创建选择注释
这就是您的示例的样子。第三方组件 COMP1
和 COMP2
被移动到包 ReadOnlyLibrary
.
package Test
// Original definition of Component 1 and 2 in the external library
package ReadOnlyLibrary
model COMP1
parameter Real p1=1 "";
Real v "";
equation
v=p1*time;
end COMP1;
model COMP2
parameter Real p2=1 "";
Real v "";
equation
v=p2*time;
end COMP2;
end ReadOnlyLibrary;
// Interface and variants with modified default values
partial model Call_Interface
Real v "";
end Call_Interface;
model Call1 "Default"
extends Call_Interface;
extends ReadOnlyLibrary.COMP1(p1=10);
end Call1;
model Call2 "Variant"
extends Call_Interface;
extends ReadOnlyLibrary.COMP2(p2=20);
end Call2;
// Main module (system)
model Main
parameter Real pm=100 "";
Real vm "";
replaceable Test.Call1 OBJ constrainedby Test.Call_Interface annotation (choicesAllMatching);
equation
vm = OBJ.v+pm;
end Main;
// Application model, using the main model
model App
Main main annotation (Placement(transformation(extent={{-12,10},{8,30}})));
end App;
end Test;