这一篇来看一下热物理类是如何编译并创建储存了可选模型的 hashTable 的。
根据以前的经验,编译和构建 hashTable 肯定是跟这个源文件有关:src/thermophysicalModels/basic/rhoThermo/rhoThermos
。
这个文件里,全部都是在调用宏函数。而且,从宏函数的参数来看,似乎就是个排列组合的游戏,把所有可用的组合都写了一遍。1
2
3
4
5
6
7
8
9
10
11
12makeThermo
(
rhoThermo,
heRhoThermo,
pureMixture,
constTransport,
sensibleInternalEnergy,
hConstThermo,
perfectGas,
specie
);
......
为了弄清这部分内容,需要先理解 makeThermo
这个宏函数的定义,见 src/thermophysicalModels/basic/fluidThermo/makeThermo.H
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71#define makeThermoTypedefs(BaseThermo,Cthermo,Mixture,Transport,Type,Thermo,EqnOfState,Specie)\
\
typedef \
Transport \
< \
species::thermo \
< \
Thermo \
< \
EqnOfState \
< \
Specie \
> \
>, \
Type \
> \
> Transport##Type##Thermo##EqnOfState##Specie; \
\
typedef \
Cthermo \
< \
BaseThermo, \
Mixture<Transport##Type##Thermo##EqnOfState##Specie> \
> Cthermo##Mixture##Transport##Type##Thermo##EqnOfState##Specie; \
\
defineTemplateTypeNameAndDebugWithName \
( \
Cthermo##Mixture##Transport##Type##Thermo##EqnOfState##Specie, \
( \
#Cthermo"<"#Mixture"<" \
+ Transport##Type##Thermo##EqnOfState##Specie::typeName() \
+ ">>" \
).c_str(), \
0 \
);
#define makeThermo(BaseThermo,Cthermo,Mixture,Transport,Type,Thermo,EqnOfState,Specie)\
\
makeThermoTypedefs \
( \
BaseThermo, \
Cthermo, \
Mixture, \
Transport, \
Type, \
Thermo, \
EqnOfState, \
Specie \
) \
\
addToRunTimeSelectionTable \
( \
basicThermo, \
Cthermo##Mixture##Transport##Type##Thermo##EqnOfState##Specie, \
fvMesh \
); \
\
addToRunTimeSelectionTable \
( \
fluidThermo, \
Cthermo##Mixture##Transport##Type##Thermo##EqnOfState##Specie, \
fvMesh \
); \
\
addToRunTimeSelectionTable \
( \
BaseThermo, \
Cthermo##Mixture##Transport##Type##Thermo##EqnOfState##Specie, \
fvMesh \
);
可见,在 makeThermo
这个宏函数里,先调用了 makeThermoTypedefs
宏函数,然后调用 addToRunTimeSelectionTable
函数。按照之前对 RTS 机制的理解,调用 addToRunTimeSelectionTable
函数的作用是往 hashTable 里插入元素,细节不需再赘述。这里主要来看看 makeThermoTypedefs
函数的功能,以上文列举的这个实例为例。先来看第一个 typedef:将实例中的参数代入后,1
2
3typedef \
constTransport<species::thermo<hConstThermo<perfectGas<specie>>,sensibleInternalEnergy>> \
constTransportsensibleEnthalpyhConstThermoperfectGasspecie;
第二个 typedef1
2
3
4
5
6typedef \
heRhoThermo \
< \
rhoThermo, \
pureMixture<constTransportsensibleEnthalpyhConstThermoperfectGasspecie> \
> heRhoThermopureMixtureconstTransportsensibleEnthalpyhConstThermoperfectGasspecie;
除了这两个 typedef,还调用了 defineTemplateTypeNameAndDebugWithName
宏函数,这个函数的定义在 src/OpenFOAM/db/typeInfo/className.H
:
1 | #define defineTemplateTypeNameAndDebugWithName(Type, Name, DebugSwitch) \ |
很显然,这个宏函数的作用是修改类对应的 typeName
和 debug 选项。在 OpenFOAM 中,很多类中都会调用 TypeName("typename")
,这里的 TypeName
也是一个宏函数,定义在 src/OpenFOAM/db/typeInfo/className.H
:
1 | #define TypeName(TypeNameString) \ |
可见, TypeName
这个宏函数,声明了一个类静态变量 typeName
,定义了一个函数 type
用于返回 typeName
的值,并定义了一个静态变量 debug
用于存储 debug 选项。这里与 RTS 机制有关的是 typeName
这个变量。
绕了半圈,回到 defineTemplateTypeNameAndDebugWithName
函数。了解了 typeName
这个变量的定义,很容易就能看出来, defineTemplateTypeNameAndDebugWithName
这个函数其实就是在对类的静态变量 typeName
进行赋值。根据上文的实例提供的参数,宏函数 defineTemplateTypeNameAndDebugWithName
可以理解为:对 heRhoThermopureMixtureconstTransportsensibleEnthalpyhConstThermoperfectGasspecie
对应的类的静态变量 typeName
进行赋值,赋值结果为:heRhoThermo<pureMixture< + constTransport<species::thermo<hConstThermo<perfectGas<specie>>,sensibleInternalEnergy>>::typeName() + >>
。这里调用了 constTransport
类的成员函数 typeName()
。
经过一番冗长的函数调用,得到的最终结果是:将 heRhoThermopureMixtureconstTransportsensibleEnthalpyhConstThermoperfectGasspecie
对应的类的静态变量 typeName
赋值为:heRhoThermo<pureMixture<const<hConst<perfectGas<specie>>,sensiblesensibleEnthalpy>>>
。
至此,经过一番宏函数的调用,得到了 addToRunTimeSelectionTable
宏函数的参数。前面 RTS 机制部分讲过,这个函数的作用就是对 hashTable 增加元素,以
1 | addToRunTimeSelectionTable \ |
为例,第一个参数,表示元素将增加到 BaseThermo
类(这里是 rhoThermo
)中声明的 hashTable,第二个参数,表示将要添加的类,添加成功以后,这个类的 typeName
将是 hashTable 的 key,而返回这个类的对象的一个函数,将是 hashTable 的 value。第三个参数对应着 hashTable 对象的名字,fvMesh 对应的 hashTable 对象名为 fvMeshConstructorTable
,这与在 rhoThermo
中声明的名字是对应的。
最后总结如下:
宏函数
1 | makeThermo |
调用以后,向 rhoThermo
类中声明的 hashTable 中增加了一组元素,其 key 为 heRhoThermo<pureMixture<const<hConst<perfectGas<specie>>,sensibleInternalEnergy>>>
,value 对应的函数返回的是类
1 | heRhoThermo |
的对象。
每调用一次 makeThermo
函数,就增加了一个新组元素,也即增加了一个可选的模型。不同的参数,其实对应的是不同的模板实例。
至此,就知道了在 twoPhaseEulerFoam
的 phaseModel
中定义的热物理类接口 thermo_
最终指向的是 heRhoThermo
类的对象。虽然代入的模板数很复杂,但整个架构仍然是基于 RTS 机制的。
接下来,要想理解能量方程,理解温度,粘度,压力等这些热物理相关的量是怎么计算更新的,就需要仔细看一下 heRhoThermo
类的继承派生关系了。