Modelica - 模型变体(标准的一种和更复杂的一种)
Modelica - Model variants (Standard one and more complex one)
即使几个月以来一直在使用 Modelica,我对继承和替换等高级功能还是陌生的。
我有一个标准模型(即游泳池)和一个更复杂的变体(即包括蒸发计算):这两个模型有许多我想要的共同部分 "reuse" 但它们也有一些差异: 一些方程(即质量和能量平衡方程)不同(复杂模型有更多项)并且复杂模型包括更多参数、变量和方程(即空气和蒸汽性质和定律)。
我认为我在 Modelica 中有一些可能性可以做到这一点:
- 写下两个独立的模型(只用了精彩的不同步复制粘贴文本功能)--我不想。
- 使用继承(1)编写一个具有公共定义的部分模型和两个具有特定部分的继承模型。
- 使用继承 (2) 编写包含不同方程组(和其他特定定义)的两个部分模型,并编写包含通用定义并继承两个部分模型之一的第三个模型(例如选择通过一个布尔参数)。实际上我不太确定我能做到这一点:部分模型将包含未定义 variables/parameters 的方程(将在继承模型中定义):可以吗?
- 编写标准模型并用新方程替换方程,同时添加附加定义。
我在(2)中实现了,见下面的示例1。但是我不明白如何使用替换机制(参见我在示例 2 中的失败尝试)。我哪里错了?
下面的例子是我为了理解如何去做而写的简化模型。
示例 1
package Inherited_base
partial model Base
parameter Real a=1;
parameter Real b=2;
Real c;
Real d;
equation
c+d = b;
end Base;
model Variant_1
extends Base;
equation
c = time*a;
end Variant_1;
model Variant_2
extends Base;
parameter Real e=0.5;
Real d;
equation
c+d*e = time*a;
end Variant_2;
end Inherited_base;
示例 2
model Base
parameter Real a=1;
parameter Real b=2;
class Eqs
Real c;
Real d;
equation
c = time*a;
end Eqs;
equation
replaceble Eqs bouclage;
bouclage.c+bouclage.d = b;
end Base;
编辑:我试图回答项目符号 3 中的问题:我在定义部分模型时收到错误消息,其中方程中使用的 variables/parameters 未在 class 中定义。我通过稍微修改我的想法解决了这个问题:我在两种情况下使用相同的方程式但是我有一个术语(示例中的'extra')考虑到根据情况使用不同的variables/parameters .但是,似乎无法交互式地选择要扩展的模型:下面的示例是错误的(没有 "if" 并且只有一个 'extends' 没问题)。
示例 3
package Inherited_variants
model Final
parameter Real a=1;
parameter Real b=2;
Real c;
Real d;
parameter Boolean complexmodel = false;
if complexmodel then
extends Variant_2;
else
extends Variant_1;
end if;
equation
c+d = b;
c+extra = time*a;
end Final;
partial model Variant_1
parameter Real extra=0;
end Variant_1;
partial model Variant_2
parameter Real e=0.5;
Real d;
Real extra;
equation
extra = d*e;
end Variant_2;
end Inherited_variants;
在 Scott G 和 Hans Olsson 回答后进行编辑(感谢你们!)。
这些例子很有趣,但我仍然对你的例子中 "extends" 的广泛使用感到困惑。所以我试着简化你的代码,也从 here.
那里学到了一些东西
重新排列了 Scott 的示例:
package Example
partial model FinalTerm
end FinalTerm;
model Final
model Variant_1
extends FinalTerm;
parameter Real extra=0;
end Variant_1;
parameter Real a=1;
parameter Real b=2;
Real c;
Real d;
replaceable model VarType = Variant_1 constrainedby FinalTerm annotation(choicesAllMatching=true);
//replaceable model VarType = Variant_1 constrainedby FinalTerm annotation(choices(choice=redeclare Variant_2 VarType,
// choice=redeclare Variant_1 VarType));
VarType varType;
equation
c+d = b;
c+varType.extra*d = time*a;
end Final;
model Variant_2
extends FinalTerm;
parameter Real e=0.5;
Real extra;
equation
extra = e;
end Variant_2;
end Example;
汉斯的例子重新排列:
package Example_2
partial model FinalTerm
end FinalTerm;
model Final
model Variant_1
extends FinalTerm;
parameter Real extra=0;
end Variant_1;
parameter Real a=1;
parameter Real b=2;
Real c;
Real d;
replaceable Variant_1 test constrainedby FinalTerm annotation(choicesAllMatching=true);
//replaceable Variant_1 test constrainedby FinalTerm annotation(choices(choice=redeclare Variant_2 test "NEW",
// choice=redeclare Variant_1 test "OLD"));
equation
c+d = b;
c+test.extra*d = time*a;
end Final;
model Variant_2
extends FinalTerm;
parameter Real e=0.5;
Real extra;
equation
extra = e;
end Variant_2;
end Example_2;
我的理解(或者至少我认为):
- 两者的区别examples/approaches。对于我打算的用途,我个人更喜欢 Hans 的方法(组件替换)。但是,要同时执行多个组件更换,Scott 的那个更合适。
- 'extends' 的使用不是强制性的。我发现的唯一用途是允许使用必须引用 ~common-mother-class~ 的 'constrainedby' (抱歉我的措辞不当);这与 Scott 提供的 'annotation' 相结合,允许在参数中有一个并非无用的下拉菜单(并且也可以与 Hans 的技术一起使用)。
一个小问题仍然悬而未决:根据 the previous webpage 应该可以手动定义 'annotation(choices())' 列表,但我没有成功(参见前面示例中的注释行)。这将允许适当的下拉菜单,而无需使用 "common-mother-class" 到 'extend' 和 'constrainedby' 关键字。有人知道我哪里错了吗?
您想使用 replaceable model
在模型之间切换而不是 if
语句。下面是一个基于您的示例的示例。我将留给您重新考虑如何正确地表述您的问题以正确使用可替换功能。希望对你有帮助。
在 Dymola 2017 FD01 中测试...
不确定 OMEdit 是否会处理 replaceable
正确使用,因为似乎存在一些仍在解决的长期问题:
https://trac.openmodelica.org/OpenModelica/ticket/2079.
package Example
model Test
// Simple test of the component "Final"
Final Final1(
redeclare model VarType = Variant_1,
redeclare Variant_2 varType2,
redeclare Example.Variant_3 varType3 "Test")
annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
end Test;
model Final
// Model demonstrating difference ways to use "replaceable"
extends ReplaceableModels.PartialModel;
replaceable model VarType = ReplaceableModels.Variant_1 constrainedby
ReplaceableModels.PartialVariants
annotation(choicesAllMatching=true);
VarType varType1;
replaceable ReplaceableModels.Variant_1 varType2 constrainedby
ReplaceableModels.PartialVariants annotation (choicesAllMatching=true);
replaceable ReplaceableModels.Variant_1 varType3 constrainedby
ReplaceableModels.PartialVariants annotation (choices(
choice(redeclare Example.Variant_1 varType3 "OLD"),
choice(redeclare Example.Variant_2 varType3 "NEW"),
choice(redeclare Example.Variant_3 varType3 "Test")));
equation
result1 = varType1.extra;
result2 = varType2.extra;
result3 = varType3.extra;
end Final;
model Variant_1
extends ReplaceableModels.PartialVariants;
parameter Real extra0=0;
equation
extra = extra0;
end Variant_1;
model Variant_2
extends ReplaceableModels.PartialVariants;
parameter Real a=1;
Real b;
Real c;
parameter Real e=0.5;
parameter Real d = 0.1;
equation
c+d = b;
c+extra = time*a;
extra = d*e;
end Variant_2;
model Variant_3
Real extra;
parameter Real a=1;
Real b;
Real c;
parameter Real e=0.5;
parameter Real d = 0.1;
equation
c+d = b;
c+extra = time*a;
extra = d*e;
end Variant_3;
partial model PartialModel
Real result1;
Real result2;
Real result3;
end PartialModel;
partial model PartialVariants
Real extra;
end PartialVariants;
end Example;
更新:
添加了注释,以便在图形用户界面中有一个用于模型选择的下拉箭头。
更新 2:
我已将原始代码替换为一个扩展示例,该示例根据发布者的附加问题演示了使用可替换的几种不同方法。该代码现在还包括创建的模型的 Test
(Final
) 和不从部分 class 扩展的 Variant_3 以显示 choices
如果对您的情况有用,注释还允许您包含额外的模型。
Scott G 解决方案的替代方案是使用可替换组件(以他的代码为基础):
package ReplaceableComponentTest
model Test2 "Showing how to change it"
extends Final(redeclare Example.Variant_2 varType);
end Test2;
model Final
extends Example.PartialModel;
replaceable Example.Variant_1 varType constrainedby
Example.PartialVariants annotation(choices(
choice(redeclare Example.Variant_2 test "NEW"),
choice(redeclare Example.Variant_1 test "OLD")));
equation
result = varType.extra;
end Final;
end ReplaceableComponentTest;
package Example
model Variant_1
extends Example.PartialVariants;
parameter Real extra0=0;
equation
extra = extra0;
end Variant_1;
model Variant_2
extends Example.PartialVariants;
parameter Real a=1;
Real b;
Real c;
parameter Real e=0.5;
parameter Real d = 0.1;
equation
c+d = b;
c+extra = time*a;
extra = d*e;
end Variant_2;
partial model PartialModel
Real result;
end PartialModel;
partial model PartialVariants
Real extra;
end PartialVariants;
end Example;
两者都适用于这种情况。请注意,我也添加了选择注释 - 为了安全起见,使用了 类 的全名(即使它应该有效)。
如果您有该模型的多个组件,则需要使用可替换模型,而在其他情况下,它更多的是风格问题。
我仍然可以推荐 https://modelica.org/events/Conference2003/Modelica03-AdvancedTutorial.pdf 的第五部分。
即使几个月以来一直在使用 Modelica,我对继承和替换等高级功能还是陌生的。
我有一个标准模型(即游泳池)和一个更复杂的变体(即包括蒸发计算):这两个模型有许多我想要的共同部分 "reuse" 但它们也有一些差异: 一些方程(即质量和能量平衡方程)不同(复杂模型有更多项)并且复杂模型包括更多参数、变量和方程(即空气和蒸汽性质和定律)。
我认为我在 Modelica 中有一些可能性可以做到这一点:
- 写下两个独立的模型(只用了精彩的不同步复制粘贴文本功能)--我不想。
- 使用继承(1)编写一个具有公共定义的部分模型和两个具有特定部分的继承模型。
- 使用继承 (2) 编写包含不同方程组(和其他特定定义)的两个部分模型,并编写包含通用定义并继承两个部分模型之一的第三个模型(例如选择通过一个布尔参数)。实际上我不太确定我能做到这一点:部分模型将包含未定义 variables/parameters 的方程(将在继承模型中定义):可以吗?
- 编写标准模型并用新方程替换方程,同时添加附加定义。
我在(2)中实现了,见下面的示例1。但是我不明白如何使用替换机制(参见我在示例 2 中的失败尝试)。我哪里错了?
下面的例子是我为了理解如何去做而写的简化模型。
示例 1
package Inherited_base
partial model Base
parameter Real a=1;
parameter Real b=2;
Real c;
Real d;
equation
c+d = b;
end Base;
model Variant_1
extends Base;
equation
c = time*a;
end Variant_1;
model Variant_2
extends Base;
parameter Real e=0.5;
Real d;
equation
c+d*e = time*a;
end Variant_2;
end Inherited_base;
示例 2
model Base
parameter Real a=1;
parameter Real b=2;
class Eqs
Real c;
Real d;
equation
c = time*a;
end Eqs;
equation
replaceble Eqs bouclage;
bouclage.c+bouclage.d = b;
end Base;
编辑:我试图回答项目符号 3 中的问题:我在定义部分模型时收到错误消息,其中方程中使用的 variables/parameters 未在 class 中定义。我通过稍微修改我的想法解决了这个问题:我在两种情况下使用相同的方程式但是我有一个术语(示例中的'extra')考虑到根据情况使用不同的variables/parameters .但是,似乎无法交互式地选择要扩展的模型:下面的示例是错误的(没有 "if" 并且只有一个 'extends' 没问题)。
示例 3
package Inherited_variants
model Final
parameter Real a=1;
parameter Real b=2;
Real c;
Real d;
parameter Boolean complexmodel = false;
if complexmodel then
extends Variant_2;
else
extends Variant_1;
end if;
equation
c+d = b;
c+extra = time*a;
end Final;
partial model Variant_1
parameter Real extra=0;
end Variant_1;
partial model Variant_2
parameter Real e=0.5;
Real d;
Real extra;
equation
extra = d*e;
end Variant_2;
end Inherited_variants;
在 Scott G 和 Hans Olsson 回答后进行编辑(感谢你们!)。 这些例子很有趣,但我仍然对你的例子中 "extends" 的广泛使用感到困惑。所以我试着简化你的代码,也从 here.
那里学到了一些东西重新排列了 Scott 的示例:
package Example
partial model FinalTerm
end FinalTerm;
model Final
model Variant_1
extends FinalTerm;
parameter Real extra=0;
end Variant_1;
parameter Real a=1;
parameter Real b=2;
Real c;
Real d;
replaceable model VarType = Variant_1 constrainedby FinalTerm annotation(choicesAllMatching=true);
//replaceable model VarType = Variant_1 constrainedby FinalTerm annotation(choices(choice=redeclare Variant_2 VarType,
// choice=redeclare Variant_1 VarType));
VarType varType;
equation
c+d = b;
c+varType.extra*d = time*a;
end Final;
model Variant_2
extends FinalTerm;
parameter Real e=0.5;
Real extra;
equation
extra = e;
end Variant_2;
end Example;
汉斯的例子重新排列:
package Example_2
partial model FinalTerm
end FinalTerm;
model Final
model Variant_1
extends FinalTerm;
parameter Real extra=0;
end Variant_1;
parameter Real a=1;
parameter Real b=2;
Real c;
Real d;
replaceable Variant_1 test constrainedby FinalTerm annotation(choicesAllMatching=true);
//replaceable Variant_1 test constrainedby FinalTerm annotation(choices(choice=redeclare Variant_2 test "NEW",
// choice=redeclare Variant_1 test "OLD"));
equation
c+d = b;
c+test.extra*d = time*a;
end Final;
model Variant_2
extends FinalTerm;
parameter Real e=0.5;
Real extra;
equation
extra = e;
end Variant_2;
end Example_2;
我的理解(或者至少我认为):
- 两者的区别examples/approaches。对于我打算的用途,我个人更喜欢 Hans 的方法(组件替换)。但是,要同时执行多个组件更换,Scott 的那个更合适。
- 'extends' 的使用不是强制性的。我发现的唯一用途是允许使用必须引用 ~common-mother-class~ 的 'constrainedby' (抱歉我的措辞不当);这与 Scott 提供的 'annotation' 相结合,允许在参数中有一个并非无用的下拉菜单(并且也可以与 Hans 的技术一起使用)。
一个小问题仍然悬而未决:根据 the previous webpage 应该可以手动定义 'annotation(choices())' 列表,但我没有成功(参见前面示例中的注释行)。这将允许适当的下拉菜单,而无需使用 "common-mother-class" 到 'extend' 和 'constrainedby' 关键字。有人知道我哪里错了吗?
您想使用 replaceable model
在模型之间切换而不是 if
语句。下面是一个基于您的示例的示例。我将留给您重新考虑如何正确地表述您的问题以正确使用可替换功能。希望对你有帮助。
在 Dymola 2017 FD01 中测试...
不确定 OMEdit 是否会处理 replaceable
正确使用,因为似乎存在一些仍在解决的长期问题:
https://trac.openmodelica.org/OpenModelica/ticket/2079.
package Example
model Test
// Simple test of the component "Final"
Final Final1(
redeclare model VarType = Variant_1,
redeclare Variant_2 varType2,
redeclare Example.Variant_3 varType3 "Test")
annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
end Test;
model Final
// Model demonstrating difference ways to use "replaceable"
extends ReplaceableModels.PartialModel;
replaceable model VarType = ReplaceableModels.Variant_1 constrainedby
ReplaceableModels.PartialVariants
annotation(choicesAllMatching=true);
VarType varType1;
replaceable ReplaceableModels.Variant_1 varType2 constrainedby
ReplaceableModels.PartialVariants annotation (choicesAllMatching=true);
replaceable ReplaceableModels.Variant_1 varType3 constrainedby
ReplaceableModels.PartialVariants annotation (choices(
choice(redeclare Example.Variant_1 varType3 "OLD"),
choice(redeclare Example.Variant_2 varType3 "NEW"),
choice(redeclare Example.Variant_3 varType3 "Test")));
equation
result1 = varType1.extra;
result2 = varType2.extra;
result3 = varType3.extra;
end Final;
model Variant_1
extends ReplaceableModels.PartialVariants;
parameter Real extra0=0;
equation
extra = extra0;
end Variant_1;
model Variant_2
extends ReplaceableModels.PartialVariants;
parameter Real a=1;
Real b;
Real c;
parameter Real e=0.5;
parameter Real d = 0.1;
equation
c+d = b;
c+extra = time*a;
extra = d*e;
end Variant_2;
model Variant_3
Real extra;
parameter Real a=1;
Real b;
Real c;
parameter Real e=0.5;
parameter Real d = 0.1;
equation
c+d = b;
c+extra = time*a;
extra = d*e;
end Variant_3;
partial model PartialModel
Real result1;
Real result2;
Real result3;
end PartialModel;
partial model PartialVariants
Real extra;
end PartialVariants;
end Example;
更新:
添加了注释,以便在图形用户界面中有一个用于模型选择的下拉箭头。
更新 2:
我已将原始代码替换为一个扩展示例,该示例根据发布者的附加问题演示了使用可替换的几种不同方法。该代码现在还包括创建的模型的 Test
(Final
) 和不从部分 class 扩展的 Variant_3 以显示 choices
如果对您的情况有用,注释还允许您包含额外的模型。
Scott G 解决方案的替代方案是使用可替换组件(以他的代码为基础):
package ReplaceableComponentTest
model Test2 "Showing how to change it"
extends Final(redeclare Example.Variant_2 varType);
end Test2;
model Final
extends Example.PartialModel;
replaceable Example.Variant_1 varType constrainedby
Example.PartialVariants annotation(choices(
choice(redeclare Example.Variant_2 test "NEW"),
choice(redeclare Example.Variant_1 test "OLD")));
equation
result = varType.extra;
end Final;
end ReplaceableComponentTest;
package Example
model Variant_1
extends Example.PartialVariants;
parameter Real extra0=0;
equation
extra = extra0;
end Variant_1;
model Variant_2
extends Example.PartialVariants;
parameter Real a=1;
Real b;
Real c;
parameter Real e=0.5;
parameter Real d = 0.1;
equation
c+d = b;
c+extra = time*a;
extra = d*e;
end Variant_2;
partial model PartialModel
Real result;
end PartialModel;
partial model PartialVariants
Real extra;
end PartialVariants;
end Example;
两者都适用于这种情况。请注意,我也添加了选择注释 - 为了安全起见,使用了 类 的全名(即使它应该有效)。
如果您有该模型的多个组件,则需要使用可替换模型,而在其他情况下,它更多的是风格问题。
我仍然可以推荐 https://modelica.org/events/Conference2003/Modelica03-AdvancedTutorial.pdf 的第五部分。