参数化 Modelica 库和使用模型作为参数的可能性 - 第 2 部分
Parametrised Modelica library and possibility to use models as parameters - part 2
我致力于了解库中的参数化包如何适应外部应用程序代码,即我喜欢将库代码和应用程序代码分开。
在我这里的示例中,我的包设备有两个参数,一个连接器 LCon 和一个模型 CType。连接器影响设备包中的所有模型。模型CType只影响Equipment中的一个模型RType(并且具有更紧密的内外关系)。
当我根据 LCon2 和 CType2 的应用要求调整封装设备时,我可以按如下方式一次性完成。
code1
package Equipment2
import BR5i.Equipment;
extends Equipment(redeclare connector LCon=LCon2,
redeclare model CType=CType2);
end Equipment2;
但是,我认为如果将这两个改编分成两个不同的部分,代码(在长 运行 中)更具可读性。我尝试下面的代码,但不起作用。错误文本:找不到 RType 的 class 声明 - 当我在 JModelica 中 运行 它时。
code2
package Equipment2
import BR5i.Equipment;
extends Equipment(redeclare connector LCon=LCon2);
end Equipment2;
model BRType2
import BR5i.Equipment2.RType;
extends RType(redeclare model CType=CType2);
end BRType2;
(对于代码 2,修改了库,因此将参数 CType 设备级别向下移动到单独的模型 RType,其中 CType 应作为参数。最后我希望代码 2 的 BRType2 对应于 Equipment2.RType 来自代码 1).
我想知道是否可以像这样分几个步骤进行更改,即首先 RType 获得一个新的连接器 LCon2,然后在下一步中,现在从 Equipment2 导入的 RType 应将 CType 替换为 CType2?
我明白代码不应该被看作是"assignment statements"的一个序列,而是并行的。在我看来,代码 2 中 "equations" 的逻辑应该可以得到正确的 BRType2.
您的 "code2" 将导致 BRType2 不 修改 CType。重新声明并不意味着 "change package A to look like this",而是 "this should be like package A, but with these changes"。所以要得到你想要的结果,你应该这样做:
package Equipment2
import BR5i.Equipment;
extends Equipment(redeclare connector LCon=LCon2);
end Equipment2;
model BRType2
// Equipment2 has the change in LCon, so extend RType from there instead
import Equipment2.RType;
extends RType(redeclare model CType=CType2);
end BRType2;
另请注意,如果 Equipment 包含 Rtype 的任何实例或对 Rtype 的其他引用,则此方法不会给出预期结果,因为它们将引用未更改的 RType,而不是 BRType2。
为什么你会收到关于找不到 RType 的错误,我不能说。这可能是一个错误,但我会先检查一下你是否正确编写了它的路径。
根据要求,我在这里提供了一个小的独立示例,大约 150 行。我决定重新使用我最近在其他几篇文章中使用的玩具示例,现在添加示例此处讨论的问题所需的内容。这意味着我使用的东西名称与上面写的不同,但问题的结构完全相同。
玩具示例描述了将介质从一个容器泵送到另一个容器的过程,并进行了通用化,以便我们可以轻松更换介质,并且泵和罐的设备会自动更新。最初,介质包含两种物质。通过单独的简短应用程序代码,我们定义了一个包含更多组件的介质,并通过重新声明连接器 LiquidCon 更新了包设备,然后系统设置被简单地重新使用。
现在我在收获中添加一个内部模型,描述物质之间的一些反应。最初我们有一个反应模型 NoReaction,它使收获罐中的物质不发生任何反应。另一个反应模型是显示物质 3 降解的反应 3。
我想强调的问题是,如果我们首先调整带有用于说三种物质的连接器的设备。然后在第二轮中将适配设备3的反应模型更改为反应模型Reaction3,然后JModelica编译器给出错误信息,而OpenModelica则没有并产生模拟结果就可以了。这在代码中标记为备选方案 2。
备选方案 1. 另一方面,如果两个非常不同的重新声明是同时完成的,即同时更改了连接器 LiquidCon 和模型 ReactionType,那么它在 JModelica 和 OpenModelica 中都有效。
下面的独立代码和示例测试现在是备选方案 2 并在 JModelica 2.4 中生成错误但在 OpenModelica 中有效。我不清楚对 Modelica def 本身有什么期望。
package DEMO_v14
// Here I have put together a small demo-library to illustrate questions
// around structuring handling of medium. The key structures are taken
// from MSL fluid, I think it is fair to say.
// Author: Jan Peter Axelsson
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium2
replaceable constant String name = "Two components" "Medium name";
replaceable constant Integer nc = 2 "Number of substances";
replaceable type Concentration = Real[nc] "Substance conc";
replaceable constant Real[nc] mw = {10, 20} "Substance weight";
constant Integer A = 1 "Substance index";
constant Integer B = 2 "Substance index";
end Medium2;
package Medium3
import M2 = DEMO_v14.Medium2;
extends M2
(name="Three components" "Medium name",
nc=3 "Number of substances",
mw = cat(1,M2.mw,{30}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
end Medium3;
connector LiquidCon3
Medium3.Concentration c "Substance conc";
flow Real F (unit="m3/s") "Flow rate";
end LiquidCon3;
model Reaction3
constant Integer nc = 3;
outer Real[nc] c;
outer Real[nc] q;
equation
q[1] = 0;
q[2] = 0;
q[3] =-c[3];
end Reaction3;
// ---------------------------------------------------------------------------------------------
// Equipment dependent on the medium
// ---------------------------------------------------------------------------------------------
package Equipment
replaceable connector LiquidCon
end LiquidCon;
// replaceable model ReactionType // Alternative 1
// end ReactionType;
model PumpType
LiquidCon inlet, outlet;
RealInput Fsp;
equation
inlet.F = Fsp;
connect(outlet, inlet);
end PumpType;
model FeedtankType
LiquidCon outlet;
constant Integer medium_nc = size(outlet.c,1);
parameter Real[medium_nc] c_in (each unit="kg/m3")
= {1.0*k for k in 1:medium_nc} "Feed inlet conc";
parameter Real V_0 (unit="m3") = 100 "Initial feed volume";
Real V(start=V_0, fixed=true, unit="m3") "Feed volume";
equation
for i in 1:medium_nc loop
outlet.c[i] = c_in[i];
end for;
der(V) = outlet.F;
end FeedtankType;
model HarvesttankType
// Connection to reaction
replaceable model ReactionType // Alternative 2
end ReactionType;
ReactionType reaction;
inner Real[medium_nc] c "Substance conc";
inner Real[medium_nc] q "Reaction rate";
LiquidCon inlet, port;
constant Integer medium_nc = size(inlet.c,1);
parameter Real V_0 (unit="m3") = 1.0 "Initial harvest liquid volume";
parameter Real[medium_nc] m_0
(each unit="kg/m3") = zeros(medium_nc) "Initial substance mass";
Real[medium_nc] m
(start=m_0, each fixed=true) "Substance mass";
Real V(start=V_0, fixed=true, unit="m3") "Harvest liquid volume";
equation
for i in 1:medium_nc loop
der(m[i]) = inlet.c[i]*inlet.F + q[i];
c[i] = m[i]/V;
port.c[i] = c[i];
end for;
der(V) = inlet.F;
end HarvesttankType;
model NoReaction
constant Integer nc = Medium.nc;
outer Real[nc] c;
outer Real[nc] q;
equation
for i in 1:nc loop
q[i] = 0;
end for;
end NoReaction;
end Equipment;
// ---------------------------------------------------------------------------------------------
// Control
// ---------------------------------------------------------------------------------------------
package Control
block FixValueType
RealOutput out;
parameter Real val=0;
equation
out = val;
end FixValueType;
end Control;
// ---------------------------------------------------------------------------------------------
// Adaptation of library for the actual culture and media
// ---------------------------------------------------------------------------------------------
// package Equipment3 // Alternative 1
// import DEMO_v14.Equipment;
// extends Equipment(redeclare connector LiquidCon=LiquidCon3,
// redeclare model ReactionType=Reaction3);
// end Equipment3;
package Equipment3 // Alternative 2
import DEMO_v14.Equipment;
extends Equipment(redeclare connector LiquidCon=LiquidCon3);
end Equipment3;
model HarvesttankType3
import DEMO_v14.Equipment3.HarvesttankType;
extends HarvesttankType(redeclare model ReactionType=Reaction3);
end HarvesttankType3;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
model Test
Medium3 medium;
Equipment3.FeedtankType feedtank;
// Equipment3.HarvesttankType harvesttank; // Alternative 1
HarvesttankType3 harvesttank; // Alternative 2
Equipment3.PumpType pump;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end DEMO_v14;
我没有时间详细分析你的问题,但我想在这里指出,如果一些代码在一个工具中被接受,但在另一个工具中不被接受,并不一定意味着这个错误是在不接受代码的工具中。随着时间的推移,Modelica 语义变得更加严格,使 Modelica 使用起来更安全,并且更容易跨工具移植。由于 OpenModelica 内核是最古老的内核之一,众所周知,在最新版本中接受很多实际上(在许多情况下不再)合法的 Modelica 代码。
抱歉,我没有时间从Modelica语义合法性的角度深入分析这个问题。无论如何,我相信您可以使用合法的 Modelica 实现您想要实现的目标。关于建模实践的两点评论:将空的 class (在您的情况下为连接器)作为可替换的 class 是不安全的,应该避免,因为它可以用任何东西替换,这本质上是不安全的.我还认为您可以通过连接器中的可变长度矢量实现您想要实现的目标,连接器本身不需要可更换。
祝你一切顺利,/Hubertus
我赞成这样的想法,即以安全的方式使库包参数化,您可以使灵活性尽可能“小”。你可以在包中有一个常量整数 nc ,你在调整包时给出数字 Medium3.nc 。然后连接器 LiquidCon 在包 Equipment 中定义,并将浓度向量声明为 Real [nc] c;除了 nc 之外,关于 Medium 的其他信息可以被带到配置级别的应用程序测试,而不是作为包设备的改编,并且在这个例子中没有讨论,但在其他相关帖子中讨论。这样,包适配过程将尽可能“安全”。
涉及将 ReactionType 引入 HarvesttankType 的其他改编(现在已改编为实际的 nc)需要非常灵活才能使该库包引起任何兴趣。我们对 ReactionType 的要求是具有接口:outer Real(nc] c, q; 并且我们可以在部分模型中描述并使用 constrainedby 构造,以带来一些安全性。
请参阅下面的代码 DEMO_v17_alt1 和 d17_alt1_app7。
但是,我更愿意将代码编写为 alt2,并只为 HarvesttankType 而不是为整个设备包定义 ReactionType 等。这将需要允许一个两步的图书馆改编程序。第一级使设备适应中型组件的数量。第二级将现在调整的 HarvesttankType 调整为 ReactionType。这在 JModelica 中是不可能的,但实际上在 OpenModelica 中。
所以只有 alt1 在 JModelica 2.4 中工作,而 alt1 和 alt2 在 OpenModelica 1.13.2(和 1.14 beta)中工作。当前的 Modelica 定义是怎么说的?
图书馆代码DEMO_v17_alt1:
package DEMO_v17_alt1
// Here I have put together a small demo-library to illustrate questions
// around structuring handling of medium. The key structures are taken
// from MSL fluid, I think it is fair to say.
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium2
replaceable constant String name = "Two components" "Medium name";
replaceable constant Integer nc = 2 "Number of substances";
replaceable type Concentration = Real[nc] "Substance conc";
replaceable constant Real[nc] mw = {10, 20} "Substance weight";
constant Integer A = 1 "Substance index";
constant Integer B = 2 "Substance index";
end Medium2;
package Medium3
import M2 = DEMO_v17_alt1.Medium2;
extends M2
(name="Three components" "Medium name",
nc=3 "Number of substances",
mw = cat(1,M2.mw,{30}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
end Medium3;
model Reaction3
constant Integer nc = 3;
outer Real[nc] c;
outer Real[nc] q;
equation
q[1] = 0;
q[2] = 0;
q[3] =-c[3];
end Reaction3;
// ---------------------------------------------------------------------------------------------
// Equipment dependent on the medium
// ---------------------------------------------------------------------------------------------
package Equipment
constant Integer nc;
connector LiquidCon
Real[nc] c "Substance conc";
flow Real F (unit="m3/s") "Flow rate";
end LiquidCon;
replaceable model ReactionType = NoReaction // Alternative 1
constrainedby ReactionTypeInterface;
partial model ReactionTypeInterface // Alternative 1
outer Real[nc] c, q;
end ReactionTypeInterface;
model NoReaction // Alternative 1
extends ReactionTypeInterface;
equation
for i in 1:nc loop
q[i] = 0;
end for;
end NoReaction;
model PumpType
LiquidCon inlet, outlet;
RealInput Fsp;
equation
inlet.F = Fsp;
connect(outlet, inlet);
end PumpType;
model FeedtankType
LiquidCon outlet;
constant Integer medium_nc = size(outlet.c,1);
parameter Real[medium_nc] c_in (each unit="kg/m3")
= {1.0*k for k in 1:medium_nc} "Feed inlet conc";
parameter Real V_0 (unit="m3") = 100 "Initial feed volume";
Real V(start=V_0, fixed=true, unit="m3") "Feed volume";
equation
for i in 1:medium_nc loop
outlet.c[i] = c_in[i];
end for;
der(V) = outlet.F;
end FeedtankType;
model HarvesttankType
// Connection to reaction
// replaceable model ReactionType = NoReaction constrainedby ReactionTypeInterface; // Alternative 2
ReactionType reaction;
inner Real[medium_nc] c "Substance conc";
inner Real[medium_nc] q "Reaction rate";
LiquidCon inlet, port;
constant Integer medium_nc = size(inlet.c,1);
parameter Real V_0 (unit="m3") = 1.0 "Initial harvest liquid volume";
parameter Real[medium_nc] m_0
(each unit="kg/m3") = zeros(medium_nc) "Initial substance mass";
Real[medium_nc] m
(start=m_0, each fixed=true) "Substance mass";
Real V(start=V_0, fixed=true, unit="m3") "Harvest liquid volume";
equation
for i in 1:medium_nc loop
der(m[i]) = inlet.c[i]*inlet.F + q[i];
c[i] = m[i]/V;
port.c[i] = c[i];
end for;
der(V) = inlet.F;
end HarvesttankType;
end Equipment;
// ---------------------------------------------------------------------------------------------
// Control
// ---------------------------------------------------------------------------------------------
package Control
block FixValueType
RealOutput out;
parameter Real val=0;
equation
out = val;
end FixValueType;
end Control;
// ---------------------------------------------------------------------------------------------
// Adaptation of library DEMO_v17_alt1 to Medium3 and Reaction3
// ---------------------------------------------------------------------------------------------
package Equipment3 // Alternative 1
import DEMO_v17_alt1.Equipment;
extends Equipment(nc=Medium3.nc,
redeclare model ReactionType=Reaction3);
end Equipment3;
// package Equipment3 // Alternative 2
// import DEMO_v17_alt2.Equipment;
// extends Equipment(nc=3);
// end Equipment3;
// model HarvesttankType3
// import DEMO_v17_alt2.Equipment3.HarvesttankType;
// extends HarvesttankType(redeclare model ReactionType=Reaction3);
// end HarvesttankType3;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
model Test
Medium3 medium;
Equipment3.FeedtankType feedtank;
Equipment3.HarvesttankType harvesttank; // Alternative 1
// HarvesttankType3 harvesttank; // Alternative 2
Equipment3.PumpType pump;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end DEMO_v17_alt1;
和申请代码d17_alt1_app7
encapsulated package d17_alt1_app7
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium7
import M2 = DEMO_v17_alt1.Medium2;
extends M2
(name = "Seven components" "Medium name",
nc = 7 "Number of substances",
mw = cat(1,M2.mw,{30,40,50,60,70}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
constant Integer D = 4 "Substance index";
constant Integer E = 5 "Substance index";
constant Integer F = 6 "Substance index";
constant Integer G = 7 "Substance index";
end Medium7;
model Reaction7
constant Integer nc = 7;
outer Real[nc] c;
outer Real[nc] q;
equation
q[1] = 0;
q[2] = 0;
q[3] = 0;
q[4] = 0;
q[5] = 0;
q[6] = 0;
q[7] =-c[7];
end Reaction7;
// ---------------------------------------------------------------------------------------------
// Adaptation of library DEMO_v17_alt1 to Medium7 and Reaction7
// ---------------------------------------------------------------------------------------------
package Equipment7
import DEMO_v17_alt1.Equipment;
extends Equipment(nc=Medium7.nc,
redeclare model ReactionType=Reaction7);
end Equipment7;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
import DEMO_v17_alt1.Control;
model Test
Medium7 medium; // Instance not necessary but helpful for user interface
Equipment7.PumpType pump;
Equipment7.FeedtankType feedtank;
Equipment7.HarvesttankType harvesttank;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end d17_alt1_app7;
我最近从与 Modelon 和 OpenModelica 相关的人员那里得到了一些关于这个主题的帮助,对此我深表感谢。下面是库和应用程序的更新文件。提供的代码在 JModelica 和 OpenModelica 中确实有效,现在在 Dymola 中也有效。
对已更正的代码错误的一些评论。
在模型测试中,我习惯于制作一个感兴趣的媒介实例。在 Modelica 中创建这样的包的实例实际上是不允许的(而且也不是很有意义),尽管 JModelica 和 OpenModelica 的当前版本支持它。我执行此包 Medium 实例的原因是 two-fold:
我通常需要在测试中(但在这个例子中不是)可以访问媒体包中的信息来进行配置。例如,如果我将传感器连接到收获罐并且该传感器是生殖器类型,那么我需要指定我想要测量的物质,最好使用包装介质中状态向量存储中的物质位置助记符来完成。我当然可以导入配置所需的助记符,一个一个地导入,但是更短,甚至更易读,只使用中等包。
从 FMU 能够访问中包中的信息是很好的。这个包可能不仅包含助记符,还包含我们在为 FMU 和交互式模拟设计 tailer-made 用户界面时要使用的介质的各种事实。这就是我在 Python 中使用 JModelica 所做的。这实际上工作得很好,就像现在使用 JModelica 和 PyFMI 一样,但我学到的东西在 Modelica 中是被禁止的。
我在几个地方把medium nc中的组件数传给了不同的设备型号。我使用连接器稍微 in-directly 传输 nc 并“测量”向量的大小。在编译时在 Modelica 中这样做是不行的 time.Also 这在 JModelica 和 OpenModelica 中都有效目前,但不在 Dymola 中。我通过在未指定的通用包 Equipment 中引入一个局部常量来解决此问题,但稍后在包适应应使用的介质时给出适当的数字。然后它得到值 medium.nc
我希望这些修改使代码更容易被接受,并且至少适用于 JModelica、OpenModelica 和 Dymola。但是,我对这些解决方案不太满意,因为它没有解决我的问题 user-requirements 如上所述。
此外,对于这个“解决方案”,“备选方案 2”——分两步(或更多步骤)调整库是不相关的——毕竟这是 post 中的关键问题。稍后我将尝试 re-formulate 这个问题,并在新的 post 中用一个较小的例子。
在库下面DEMO_v18_alt1然后是应用程序d18_alt1_app7
package DEMO_v18_alt1
// Here I have put together a small demo-library to illustrate questions
// around structuring handling of medium. The key structures are taken
// from MSL fluid, I think it is fair to say.
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium2
replaceable constant String name = "Two components" "Medium name";
replaceable constant Integer nc = 2 "Number of substances";
replaceable type Concentration = Real[nc] "Substance conc";
replaceable constant Real[nc] mw = {10, 20} "Substance weight";
constant Integer A = 1 "Substance index";
constant Integer B = 2 "Substance index";
end Medium2;
package Medium3
import M2 = DEMO_v18_alt1.Medium2;
extends M2
(name="Three components" "Medium name",
nc=3 "Number of substances",
mw = cat(1,M2.mw,{30}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
end Medium3;
model Reaction3
constant Integer nc = 3;
outer Real[nc] c;
outer Real[nc] q;
equation
q[1] = 0;
q[2] = 0;
q[3] =-c[3];
end Reaction3;
// ---------------------------------------------------------------------------------------------
// Equipment dependent on the medium
// ---------------------------------------------------------------------------------------------
package Equipment
constant Integer nc;
connector LiquidCon
Real[nc] c "Substance conc";
flow Real F (unit="m3/s") "Flow rate";
end LiquidCon;
replaceable model ReactionType = NoReaction // Alternative 1
constrainedby ReactionTypeInterface;
partial model ReactionTypeInterface // Alternative 1
outer Real[nc] c, q;
end ReactionTypeInterface;
model NoReaction // Alternative 1
extends ReactionTypeInterface;
equation
for i in 1:nc loop
q[i] = 0;
end for;
end NoReaction;
model PumpType
LiquidCon inlet, outlet;
RealInput Fsp;
equation
inlet.F = Fsp;
connect(outlet, inlet);
end PumpType;
model FeedtankType
LiquidCon outlet;
parameter Real[nc] c_in (each unit="kg/m3")
= {1.0*k for k in 1:nc} "Feed inlet conc";
parameter Real V_0 (unit="m3") = 100 "Initial feed volume";
Real V(start=V_0, fixed=true, unit="m3") "Feed volume";
equation
for i in 1:nc loop
outlet.c[i] = c_in[i];
end for;
der(V) = outlet.F;
end FeedtankType;
model HarvesttankType
// Connection to reaction
// replaceable model ReactionType = NoReaction constrainedby ReactionTypeInterface; // Alternative 2
ReactionType reaction;
inner Real[nc] c "Substance conc";
inner Real[nc] q "Reaction rate";
LiquidCon inlet, port;
parameter Real V_0 (unit="m3") = 1.0 "Initial harvest liquid volume";
parameter Real[nc] m_0
(each unit="kg/m3") = zeros(nc) "Initial substance mass";
Real[nc] m
(start=m_0, each fixed=true) "Substance mass";
Real V(start=V_0, fixed=true, unit="m3") "Harvest liquid volume";
equation
for i in 1:nc loop
der(m[i]) = inlet.c[i]*inlet.F + q[i];
c[i] = m[i]/V;
port.c[i] = c[i];
end for;
der(V) = inlet.F;
end HarvesttankType;
end Equipment;
// ---------------------------------------------------------------------------------------------
// Control
// ---------------------------------------------------------------------------------------------
package Control
block FixValueType
RealOutput out;
parameter Real val=0;
equation
out = val;
end FixValueType;
end Control;
// ---------------------------------------------------------------------------------------------
// Adaptation of library for the actual culture and media
// ---------------------------------------------------------------------------------------------
package Equipment3 // Alternative 1
import DEMO_v18_alt1.Equipment;
extends Equipment(nc=Medium3.nc,
redeclare model ReactionType=Reaction3);
end Equipment3;
// package Equipment3 // Alternative 2
// import DEMO_v18_alt2.Equipment;
// extends Equipment(nc=Medium3.nc);
// end Equipment3;
// model HarvesttankType3
// import DEMO_v18_alt2.Equipment3.HarvesttankType;
// extends HarvesttankType(redeclare model ReactionType=Reaction3);
// end HarvesttankType3;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
model Test
package medium = DEMO_v18_alt1.Medium3; // Not accessible in FMU though
Equipment3.FeedtankType feedtank;
Equipment3.HarvesttankType harvesttank; // Alternative 1
// HarvesttankType3 harvesttank; // Alternative 2
Equipment3.PumpType pump;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end DEMO_v18_alt1;
这里是申请代码
encapsulated package d18_alt1_app7
// Here I put together an application for 7 substances - print 8 pt
// and import code from the library DEMO.
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium7
import M2 = DEMO_v18_alt1.Medium2;
extends M2
(name = "Seven components" "Medium name",
nc = 7 "Number of substances",
mw = cat(1,M2.mw,{30,40,50,60,70}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
constant Integer D = 4 "Substance index";
constant Integer E = 5 "Substance index";
constant Integer F = 6 "Substance index";
constant Integer G = 7 "Substance index";
end Medium7;
model Reaction7
constant Integer nc = 7;
outer Real[nc] c;
outer Real[nc] q;
equation
q[1] = 0;
q[2] = 0;
q[3] = 0;
q[4] = 0;
q[5] = 0;
q[6] = 0;
q[7] =-c[7];
end Reaction7;
// ---------------------------------------------------------------------------------------------
// Adaptation of library DEMO_v18_alt1 to Medium7 and Reaction7
// ---------------------------------------------------------------------------------------------
package Equipment7
import DEMO_v18_alt1.Equipment;
extends Equipment(nc=Medium7.nc,
redeclare model ReactionType=Reaction7);
end Equipment7;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
import DEMO_v18_alt1.Control;
model Test
package medium = d18_alt1_app7.Medium7; // Not accessible in FMU though
Equipment7.PumpType pump;
Equipment7.FeedtankType feedtank;
Equipment7.HarvesttankType harvesttank;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end d18_alt1_app7;
我致力于了解库中的参数化包如何适应外部应用程序代码,即我喜欢将库代码和应用程序代码分开。
在我这里的示例中,我的包设备有两个参数,一个连接器 LCon 和一个模型 CType。连接器影响设备包中的所有模型。模型CType只影响Equipment中的一个模型RType(并且具有更紧密的内外关系)。
当我根据 LCon2 和 CType2 的应用要求调整封装设备时,我可以按如下方式一次性完成。
code1
package Equipment2
import BR5i.Equipment;
extends Equipment(redeclare connector LCon=LCon2,
redeclare model CType=CType2);
end Equipment2;
但是,我认为如果将这两个改编分成两个不同的部分,代码(在长 运行 中)更具可读性。我尝试下面的代码,但不起作用。错误文本:找不到 RType 的 class 声明 - 当我在 JModelica 中 运行 它时。
code2
package Equipment2
import BR5i.Equipment;
extends Equipment(redeclare connector LCon=LCon2);
end Equipment2;
model BRType2
import BR5i.Equipment2.RType;
extends RType(redeclare model CType=CType2);
end BRType2;
(对于代码 2,修改了库,因此将参数 CType 设备级别向下移动到单独的模型 RType,其中 CType 应作为参数。最后我希望代码 2 的 BRType2 对应于 Equipment2.RType 来自代码 1).
我想知道是否可以像这样分几个步骤进行更改,即首先 RType 获得一个新的连接器 LCon2,然后在下一步中,现在从 Equipment2 导入的 RType 应将 CType 替换为 CType2?
我明白代码不应该被看作是"assignment statements"的一个序列,而是并行的。在我看来,代码 2 中 "equations" 的逻辑应该可以得到正确的 BRType2.
您的 "code2" 将导致 BRType2 不 修改 CType。重新声明并不意味着 "change package A to look like this",而是 "this should be like package A, but with these changes"。所以要得到你想要的结果,你应该这样做:
package Equipment2
import BR5i.Equipment;
extends Equipment(redeclare connector LCon=LCon2);
end Equipment2;
model BRType2
// Equipment2 has the change in LCon, so extend RType from there instead
import Equipment2.RType;
extends RType(redeclare model CType=CType2);
end BRType2;
另请注意,如果 Equipment 包含 Rtype 的任何实例或对 Rtype 的其他引用,则此方法不会给出预期结果,因为它们将引用未更改的 RType,而不是 BRType2。
为什么你会收到关于找不到 RType 的错误,我不能说。这可能是一个错误,但我会先检查一下你是否正确编写了它的路径。
根据要求,我在这里提供了一个小的独立示例,大约 150 行。我决定重新使用我最近在其他几篇文章中使用的玩具示例,现在添加示例此处讨论的问题所需的内容。这意味着我使用的东西名称与上面写的不同,但问题的结构完全相同。
玩具示例描述了将介质从一个容器泵送到另一个容器的过程,并进行了通用化,以便我们可以轻松更换介质,并且泵和罐的设备会自动更新。最初,介质包含两种物质。通过单独的简短应用程序代码,我们定义了一个包含更多组件的介质,并通过重新声明连接器 LiquidCon 更新了包设备,然后系统设置被简单地重新使用。
现在我在收获中添加一个内部模型,描述物质之间的一些反应。最初我们有一个反应模型 NoReaction,它使收获罐中的物质不发生任何反应。另一个反应模型是显示物质 3 降解的反应 3。
我想强调的问题是,如果我们首先调整带有用于说三种物质的连接器的设备。然后在第二轮中将适配设备3的反应模型更改为反应模型Reaction3,然后JModelica编译器给出错误信息,而OpenModelica则没有并产生模拟结果就可以了。这在代码中标记为备选方案 2。
备选方案 1. 另一方面,如果两个非常不同的重新声明是同时完成的,即同时更改了连接器 LiquidCon 和模型 ReactionType,那么它在 JModelica 和 OpenModelica 中都有效。
下面的独立代码和示例测试现在是备选方案 2 并在 JModelica 2.4 中生成错误但在 OpenModelica 中有效。我不清楚对 Modelica def 本身有什么期望。
package DEMO_v14
// Here I have put together a small demo-library to illustrate questions
// around structuring handling of medium. The key structures are taken
// from MSL fluid, I think it is fair to say.
// Author: Jan Peter Axelsson
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium2
replaceable constant String name = "Two components" "Medium name";
replaceable constant Integer nc = 2 "Number of substances";
replaceable type Concentration = Real[nc] "Substance conc";
replaceable constant Real[nc] mw = {10, 20} "Substance weight";
constant Integer A = 1 "Substance index";
constant Integer B = 2 "Substance index";
end Medium2;
package Medium3
import M2 = DEMO_v14.Medium2;
extends M2
(name="Three components" "Medium name",
nc=3 "Number of substances",
mw = cat(1,M2.mw,{30}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
end Medium3;
connector LiquidCon3
Medium3.Concentration c "Substance conc";
flow Real F (unit="m3/s") "Flow rate";
end LiquidCon3;
model Reaction3
constant Integer nc = 3;
outer Real[nc] c;
outer Real[nc] q;
equation
q[1] = 0;
q[2] = 0;
q[3] =-c[3];
end Reaction3;
// ---------------------------------------------------------------------------------------------
// Equipment dependent on the medium
// ---------------------------------------------------------------------------------------------
package Equipment
replaceable connector LiquidCon
end LiquidCon;
// replaceable model ReactionType // Alternative 1
// end ReactionType;
model PumpType
LiquidCon inlet, outlet;
RealInput Fsp;
equation
inlet.F = Fsp;
connect(outlet, inlet);
end PumpType;
model FeedtankType
LiquidCon outlet;
constant Integer medium_nc = size(outlet.c,1);
parameter Real[medium_nc] c_in (each unit="kg/m3")
= {1.0*k for k in 1:medium_nc} "Feed inlet conc";
parameter Real V_0 (unit="m3") = 100 "Initial feed volume";
Real V(start=V_0, fixed=true, unit="m3") "Feed volume";
equation
for i in 1:medium_nc loop
outlet.c[i] = c_in[i];
end for;
der(V) = outlet.F;
end FeedtankType;
model HarvesttankType
// Connection to reaction
replaceable model ReactionType // Alternative 2
end ReactionType;
ReactionType reaction;
inner Real[medium_nc] c "Substance conc";
inner Real[medium_nc] q "Reaction rate";
LiquidCon inlet, port;
constant Integer medium_nc = size(inlet.c,1);
parameter Real V_0 (unit="m3") = 1.0 "Initial harvest liquid volume";
parameter Real[medium_nc] m_0
(each unit="kg/m3") = zeros(medium_nc) "Initial substance mass";
Real[medium_nc] m
(start=m_0, each fixed=true) "Substance mass";
Real V(start=V_0, fixed=true, unit="m3") "Harvest liquid volume";
equation
for i in 1:medium_nc loop
der(m[i]) = inlet.c[i]*inlet.F + q[i];
c[i] = m[i]/V;
port.c[i] = c[i];
end for;
der(V) = inlet.F;
end HarvesttankType;
model NoReaction
constant Integer nc = Medium.nc;
outer Real[nc] c;
outer Real[nc] q;
equation
for i in 1:nc loop
q[i] = 0;
end for;
end NoReaction;
end Equipment;
// ---------------------------------------------------------------------------------------------
// Control
// ---------------------------------------------------------------------------------------------
package Control
block FixValueType
RealOutput out;
parameter Real val=0;
equation
out = val;
end FixValueType;
end Control;
// ---------------------------------------------------------------------------------------------
// Adaptation of library for the actual culture and media
// ---------------------------------------------------------------------------------------------
// package Equipment3 // Alternative 1
// import DEMO_v14.Equipment;
// extends Equipment(redeclare connector LiquidCon=LiquidCon3,
// redeclare model ReactionType=Reaction3);
// end Equipment3;
package Equipment3 // Alternative 2
import DEMO_v14.Equipment;
extends Equipment(redeclare connector LiquidCon=LiquidCon3);
end Equipment3;
model HarvesttankType3
import DEMO_v14.Equipment3.HarvesttankType;
extends HarvesttankType(redeclare model ReactionType=Reaction3);
end HarvesttankType3;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
model Test
Medium3 medium;
Equipment3.FeedtankType feedtank;
// Equipment3.HarvesttankType harvesttank; // Alternative 1
HarvesttankType3 harvesttank; // Alternative 2
Equipment3.PumpType pump;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end DEMO_v14;
我没有时间详细分析你的问题,但我想在这里指出,如果一些代码在一个工具中被接受,但在另一个工具中不被接受,并不一定意味着这个错误是在不接受代码的工具中。随着时间的推移,Modelica 语义变得更加严格,使 Modelica 使用起来更安全,并且更容易跨工具移植。由于 OpenModelica 内核是最古老的内核之一,众所周知,在最新版本中接受很多实际上(在许多情况下不再)合法的 Modelica 代码。
抱歉,我没有时间从Modelica语义合法性的角度深入分析这个问题。无论如何,我相信您可以使用合法的 Modelica 实现您想要实现的目标。关于建模实践的两点评论:将空的 class (在您的情况下为连接器)作为可替换的 class 是不安全的,应该避免,因为它可以用任何东西替换,这本质上是不安全的.我还认为您可以通过连接器中的可变长度矢量实现您想要实现的目标,连接器本身不需要可更换。
祝你一切顺利,/Hubertus
我赞成这样的想法,即以安全的方式使库包参数化,您可以使灵活性尽可能“小”。你可以在包中有一个常量整数 nc ,你在调整包时给出数字 Medium3.nc 。然后连接器 LiquidCon 在包 Equipment 中定义,并将浓度向量声明为 Real [nc] c;除了 nc 之外,关于 Medium 的其他信息可以被带到配置级别的应用程序测试,而不是作为包设备的改编,并且在这个例子中没有讨论,但在其他相关帖子中讨论。这样,包适配过程将尽可能“安全”。
涉及将 ReactionType 引入 HarvesttankType 的其他改编(现在已改编为实际的 nc)需要非常灵活才能使该库包引起任何兴趣。我们对 ReactionType 的要求是具有接口:outer Real(nc] c, q; 并且我们可以在部分模型中描述并使用 constrainedby 构造,以带来一些安全性。
请参阅下面的代码 DEMO_v17_alt1 和 d17_alt1_app7。
但是,我更愿意将代码编写为 alt2,并只为 HarvesttankType 而不是为整个设备包定义 ReactionType 等。这将需要允许一个两步的图书馆改编程序。第一级使设备适应中型组件的数量。第二级将现在调整的 HarvesttankType 调整为 ReactionType。这在 JModelica 中是不可能的,但实际上在 OpenModelica 中。
所以只有 alt1 在 JModelica 2.4 中工作,而 alt1 和 alt2 在 OpenModelica 1.13.2(和 1.14 beta)中工作。当前的 Modelica 定义是怎么说的?
图书馆代码DEMO_v17_alt1:
package DEMO_v17_alt1
// Here I have put together a small demo-library to illustrate questions
// around structuring handling of medium. The key structures are taken
// from MSL fluid, I think it is fair to say.
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium2
replaceable constant String name = "Two components" "Medium name";
replaceable constant Integer nc = 2 "Number of substances";
replaceable type Concentration = Real[nc] "Substance conc";
replaceable constant Real[nc] mw = {10, 20} "Substance weight";
constant Integer A = 1 "Substance index";
constant Integer B = 2 "Substance index";
end Medium2;
package Medium3
import M2 = DEMO_v17_alt1.Medium2;
extends M2
(name="Three components" "Medium name",
nc=3 "Number of substances",
mw = cat(1,M2.mw,{30}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
end Medium3;
model Reaction3
constant Integer nc = 3;
outer Real[nc] c;
outer Real[nc] q;
equation
q[1] = 0;
q[2] = 0;
q[3] =-c[3];
end Reaction3;
// ---------------------------------------------------------------------------------------------
// Equipment dependent on the medium
// ---------------------------------------------------------------------------------------------
package Equipment
constant Integer nc;
connector LiquidCon
Real[nc] c "Substance conc";
flow Real F (unit="m3/s") "Flow rate";
end LiquidCon;
replaceable model ReactionType = NoReaction // Alternative 1
constrainedby ReactionTypeInterface;
partial model ReactionTypeInterface // Alternative 1
outer Real[nc] c, q;
end ReactionTypeInterface;
model NoReaction // Alternative 1
extends ReactionTypeInterface;
equation
for i in 1:nc loop
q[i] = 0;
end for;
end NoReaction;
model PumpType
LiquidCon inlet, outlet;
RealInput Fsp;
equation
inlet.F = Fsp;
connect(outlet, inlet);
end PumpType;
model FeedtankType
LiquidCon outlet;
constant Integer medium_nc = size(outlet.c,1);
parameter Real[medium_nc] c_in (each unit="kg/m3")
= {1.0*k for k in 1:medium_nc} "Feed inlet conc";
parameter Real V_0 (unit="m3") = 100 "Initial feed volume";
Real V(start=V_0, fixed=true, unit="m3") "Feed volume";
equation
for i in 1:medium_nc loop
outlet.c[i] = c_in[i];
end for;
der(V) = outlet.F;
end FeedtankType;
model HarvesttankType
// Connection to reaction
// replaceable model ReactionType = NoReaction constrainedby ReactionTypeInterface; // Alternative 2
ReactionType reaction;
inner Real[medium_nc] c "Substance conc";
inner Real[medium_nc] q "Reaction rate";
LiquidCon inlet, port;
constant Integer medium_nc = size(inlet.c,1);
parameter Real V_0 (unit="m3") = 1.0 "Initial harvest liquid volume";
parameter Real[medium_nc] m_0
(each unit="kg/m3") = zeros(medium_nc) "Initial substance mass";
Real[medium_nc] m
(start=m_0, each fixed=true) "Substance mass";
Real V(start=V_0, fixed=true, unit="m3") "Harvest liquid volume";
equation
for i in 1:medium_nc loop
der(m[i]) = inlet.c[i]*inlet.F + q[i];
c[i] = m[i]/V;
port.c[i] = c[i];
end for;
der(V) = inlet.F;
end HarvesttankType;
end Equipment;
// ---------------------------------------------------------------------------------------------
// Control
// ---------------------------------------------------------------------------------------------
package Control
block FixValueType
RealOutput out;
parameter Real val=0;
equation
out = val;
end FixValueType;
end Control;
// ---------------------------------------------------------------------------------------------
// Adaptation of library DEMO_v17_alt1 to Medium3 and Reaction3
// ---------------------------------------------------------------------------------------------
package Equipment3 // Alternative 1
import DEMO_v17_alt1.Equipment;
extends Equipment(nc=Medium3.nc,
redeclare model ReactionType=Reaction3);
end Equipment3;
// package Equipment3 // Alternative 2
// import DEMO_v17_alt2.Equipment;
// extends Equipment(nc=3);
// end Equipment3;
// model HarvesttankType3
// import DEMO_v17_alt2.Equipment3.HarvesttankType;
// extends HarvesttankType(redeclare model ReactionType=Reaction3);
// end HarvesttankType3;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
model Test
Medium3 medium;
Equipment3.FeedtankType feedtank;
Equipment3.HarvesttankType harvesttank; // Alternative 1
// HarvesttankType3 harvesttank; // Alternative 2
Equipment3.PumpType pump;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end DEMO_v17_alt1;
和申请代码d17_alt1_app7
encapsulated package d17_alt1_app7
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium7
import M2 = DEMO_v17_alt1.Medium2;
extends M2
(name = "Seven components" "Medium name",
nc = 7 "Number of substances",
mw = cat(1,M2.mw,{30,40,50,60,70}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
constant Integer D = 4 "Substance index";
constant Integer E = 5 "Substance index";
constant Integer F = 6 "Substance index";
constant Integer G = 7 "Substance index";
end Medium7;
model Reaction7
constant Integer nc = 7;
outer Real[nc] c;
outer Real[nc] q;
equation
q[1] = 0;
q[2] = 0;
q[3] = 0;
q[4] = 0;
q[5] = 0;
q[6] = 0;
q[7] =-c[7];
end Reaction7;
// ---------------------------------------------------------------------------------------------
// Adaptation of library DEMO_v17_alt1 to Medium7 and Reaction7
// ---------------------------------------------------------------------------------------------
package Equipment7
import DEMO_v17_alt1.Equipment;
extends Equipment(nc=Medium7.nc,
redeclare model ReactionType=Reaction7);
end Equipment7;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
import DEMO_v17_alt1.Control;
model Test
Medium7 medium; // Instance not necessary but helpful for user interface
Equipment7.PumpType pump;
Equipment7.FeedtankType feedtank;
Equipment7.HarvesttankType harvesttank;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end d17_alt1_app7;
我最近从与 Modelon 和 OpenModelica 相关的人员那里得到了一些关于这个主题的帮助,对此我深表感谢。下面是库和应用程序的更新文件。提供的代码在 JModelica 和 OpenModelica 中确实有效,现在在 Dymola 中也有效。
对已更正的代码错误的一些评论。
在模型测试中,我习惯于制作一个感兴趣的媒介实例。在 Modelica 中创建这样的包的实例实际上是不允许的(而且也不是很有意义),尽管 JModelica 和 OpenModelica 的当前版本支持它。我执行此包 Medium 实例的原因是 two-fold:
我通常需要在测试中(但在这个例子中不是)可以访问媒体包中的信息来进行配置。例如,如果我将传感器连接到收获罐并且该传感器是生殖器类型,那么我需要指定我想要测量的物质,最好使用包装介质中状态向量存储中的物质位置助记符来完成。我当然可以导入配置所需的助记符,一个一个地导入,但是更短,甚至更易读,只使用中等包。
从 FMU 能够访问中包中的信息是很好的。这个包可能不仅包含助记符,还包含我们在为 FMU 和交互式模拟设计 tailer-made 用户界面时要使用的介质的各种事实。这就是我在 Python 中使用 JModelica 所做的。这实际上工作得很好,就像现在使用 JModelica 和 PyFMI 一样,但我学到的东西在 Modelica 中是被禁止的。
我在几个地方把medium nc中的组件数传给了不同的设备型号。我使用连接器稍微 in-directly 传输 nc 并“测量”向量的大小。在编译时在 Modelica 中这样做是不行的 time.Also 这在 JModelica 和 OpenModelica 中都有效目前,但不在 Dymola 中。我通过在未指定的通用包 Equipment 中引入一个局部常量来解决此问题,但稍后在包适应应使用的介质时给出适当的数字。然后它得到值 medium.nc
我希望这些修改使代码更容易被接受,并且至少适用于 JModelica、OpenModelica 和 Dymola。但是,我对这些解决方案不太满意,因为它没有解决我的问题 user-requirements 如上所述。
此外,对于这个“解决方案”,“备选方案 2”——分两步(或更多步骤)调整库是不相关的——毕竟这是 post 中的关键问题。稍后我将尝试 re-formulate 这个问题,并在新的 post 中用一个较小的例子。
在库下面DEMO_v18_alt1然后是应用程序d18_alt1_app7
package DEMO_v18_alt1
// Here I have put together a small demo-library to illustrate questions
// around structuring handling of medium. The key structures are taken
// from MSL fluid, I think it is fair to say.
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium2
replaceable constant String name = "Two components" "Medium name";
replaceable constant Integer nc = 2 "Number of substances";
replaceable type Concentration = Real[nc] "Substance conc";
replaceable constant Real[nc] mw = {10, 20} "Substance weight";
constant Integer A = 1 "Substance index";
constant Integer B = 2 "Substance index";
end Medium2;
package Medium3
import M2 = DEMO_v18_alt1.Medium2;
extends M2
(name="Three components" "Medium name",
nc=3 "Number of substances",
mw = cat(1,M2.mw,{30}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
end Medium3;
model Reaction3
constant Integer nc = 3;
outer Real[nc] c;
outer Real[nc] q;
equation
q[1] = 0;
q[2] = 0;
q[3] =-c[3];
end Reaction3;
// ---------------------------------------------------------------------------------------------
// Equipment dependent on the medium
// ---------------------------------------------------------------------------------------------
package Equipment
constant Integer nc;
connector LiquidCon
Real[nc] c "Substance conc";
flow Real F (unit="m3/s") "Flow rate";
end LiquidCon;
replaceable model ReactionType = NoReaction // Alternative 1
constrainedby ReactionTypeInterface;
partial model ReactionTypeInterface // Alternative 1
outer Real[nc] c, q;
end ReactionTypeInterface;
model NoReaction // Alternative 1
extends ReactionTypeInterface;
equation
for i in 1:nc loop
q[i] = 0;
end for;
end NoReaction;
model PumpType
LiquidCon inlet, outlet;
RealInput Fsp;
equation
inlet.F = Fsp;
connect(outlet, inlet);
end PumpType;
model FeedtankType
LiquidCon outlet;
parameter Real[nc] c_in (each unit="kg/m3")
= {1.0*k for k in 1:nc} "Feed inlet conc";
parameter Real V_0 (unit="m3") = 100 "Initial feed volume";
Real V(start=V_0, fixed=true, unit="m3") "Feed volume";
equation
for i in 1:nc loop
outlet.c[i] = c_in[i];
end for;
der(V) = outlet.F;
end FeedtankType;
model HarvesttankType
// Connection to reaction
// replaceable model ReactionType = NoReaction constrainedby ReactionTypeInterface; // Alternative 2
ReactionType reaction;
inner Real[nc] c "Substance conc";
inner Real[nc] q "Reaction rate";
LiquidCon inlet, port;
parameter Real V_0 (unit="m3") = 1.0 "Initial harvest liquid volume";
parameter Real[nc] m_0
(each unit="kg/m3") = zeros(nc) "Initial substance mass";
Real[nc] m
(start=m_0, each fixed=true) "Substance mass";
Real V(start=V_0, fixed=true, unit="m3") "Harvest liquid volume";
equation
for i in 1:nc loop
der(m[i]) = inlet.c[i]*inlet.F + q[i];
c[i] = m[i]/V;
port.c[i] = c[i];
end for;
der(V) = inlet.F;
end HarvesttankType;
end Equipment;
// ---------------------------------------------------------------------------------------------
// Control
// ---------------------------------------------------------------------------------------------
package Control
block FixValueType
RealOutput out;
parameter Real val=0;
equation
out = val;
end FixValueType;
end Control;
// ---------------------------------------------------------------------------------------------
// Adaptation of library for the actual culture and media
// ---------------------------------------------------------------------------------------------
package Equipment3 // Alternative 1
import DEMO_v18_alt1.Equipment;
extends Equipment(nc=Medium3.nc,
redeclare model ReactionType=Reaction3);
end Equipment3;
// package Equipment3 // Alternative 2
// import DEMO_v18_alt2.Equipment;
// extends Equipment(nc=Medium3.nc);
// end Equipment3;
// model HarvesttankType3
// import DEMO_v18_alt2.Equipment3.HarvesttankType;
// extends HarvesttankType(redeclare model ReactionType=Reaction3);
// end HarvesttankType3;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
model Test
package medium = DEMO_v18_alt1.Medium3; // Not accessible in FMU though
Equipment3.FeedtankType feedtank;
Equipment3.HarvesttankType harvesttank; // Alternative 1
// HarvesttankType3 harvesttank; // Alternative 2
Equipment3.PumpType pump;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end DEMO_v18_alt1;
这里是申请代码
encapsulated package d18_alt1_app7
// Here I put together an application for 7 substances - print 8 pt
// and import code from the library DEMO.
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium7
import M2 = DEMO_v18_alt1.Medium2;
extends M2
(name = "Seven components" "Medium name",
nc = 7 "Number of substances",
mw = cat(1,M2.mw,{30,40,50,60,70}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
constant Integer D = 4 "Substance index";
constant Integer E = 5 "Substance index";
constant Integer F = 6 "Substance index";
constant Integer G = 7 "Substance index";
end Medium7;
model Reaction7
constant Integer nc = 7;
outer Real[nc] c;
outer Real[nc] q;
equation
q[1] = 0;
q[2] = 0;
q[3] = 0;
q[4] = 0;
q[5] = 0;
q[6] = 0;
q[7] =-c[7];
end Reaction7;
// ---------------------------------------------------------------------------------------------
// Adaptation of library DEMO_v18_alt1 to Medium7 and Reaction7
// ---------------------------------------------------------------------------------------------
package Equipment7
import DEMO_v18_alt1.Equipment;
extends Equipment(nc=Medium7.nc,
redeclare model ReactionType=Reaction7);
end Equipment7;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
import DEMO_v18_alt1.Control;
model Test
package medium = d18_alt1_app7.Medium7; // Not accessible in FMU though
Equipment7.PumpType pump;
Equipment7.FeedtankType feedtank;
Equipment7.HarvesttankType harvesttank;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end d18_alt1_app7;