openfoam学习心得—壁面函数在CFD中如何实施

openfoam学习心得—壁面函数在CFD中如何实施

最近研究壁面函数,发现邱教授博客,讲的很是不错!记录一下
http://xiaopingqiu.github.io/2016/04/25/wallFunctions4/
在一般的外流场计算中,一般遇到的边界有入口、出口、对称面以及壁面-v7编程指南P40对此处应用的边界条件进行了说明,我们重点关注壁面,壁面一般设置为v-no-slip,p-法向梯度为0,代入离散方程从而进行求解,当加入湍流模型时,还会存在湍流参量k、 ε \varepsilon ε ω \omega ω,nut,博主主要想归纳在运用壁面函数时,到底该如何对这些参量设置边界条件。
openfoam中的壁面函数按其计算位置分为两种—第一种计算壁面上的值,第二种计算靠近壁面第一层网格,其中心的值。
openfoam里面求解器源代码都位于applications里面,如壁面函数等预先定义好的类位于src里面,其主要有六个k、 ε \varepsilon ε ω \omega ω,nut、f、vopenfoam学习心得—壁面函数在CFD中如何实施_第1张图片f、v主要是针对f-v2湍流模型,这里我们主要看k、 ε \varepsilon ε ω \omega ω、nut,注意文件夹的名称以s结尾,说明对于某一个参量,可能存在不止一种壁面函数,我们进去下一级目录查看,可以发现 ε \varepsilon ε ω \omega ω只有一种壁面函数,k有两种,nut足足有八种壁面函数可供选择!今天笔者主要阅读kqRwallFunctions源代码,遂做些标注,方便日后查阅也供他人参考,有理解不对的地方,还望大佬不吝赐教!
openfoam学习心得—壁面函数在CFD中如何实施_第2张图片
在这里插入图片描述kqRwallFunction.H-这是类声明,固没有出现函数体

namespace Foam         //名称空间
{
template<class Type>    //模板类定义符,Type可以是任何类
class kqRWallFunctionFvPatchField  
:
    public zeroGradientFvPatchField<Type> //该类公有继承于模板类
{

public:      //公有成员

   
    //- Runtime type information
    TypeName("kqRWallFunction");  //成员变量初始化


    // Constructors

        //- Construct from patch and internal field
        kqRWallFunctionFvPatchField //构造函数 无返回值,以类名命名,初始化以引用类型传递参数
        (
            const fvPatch&,
            const DimensionedField<Type, volMesh>&
        );

        //- Construct from patch, internal field and dictionary
        kqRWallFunctionFvPatchField
        (
            const fvPatch&,
            const DimensionedField<Type, volMesh>&,
            const dictionary&
        ); //构造函数的重载

        //- Construct by mapping given
        // kqRWallFunctionFvPatchField
        //  onto a new patch
        kqRWallFunctionFvPatchField
        (
            const kqRWallFunctionFvPatchField&,
            const fvPatch&,
            const DimensionedField<Type, volMesh>&,
            const fvPatchFieldMapper&
        );

        //- Copy constructor
        kqRWallFunctionFvPatchField
        (
            const kqRWallFunctionFvPatchField&
        );

        //- Construct and return a clone
        virtual tmp<fvPatchField<Type>> clone() const //虚函数,可在子类中重新定义,返回值是一个tmp>类的对象,这是一个模板类
        {
            return tmp<fvPatchField<Type>>
            (
                new kqRWallFunctionFvPatchField(*this)//*this表示一个kqRWallFunctionFvPatchField 对象,调用了上面的copy构造函数
            );
        }

        //- Copy constructor setting internal field reference
        kqRWallFunctionFvPatchField
        (
            const kqRWallFunctionFvPatchField&,
            const DimensionedField<Type, volMesh>&
        );

        //- Construct and return a clone setting internal field reference
        virtual tmp<fvPatchField<Type>> clone
        (
            const DimensionedField<Type, volMesh>& iF
        ) const
        {
            return tmp<fvPatchField<Type>> //生成tmp>类的对象
            (
                new kqRWallFunctionFvPatchField(*this, iF)//其实函数参数是一个指针,指向kqRWallFunctionFvPatchField对象
            );
        }


    // Member Functions---成员函数

        //- Evaluate the patchField
        virtual void evaluate
        (
            const Pstream::commsTypes commsType = Pstream::commsTypes::blocking
        );

        //- Write
        virtual void write(Ostream&) const;
};

kqRwallFunction.C

#include "kqRWallFunctionFvPatchField.H"
#include "addToRunTimeSelectionTable.H"

// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //

template<class Type> //同上,模板类修饰符
Foam::kqRWallFunctionFvPatchField<Type>::kqRWallFunctionFvPatchField
(
    const fvPatch& p,
    const DimensionedField<Type, volMesh>& iF
)
:
    zeroGradientFvPatchField<Type>(p, iF)
{}//调用父类构造函数


template<class Type>
Foam::kqRWallFunctionFvPatchField<Type>::kqRWallFunctionFvPatchField
(
    const fvPatch& p,
    const DimensionedField<Type, volMesh>& iF,
    const dictionary& dict
)
:
    zeroGradientFvPatchField<Type>(p, iF, dict)
{}


template<class Type>
Foam::kqRWallFunctionFvPatchField<Type>::kqRWallFunctionFvPatchField
(
    const kqRWallFunctionFvPatchField& ptf,
    const fvPatch& p,
    const DimensionedField<Type, volMesh>& iF,
    const fvPatchFieldMapper& mapper
)
:
    zeroGradientFvPatchField<Type>(ptf, p, iF, mapper)
{}


template<class Type>
Foam::kqRWallFunctionFvPatchField<Type>::kqRWallFunctionFvPatchField
(
    const kqRWallFunctionFvPatchField& tkqrwfpf
)
:
    zeroGradientFvPatchField<Type>(tkqrwfpf)
{}


template<class Type>
Foam::kqRWallFunctionFvPatchField<Type>::kqRWallFunctionFvPatchField
(
    const kqRWallFunctionFvPatchField& tkqrwfpf,
    const DimensionedField<Type, volMesh>& iF
)
:
    zeroGradientFvPatchField<Type>(tkqrwfpf, iF)
{}
//全是调用父类构造函数,这个类就是个空壳

// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //

template<class Type>
void Foam::kqRWallFunctionFvPatchField<Type>::evaluate
(
    const Pstream::commsTypes commsType
)
{
    zeroGradientFvPatchField<Type>::evaluate(commsType);//调用父类函数
}


template<class Type>
void Foam::kqRWallFunctionFvPatchField<Type>::write(Ostream& os) const
{
    zeroGradientFvPatchField<Type>::write(os); //又是调用父类
    writeEntry(os, "value", *this);
}

读完这份源码,唯一的感受就是,kqRwallFunction这个边界条件就是zeroGradient,完全没有引入新的东西。
kLowReWallFunction.C
这是另外一个k壁面函数,虽然叫做LowRe但是也适用于HighRe,其继承于fixedValueFvPatchField,可以看出其为一个固定值边界条件,我们主要分析它的成员函数:

void kLowReWallFunctionFvPatchScalarField::updateCoeffs()
{
    if (updated())//判断patch单元的值是否更新
    {
        return;
    }

    const label patchi = patch().index();//边界是被划分为不同的patch,这是每个patch的标号(label)

    const turbulenceModel& turbModel = db().lookupObject<turbulenceModel>
    (
        IOobject::groupName
        (
            turbulenceModel::propertiesName,
            internalField().group()
        )
    ); //初始化一个对象

    const nutWallFunctionFvPatchScalarField& nutw =
        nutWallFunctionFvPatchScalarField::nutw(turbModel, patchi);

    const scalarField& y = turbModel.y()[patchi]; //算near wall distant
    // tmp可以理解为volScalarField* 其实也就是个包装过的指针,搭配new堆内存使用
    const tmp<volScalarField> tk = turbModel.k();
    const volScalarField& k = tk();//算第一个单元的k值

    const tmp<scalarField> tnuw = turbModel.nu(patchi);
    const scalarField& nuw = tnuw(); //算第一个单元的粘度值

    const scalar Cmu25 = pow025(nutw.Cmu());//算摩擦速度Cmu25=Cmu^0.25

    scalarField& kw = *this;//初始化修正的k

    // Set k wall values
    forAll(kw, facei)
    {
        label celli = patch().faceCells()[facei];//由面值算单元值

        scalar uTau = Cmu25*sqrt(k[celli]);//算摩擦速度

        scalar yPlus = uTau*y[facei]/nuw[facei];//算y+

        if (yPlus > nutw.yPlusLam())
        {
            scalar Ck = -0.416;
            scalar Bk = 8.366;
            kw[facei] = Ck/nutw.kappa()*log(yPlus) + Bk;//注意这里是kw[facei],也就是说边界上的湍动能是固定值
        }
        else
        {
            scalar C = 11.0;
            scalar Cf = (1.0/sqr(yPlus + C) + 2.0*yPlus/pow3(C) - 1.0/sqr(C));
            kw[facei] = 2400.0/sqr(Ceps2_)*Cf;
        }

        kw[facei] *= sqr(uTau);//个人认为这个时候K场边界上应该是零梯度的,因为k+应该是面中心的值但是代码却是 kw[facei],说明面中心的值等于面上的值。

    }

    // Limit kw to avoid failure of the turbulence model due to division by kw
    kw = max(kw, small);

    fixedValueFvPatchField<scalar>::updateCoeffs();//执行父类的函数,更新update值
    // TODO: perform averaging for cells sharing more than one boundary face
}

你可能感兴趣的:(openfoam学习心得—壁面函数在CFD中如何实施)