这一篇来看一下热物理类是如何编译并创建储存了可选模型的 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 类的继承派生关系了。