化学组件¶
在最后一个基于组件建模的例子里,我们会再次回顾在向量与数组章节内介绍的化学系统。不过,这次我们将创建各种效应的组件模型,并演示Modelica内的连接是如何自动确保种类的守恒。
种类¶
我们在本例中将要处理的物质类型由以下enumeration
定义:
within ModelicaByExample.Components.ChemicalReactions.ABX;
type Species = enumeration(A, B, X);
请注意,这个定义在一个名为ABX
的包内。这表示该组件模型要在涉及A
、B
和X
的系统内正常工作。
Mixture
¶
下列connector
定义也包含在ABX
包内(这可以在Interfaces
子包中找到):
within ModelicaByExample.Components.ChemicalReactions.ABX.Interfaces;
connector Mixture
Modelica.SIunits.Concentration C[Species];
flow ConcentrationRate R[Species];
end Mixture;
在这里我们看到,我们的Mixture
连接器使用浓度为穿越变量,浓度变化率为流变量。虽然,在这种情况下flow
变量不是严格意义上的守恒量的流。但在本例中,由于所有反应都包含在相同的容器内,这样的定义足够了。
请注意,连接器里的C
和R
均为数组。而其下标由enumeration
类型给出。我们之前就看到过枚举类的这种用法。
Solution
¶
我们的第一个组件模型用于追踪控制体积内各种化学物质的浓度。正如前面所提到的,由于所有反应发生在同一体积内,我们实际上不需要指定控制体积的大小。
Solution
模型很简单。如同在本章前面部分讨论过的RegionalPopulation
模型,与模型唯一连接器相关联的横跨变量的变化率等于该连接器中的flow
变量:
within ModelicaByExample.Components.ChemicalReactions.ABX.Components;
model Solution "A mixture of species A, B and X"
Interfaces.Mixture mixture
annotation (Placement(transformation(extent={{90,-10},{110,10}})));
Modelica.SIunits.Concentration C[Species]=mixture.C
annotation(Dialog(group="Initialization",showStartAttribute=true));
equation
der(mixture.C) = mixture.R;
end Solution;
反应¶
Reaction
¶
正如我们之前所看到的,该系统有三种化学反应。我们将研究的每个具体的反应,都会扩展自以下partial
模型:
within ModelicaByExample.Components.ChemicalReactions.ABX.Interfaces;
partial model Reaction "A reaction potentially involving species A, B and X"
parameter Real k "Reaction coefficient";
Mixture mixture
annotation (Placement(transformation(extent={{-110,-10},{-90,10}})));
protected
ConcentrationRate consumed[Species];
ConcentrationRate produced[Species];
Modelica.SIunits.Concentration C[Species] = mixture.C;
equation
consumed = -produced;
mixture.R = consumed;
end Reaction;
我们看到,每个反应有反应系数k
和Mixture
类型的连接器mixture
。而mixture
连接器则连接到反应发生的Solution
部件中。内部向量值变量consumed
和produced
起到的作用类似于在本章前面部分介绍过的SinkOrSource
内的decline
和growth
变量(即使用这些变量,我们就可以将每个反应的作用以一种直观的方法描述出来。)
A+B->X
¶
第一个完整反应模型中,我们将考虑的是一个A
分子,一个B
分子合成一个X
分子。使用Reaction
模型,我们可以如下对这种反应进行建模:
model 'A+B->X' "A+B -> X"
extends Interfaces.Reaction;
protected
Interfaces.ConcentrationRate R = k*C[Species.A]*C[Species.B];
equation
consumed[Species.A] = R;
consumed[Species.B] = R;
produced[Species.X] = R;
end 'A+B->X';
该模型的第一个特点在于,它是由非字母数字字符组成的。具体来说,模型的名称中包含+
、-
、>
。只要名称是用单引号字符引用,这在Modelica是允许的。反应速率R
与继承自Reaction
模型的consumed
以及produced
变量配合使用。由此就可以清楚描述该反应中反应物和产物的方程式。
A+B<-X
¶
我们会考虑的下一个反应是将一个X
分子转换成(回)一个A
分子和一个B
分子。这与之前的反应相反。该反应的Modelica代码为:
model 'A+B<-X' "A+B <- X"
extends Interfaces.Reaction;
protected
Interfaces.ConcentrationRate R = k*C[Species.X];
equation
produced[Species.A] = R;
produced[Species.B] = R;
consumed[Species.X] = R;
end 'A+B<-X';
同样,方程清楚表达了哪些种类是反应物(即反应中的消耗),而那些是产物(即反应所产生的物质)。
X+B->R+S
¶
我们的最后一个反应将X
分子和B
分子转化成R
分子和S
分子:
model 'X+B->R+S' "X+B->R+S"
extends Interfaces.Reaction;
protected
Interfaces.ConcentrationRate R = k*C[Species.B]*C[Species.X];
equation
consumed[Species.A] = 0;
consumed[Species.B] = R;
consumed[Species.X] = R;
end 'X+B->R+S';
我们不追踪R
和S
物质的浓度。因为,它们不过是副产物,不参与任何其它反应。本模型与前述模型同样遵循我们熟悉的模式。不同点在于,A
类物质不参与反应。
系统¶
我们可以将Solution
模型和不同的反应模型相结合,如下:
within ModelicaByExample.Components.ChemicalReactions.Examples;
model ABX_System "Model of simple two reaction system"
ABX.Components.Solution solution(C(each fixed=true, start={1,1,0}))
annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
ABX.Components.'A+B->X' 'A+B->X'(k=0.1)
annotation (Placement(transformation(extent={{30,30},{50,50}})));
ABX.Components.'A+B<-X' 'A+B<-X'(k=0.1)
annotation (Placement(transformation(extent={{30,-10},{50,10}})));
ABX.Components.'X+B->R+S' 'X+B->R+S'(k=10)
annotation (Placement(transformation(extent={{30,-50},{50,-30}})));
equation
connect('A+B<-X'.mixture, solution.mixture) annotation (Line(
points={{30,0},{10,0}}, color={0,0,0},
smooth=Smooth.None));
connect('X+B->R+S'.mixture, solution.mixture) annotation (Line(
points={{30,-40},{20,-40},{20,0},{10,0}},
color={0,0,0},
smooth=Smooth.None));
connect('A+B->X'.mixture, solution.mixture) annotation (Line(
points={{30,40},{20,40},{20,0},{10,0}},
color={0,0,0},
smooth=Smooth.None));
end ABX_System;
注意solution
组件内的修改语句如何用来设置solution
组件内物质的初始浓度。另外,反应系数是用每个反应组分的修改语句指定的。最后,每个反应组分都连接到solution.mixture
连接器。
Simulating this system for 10 seconds yields the following concentration trajectories:
#.. plot:: ../plots/ABX.py # :include-source: no
结论¶
你可能会记得,在我们之前对这个化学系统的讨论中,推导出的方程组为:
每个方程表示特定种类的增量。方程右边的每项都用于计算该特定物种流入控制体积的净流量。哪怕牵涉相对少量的种类,手工构建该系统都会很容易引入错误。但通过使用面向组件方法,我们从不需要推导上述方程组。其结果是,这些方程会自动生成。通过自动化这个过程,我们能够避免许多潜在的错误。我们也不再需要花时间去找出并修复这些错误。