OpenFOAM-3.0 的湍流模型(二)

本篇分析 OpenFOAM-3.0 中湍流模型的 RTS 机制。RTS 机制主要是通过调用几个相关的宏函数来实现的,所以,分析 RTS 机制需要将相关的宏函数展开。四类湍流模型,机制是类似的,这里以单相不可压缩湍流模型为例,后文会给出所有其他湍流模型相关的宏函数的展开结果,供读者参考。
RTS 机制的基础这里不再重复了,读者若对这里涉及到 RTS 机制的名称感兴趣,可以参考我以前对 RTS 机制的解读。

2. RTS 机制

单相不可压缩湍流模型类,在 Make/files 文件里包含的其中一个是 src/TurbulenceModels/incompressible/turbulentTransportModels/turbulentTransportModels.C turbulentTransportModels.C,这个文件里包含了一些通用的湍流模型模板类,并调用了一些宏函数来实现 RTS 相关的,这里将宏函数展开看看这个文件究竟实现了怎样的功能。

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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
makeBaseTurbulenceModel
(
geometricOneField,
geometricOneField,
incompressibleTurbulenceModel,
IncompressibleTurbulenceModel,
transportModel
);
#define makeRASModel(Type) \
makeTemplatedTurbulenceModel \
(transportModelIncompressibleTurbulenceModel, RAS, Type)


#define makeLESModel(Type) \
makeTemplatedTurbulenceModel \
(transportModelIncompressibleTurbulenceModel, LES, Type)


// -------------------------------------------------------------------------- //
// RAS models
// -------------------------------------------------------------------------- //
#include "SpalartAllmaras.H"
makeRASModel(SpalartAllmaras);

#include "kEpsilon.H"
makeRASModel(kEpsilon);

#include "RNGkEpsilon.H"
makeRASModel(RNGkEpsilon);

#include "realizableKE.H"
makeRASModel(realizableKE);

#include "LaunderSharmaKE.H"
makeRASModel(LaunderSharmaKE);

#include "kOmega.H"
makeRASModel(kOmega);

#include "kOmegaSST.H"
makeRASModel(kOmegaSST);

#include "kOmegaSSTSAS.H"
makeRASModel(kOmegaSSTSAS);

#include "v2f.H"
makeRASModel(v2f);

#include "LRR.H"
makeRASModel(LRR);

#include "SSG.H"
makeRASModel(SSG);

// -------------------------------------------------------------------------- //
// LES models
// -------------------------------------------------------------------------- //
#include "Smagorinsky.H"
makeLESModel(Smagorinsky);

#include "WALE.H"
makeLESModel(WALE);

#include "dynamicLagrangian.H"
makeLESModel(dynamicLagrangian);

#include "kEqn.H"
makeLESModel(kEqn);

#include "dynamicKEqn.H"
makeLESModel(dynamicKEqn);

#include "SpalartAllmarasDES.H"
makeLESModel(SpalartAllmarasDES);

#include "SpalartAllmarasDDES.H"
makeLESModel(SpalartAllmarasDDES);

#include "SpalartAllmarasIDDES.H"
makeLESModel(SpalartAllmarasIDDES);

#include "DeardorffDiffStress.H"
makeLESModel(DeardorffDiffStress);

#include "kOmegaSSTDES.H"
makeLESModel(kOmegaSSTDES);

#include "kOmegaSSTDDES.H"
makeLESModel(kOmegaSSTDDES);

#include "kOmegaSSTIDDES.H"
makeLESModel(kOmegaSSTIDDES);

这个宏函数调用

1
2
3
4
5
6
7
8
makeBaseTurbulenceModel
(
geometricOneField,
geometricOneField,
incompressibleTurbulenceModel,
IncompressibleTurbulenceModel,
transportModel
);

展开结果为

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
namespace Foam                                                             
{
typedef TurbulenceModel
<
geometricOneField,
geometricOneField,
incompressibleTurbulenceModel,
transportModel
> transportModelincompressibleTurbulenceModel;

defineTemplateRunTimeSelectionTable // 对TurbulenceModel类中定义的 hashTable 进行了初始化
(
transportModelincompressibleTurbulenceModel,
dictionary
);

typedef IncompressibleTurbulenceModel<transportModel> transportModelIncompressibleTurbulenceModel;

typedef laminar<transportModelIncompressibleTurbulenceModel> LaminartransportModelIncompressibleTurbulenceModel;

defineNamedTemplateTypeNameAndDebug(LaminartransportModelIncompressibleTurbulenceModel, 0);

addToRunTimeSelectionTable // 将laminar 模型加到定义在 TurbulenceModel 类中的hashTable
(
transportModelincompressibleTurbulenceModel,
LaminartransportModelIncompressibleTurbulenceModel,
dictionary
);

typedef RASModel<transportModelIncompressibleTurbulenceModel> RAStransportModelIncompressibleTurbulenceModel;

defineNamedTemplateTypeNameAndDebug(RAStransportModelIncompressibleTurbulenceModel, 0);

// 对 RASModel类中定义的hashTable进行了初始化
defineTemplateRunTimeSelectionTable
(RAStransportModelIncompressibleTurbulenceModel, dictionary);
// 将 RASModel 添加到 TurbulenceModel 中定义的hashTable
addToRunTimeSelectionTable
(
transportModelincompressibleTurbulenceModel,
RAStransportModelIncompressibleTurbulenceModel,
dictionary
);

typedef LESModel<transportModelIncompressibleTurbulenceModel> LEStransportModelIncompressibleTurbulenceModel;

defineNamedTemplateTypeNameAndDebug(LEStransportModelIncompressibleTurbulenceModel, 0);

// 对LESModel类中定义的hashTable进行了初始化
defineTemplateRunTimeSelectionTable
(LEStransportModelIncompressibleTurbulenceModel, dictionary);
// 将 LESModel 添加到 TurbulenceModel 中定义的hashTable
addToRunTimeSelectionTable
(
transportModelincompressibleTurbulenceModel,
LEStransportModelIncompressibleTurbulenceModel,
dictionary
);
}

makeRASModel(SpalartAllmaras) 展开结果为

1
2
makeTemplatedTurbulenceModel 
(transportModelIncompressibleTurbulenceModel, RAS, SpalartAllmaras)

继续展开结果为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
defineNamedTemplateTypeNameAndDebug                      
(Foam::RASModels::SpalartAllmaras<Foam::transportModelIncompressibleTurbulenceModel>, 0);

namespace Foam
{
namespace RASModels
{
typedef SpalartAllmaras<transportModelIncompressibleTurbulenceModel> SpalartAllmarasRAStransportModelIncompressibleTurbulenceModel;

// 将 SpalartAllmaras 模型添加到 RASModel 中定义的 hashTable
addToRunTimeSelectionTable
(
RAStransportModelIncompressibleTurbulenceModel,
SpalartAllmarasRAStransportModelIncompressibleTurbulenceModel,
dictionary
);
}
}

makeLESModel(Smagorinsky) 展开结果为

1
2
makeTemplatedTurbulenceModel 
(transportModelIncompressibleTurbulenceModel, LES, Smagorinsky)

继续展开结果为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
defineNamedTemplateTypeNameAndDebug                      
(Foam::LESModels::Smagorinsky<Foam::transportModelIncompressibleTurbulenceModel>, 0);

namespace Foam
{
namespace LESModels
{
typedef Smagorinsky<transportModelIncompressibleTurbulenceModel> SmagorinskyLEStransportModelIncompressibleTurbulenceModel;

// 将 Smagorinsky 模型添加到 LESModel 中定义的hashTable
addToRunTimeSelectionTable
(
LEStransportModelIncompressibleTurbulenceModel,
SmagorinskyLEStransportModelIncompressibleTurbulenceModel,
dictionary
);
}
}

注意,这里给 kEpsilonSmagorinsky 模型代入的模板参数是 transportModelIncompressibleTurbulenceModel,即 IncompressibleTurbulenceModel<transportModel>

上面给出了单相不可压缩湍流模型是如何添加到各自该所属的 hashTable 里的。接着,以单相不可压缩模型为例,看看湍流模型的调用过程。
pisoFoam 求解器中,湍流模型接口的定义如下

1
2
3
4
5
autoPtr<incompressible::turbulenceModel> turbulence
(
incompressible::turbulenceModel::New(U, phi, laminarTransport)
);
// laminarTransport 是 singlePhaseTransportModel 的一个对象

incompressible::turbulenceModelIncompressibleTurbulenceModel<transportModel> 的别名。
这里调用的是 IncompressibleTurbulenceModel 类的 New 函数。

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
template<class TransportModel>
Foam::autoPtr<Foam::IncompressibleTurbulenceModel<TransportModel> >
Foam::IncompressibleTurbulenceModel<TransportModel>::New
(
const volVectorField& U,
const surfaceScalarField& phi,
const TransportModel& transport,
const word& propertiesName
)
{
return autoPtr<IncompressibleTurbulenceModel>
(
static_cast<IncompressibleTurbulenceModel*>(
TurbulenceModel
<
geometricOneField,
geometricOneField,
incompressibleTurbulenceModel,
TransportModel
>::New
(
geometricOneField(),
geometricOneField(),
U,
phi,
phi,
transport,
propertiesName
).ptr())
);

返回的是 TurbulenceModel 类的 New 函数。

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
template
<
class Alpha,
class Rho,
class BasicTurbulenceModel,
class TransportModel
>
Foam::autoPtr
<
Foam::TurbulenceModel<Alpha, Rho, BasicTurbulenceModel, TransportModel>
>
Foam::TurbulenceModel<Alpha, Rho, BasicTurbulenceModel, TransportModel>::New
(
const alphaField& alpha,
const rhoField& rho,
const volVectorField& U,
const surfaceScalarField& alphaRhoPhi,
const surfaceScalarField& phi,
const transportModel& transport,
const word& propertiesName
)
{
// get model name, but do not register the dictionary
// otherwise it is registered in the database twice
const word modelType
(
IOdictionary
(
IOobject
(
IOobject::groupName(propertiesName, U.group()),
U.time().constant(),
U.db(),
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE,
false
)
).lookup("simulationType")
);

Info<< "Selecting turbulence model type " << modelType << endl;

typename dictionaryConstructorTable::iterator cstrIter =
dictionaryConstructorTablePtr_->find(modelType);

if (cstrIter == dictionaryConstructorTablePtr_->end())
{
FatalErrorInFunction
<< "Unknown TurbulenceModel type "
<< modelType << nl << nl
<< "Valid TurbulenceModel types:" << endl
<< dictionaryConstructorTablePtr_->sortedToc()
<< exit(FatalError);
}

return autoPtr<TurbulenceModel>
(
cstrIter()(alpha, rho, U, alphaRhoPhi, phi, transport, propertiesName)
);
}

这里通过读取 turbulenceProperties 文件,查找关键字 simulationType(只能是 RASLES ),并据此从定义在 TurbulenceModel 类中 hashTable 中找对应的模型,然后返回的模型(可能是 RAStransportModelIncompressibleTurbulenceModelRASfluidThermoCompressibleTurbulenceModelRASsinglePhaseTransportModelPhaseIncompressibleTurbulenceModelRASphaseModelPhaseCompressibleTurbulenceModel)的 New 函数

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
template<class BasicTurbulenceModel>
Foam::autoPtr<Foam::RASModel<BasicTurbulenceModel> >
Foam::RASModel<BasicTurbulenceModel>::New
(
const alphaField& alpha,
const rhoField& rho,
const volVectorField& U,
const surfaceScalarField& alphaRhoPhi,
const surfaceScalarField& phi,
const transportModel& transport,
const word& propertiesName
)
{
// get model name, but do not register the dictionary
// otherwise it is registered in the database twice
const word modelType
(
IOdictionary
(
IOobject
(
IOobject::groupName(propertiesName, U.group()),
U.time().constant(),
U.db(),
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE,
false
)
).subDict("RAS").lookup("RASModel")
);

Info<< "Selecting RAS turbulence model " << modelType << endl;

typename dictionaryConstructorTable::iterator cstrIter =
dictionaryConstructorTablePtr_->find(modelType);

if (cstrIter == dictionaryConstructorTablePtr_->end())
{
FatalErrorInFunction
<< "Unknown RASModel type "
<< modelType << nl << nl
<< "Valid RASModel types:" << endl
<< dictionaryConstructorTablePtr_->sortedToc()
<< exit(FatalError);
}

return autoPtr<RASModel>
(
cstrIter()(alpha, rho, U, alphaRhoPhi, phi, transport, propertiesName)
);
}

这个 New 函数中需要读取 RAS 子字典,从中读取 RASModel 关键字,并据此从定义在 RASModel 类中的 hashTable 中查找到对应的湍流模型,并返回湍流模型的构造函数

1
2
3
4
 return autoPtr<RASModel>
(
cstrIter()(alpha, rho, U, alphaRhoPhi, phi, transport, propertiesName)
);

其他三类湍流模型,机制是类似的,这里不再详述,仅给出三个链接,供大家参考:单相可压缩湍流模型多相不可压缩湍流模型多相可压缩湍流模型