首页/文章/ 详情

OpenFOAM湍流模型的实现

1年前浏览2907

OpenFoam 5.x 中湍流模型具体是如何实现的呢?让我们一起来探讨不可压流体湍流模型的实现这个问题。

1 OpenFOAM湍流模型文件结构介绍

模型的源文件位于/src/TurbulenceModels/目录下。在这个目录下,共有5个文件夹。其中目录turbulenceModels里主要给出的是各个湍流模型的类模板。比如laminar,RAS和LES模型,各个模型下还进一步的细分,比如本期我们要介绍的kEpsilon模型,就属于RAS模型中的一种。这些类模板实例化为类都需要一个参数:BasicTurbulenceModel.而目录incompressible里就为我们介绍了BasicTurbulenceModel 都可以是些什么类。接下来我们就先带着这个参数到底是什么的问题谈谈湍流模型在OF中的实现。

图一. 目录 TurbulenceModels

图二. 子目录 turbulenceModels

图三. 子目录 incompressible

2 湍流模型在代码中的实现

2.1基本的输运湍流模型

在文件

/src/TurbulenceModels/incompressible/turbulentTransportModels/turbulentTransportModels.H
 

中,有一段宏命令:

makeTurbulenceModelTypes
(
   geometricOneField,
   geometricOneField,
   incompressibleTurbulenceModel,
   IncompressibleTurbulenceModel,
   transportModel
);
 

其中geometricOneField, incompressibleTurbulenceModel和transportModel都是类名, 而IncompressibleTurbulenceModel是类模板. OF为了区分类和类模板,在起名的时候通常将类名的首字母小写,而将类模板的首字母大写。

执行完这段宏命令以后,类模板就实例化生成了如下几个类:

transportModelIncompressibleTurbulenceModel
laminartransportModelIncompressibleTurbulenceModel
RAStransportModelIncompressibleTurbulenceModel
LEStransportModelIncompressibleTurbulenceModel
 

2.2 输运湍流模型中的各个派生类和runTimeSelection机制

在文件

/src/TurbulenceModels/incompressible/turbulentTransportModels/turbulentTransportModels.C
 

中,也有一段宏命令:

 makeBaseTurbulenceModel
(
   geometricOneField,
   geometricOneField,
   incompressibleTurbulenceModel,
   IncompressibleTurbulenceModel,
   transportModel
);
 

该宏的定义在文件makeTurbulenceModel.H中:

#define makeBaseTurbulenceModel(Alpha, Rho, baseModel, BaseModel, Transport)   \
 

这段宏操作首先创建了类

transportModelincompressibleTurbulenceModel, 
 

其由类模板生成

 TurbulenceModel                                                
       <                                                                      
           geometricOneField,                                                
           geometricOneField,                                                
           incompressibleTurbulenceModel,                                                        
           transportModel                                                    
       >

 

接下来为该类(此时作为基类)建立了一个哈希表 (OF自建一个称作runTimeSelection机制, 通过"虚构造函数"的方式来实现通过基类类型的指针调用派生类的功能——[1]):

        defineTemplateRunTimeSelectionTable                                    \
       (                                                                      \
           Transport##baseModel,                                              \
           dictionary                                                         \
       );  
 

然后将派生类

RAS##Transport##BaseModel= RAStransportModelIncompressibleTurbulenceModel
 

的构造函数指针加入到该哈希表中:

        addToRunTimeSelectionTable                                             \
       (                                                                      \
           Transport##baseModel,                                              \
           RAS##Transport##BaseModel,                                         \
           dictionary                                                         \
       );                                                                     \
 

而与此同时,也为类

RAS##Transport##BaseModel
 

(作为基类)建立了哈希表:

        defineTemplateRunTimeSelectionTable                                    \
       (RAS##Transport##BaseModel, dictionary);              
 

对于类

laminar##Transport##BaseModelLES##Transport##BaseModel
 

的情况如法炮制。到这里,笔者起初也存在疑问:为何类

transportModelincompressibleTurbulenceModel
 

与类

RAStransportModelIncompressibleTurbulenceModel
 

是基类和派生类的关系呢? 我们还是回到生成该类的模板:

transportModelincompressibleTurbulenceModel=
TurbulenceModel
<
   geometricOneField,
   geometricOneField,
   incompressibleTurbulenceModel,
   transportModel
>
RAStransportModelIncompressibleTurbulenceModel=RASModel<IncompressibleTurbulenceModel<transportModel>>
 

注意到文件

/src/TurbulenceModels/incompressible/incompressibleTurbulenceModel.H
 

其中:

IncompressibleTurbulenceModel<transportModel>:
   public TurbulenceModel
   <
       geometricOneField,
       geometricOneField,
       incompressibleTurbulenceModel,
       transportModel
   >

 

所以

IncompressibleTurbulenceModel<transportModel>
 

transportModelincompressibleTurbulenceModel
 

的派生类,那么,

RAStransportModelIncompressibleTurbulenceModel
 

就是

transportModelincompressibleTurbulenceModel
 

的派生类 —— 回到刚刚谈到的类的哈希表的问题上来:

RAStransportModelIncompressibleTurbulenceModel
 

建立好了哈希表之后(此时视该类为基类),还需要往这个哈希表里添加派生类的构造函数指针。由如下宏命令实现:

makeRASModel(kEpsilon);
 

这段宏定义如下:

#define makeRASModel(Type)                                                     \
   makeTemplatedTurbulenceModel                                               \
   (transportModelIncompressibleTurbulenceModel, RAS, Type)

 

进一步的解析宏makeTemplatedTurbulenceModel:

#define makeTemplatedTurbulenceModel(BaseModel, SType, Type)                   \
   defineNamedTemplateTypeNameAndDebug                                        \
       (Foam::SType##Models::Type<Foam::BaseModel>, 0);                       \
                                                                              \
   namespace Foam                                                             \
   {                                                                          \
       namespace SType##Models                                                \
       {                                                                      \
           typedef Type<BaseModel> Type##SType##BaseModel;                    \
                                                                              \
           addToRunTimeSelectionTable                                         \
           (                                                                  \
               SType##BaseModel,                                              \
               Type##SType##BaseModel,                                        \
               dictionary                                                     \
           );                                                                 \
       }                                                                      \
   }
 

这里面的派生类:

kEpsilonRAStransportModelIncompressibleTurbulenceModel
 

是由模板定义而来:

RASModels::kEpsilon<transportModelIncompressibleTurbulenceModel>
 

查看文件

src/TurbulenceModels/turbulenceModels/RAS/kEpsilon/kEpsilon.H
 

得知:类

RASModels::kEpsilon<transportModelIncompressibleTurbulenceModel>
 

是类

RASModel<transportModelIncompressibleTurbulenceModel>
 

的派生类:

template<class BasicTurbulenceModel>
class kEpsilon
:
   public eddyViscosity<RASModel<BasicTurbulenceModel>>
 

最后通过代码

            addToRunTimeSelectionTable                                         \
           (                                                                  \
               SType##BaseModel,                                              \
               Type##SType##BaseModel,                                        \
               dictionary                                                     \
           );                                                                 \
 

派生类

kEpsilonRAStransportModelIncompressibleTurbulenceModel
 

的构造函数指针加入到了基类

RAStransportModelIncompressibleTurbulenceModel
 

的哈希表中。至此,派生类

RASModels::kEpsilon<IncompressibleTurbulenceModel<transportModel>>
 

与基类

RAStransportModelIncompressibleTurbulenceModel
=RASModel<IncompressibleTurbulenceModel<transportModel>>
 

的runTimeSelection机制完成建立.

2.3  BasicTurbulenceModel是什么?

现在我们终于可以回答文章一开始提出的问题了!—— 参数BasicTurbulenceModel在这里指的就是类

transportModelIncompressibleTurbulenceModel=
IncompressibleTurbulenceModel<transportModel>
 

3. 湍流模型在算例中的应用

以上是代码部分,那么具体到算例中,我们是如何实现湍流模型的呢?例如程序是如何一步一步的读取:

tutorials/incompressible/porousSimpleFoam/angledDuctImplicit/constant/turbulenceProperties
 

这里面的信息的呢?

在文件

applications/solvers/incompressible/simpleFoam/createFields.H
 

中,湍流模型由如下代码建立

singlePhaseTransportModel laminarTransport(U, phi);
autoPtr<incompressible::turbulenceModel> turbulence
(
   incompressible::turbulenceModel::New(U, phi, laminarTransport)
);
 

其中的

incompressible::turbulenceModel
 

就是类

IncompressibleTurbulenceModel<transportModel>:
   namespace incompressible
   {
       typedef IncompressibleTurbulenceModel<transportModel> turbulenceModel;
 

那么该类只是一个很粗糙的基类。正如上文提及的,用基类的指针,通过"虚构造函数"操作派生类.该类有一个数据成员propertiesName. 在文件turbulenceModel.C中,该数据被赋值

const Foam::word Foam::turbulenceModel::propertiesName("turbulenceProperties");
 

在该类的父类

transportModelincompressibleTurbulenceModel
 

中, 要从名称为

propertiesName=turbulenceProperties
 

的字典中寻找关键词simulationType (见TurbulenceModel.C)

    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")
   );
 

在本算例中, 找到了关键词simulationType之后, modelType根据字典信息赋值RAS.
我们之前介绍过,类

transportModelIncompressibleTurbulenceModel
 

的哈希表中有三个派生类:

laminartransportModelIncompressibleTurbulenceModel
RAStransportModelIncompressibleTurbulenceModel
LEStransportModelIncompressibleTurbulenceModel
 

在找到modelType之后,

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

程序就开始找哈希表中对应的那个派生类, 从而通过"虚构造函数"创建一个派生类对象,并将指向该对象的指针返还给基类类型的指针。这些步骤都是在基类的静态函数New 中完成的——[2]:

cstrIter()(alpha, rho, U, alphaRhoPhi, phi, transport, propertiesName)
 

该派生类就是

RAStransportModelIncompressibleTurbulenceModel;
 

同样的把该派生类看做基类, 等他读取关键词RASModel后面的内容并赋值modelType以后,根据modelType创建一个派生类对象,并返还一个基类类型的指针,该指针指向该派生类对象.见文件

src/TurbulenceModels/turbulenceModels/RAS/RASModel/RASModel.C:
   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")
   );
   typename dictionaryConstructorTable::iterator cstrIter =
       dictionaryConstructorTablePtr_->find(modelType);
       cstrIter()(alpha, rho, U, alphaRhoPhi, phi, transport, propertiesName)
 

参考文件:
[1]OpenFOAM guide/runTimeSelection mechanism.
https://openfoamwiki.net/index.php/OpenFOAM_guide/runTimeSelection_mechanism
[2]OpenFOAM 中的运行时选择机制
https://marinecfd.xyz/post/openfoam-runtime-selection/


来源:多相流在线
OpenFOAM多相流湍流
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2023-06-22
最近编辑:1年前
积鼎科技
联系我们13162025768
获赞 108粉丝 112文章 302课程 0
点赞
收藏
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习 福利任务 兑换礼品
下载APP
联系我们
帮助与反馈