OFtutorial08_customBC解析

组成

prescribedPipeInletFvPatchVectorField.H

头文件

#ifndef prescribedPipeInletFvPatchVectorField_H
#define prescribedPipeInletFvPatchVectorField_H

#include "fvPatchFields.H"
#include "fixedValueFvPatchFields.H"
#include "Switch.H"
#include "addToRunTimeSelectionTable.H"
#include "volFields.H"

prescribedPipeInletFvPatchVectorField类声明

namespace Foam//指定命名空间
{

/*---------------------------------------------------------------------------*\
               Class prescribedPipeInletFvPatchVectorField Declaration
\*---------------------------------------------------------------------------*/

// NOTE: the patch is derived from a fixedValue BC since it does prescribe
// a fixed value, although non-uniform across all of the faces, unlike the base
// class does.
class prescribedPipeInletFvPatchVectorField
:
    public fixedValueFvPatchVectorField//以公有继承的方式继承现有的fixedValueFvPatchVectorField类
{

私有成员

private:
    // Private data
        // NOTE: these class fields are used to determine the inlet profile

    	// denotes the type of the profile used to perform the approximation
        // (optional, defaults to exponential)
    	word approximationType_;//近似方式,可选,默认是指数型

    	// flow velocity magnitude
    	scalar flowSpeed_;//入口处速度大小

    	// bl thickness
    	scalar deltaByR_;

    	// centre of the pipe (optional, defaults to the origin)
    	vector centrepoint_;//管道中心位置(可选,默认值为原点)

    	// radius of the pipe
    	scalar R_;//管道半径

    	// pressure gradient coefficient (optional, default to 0, not used by all approximations)
    	scalar lambda_;//压力梯度系数

公有成员

public:

    //- Runtime type information
    // NOTE: this gets used by the runtimeSelector. In other words, this is the
    // name under which OpenFOAM knows this BC.
    TypeName("prescribedPipeInlet");//定义边界条件的名称  

    // Constructors//类的构造器(函数定义)。此处为函数重载,两个同名函数有不同的输入。编译器会根据输入的类型决定调用哪一个函数。

        //- Construct from patch and internal field

基本构造函数

这个构造函数接受一个fvPatch(边界片)的引用和一个体积网格上的向量场(DimensionedField<vector, volMesh>)的引用,用于初始化对象的某些属性。这可能是创建prescribedPipeInletFvPatchVectorField实例的最基本方式。

        prescribedPipeInletFvPatchVectorField
        (
            const fvPatch&,
            const DimensionedField<vector, volMesh>&
        );

        //- Construct as copy setting internal field reference

复制构造函数(设置内部场引用)

这个构造函数接受另一个prescribedPipeInletFvPatchVectorField对象的引用和一个新的体积网格上的向量场引用,用于创建一个新的对象实例,同时设置内部字段引用。这种构造函数通常用于基于现有对象创建新对象,但可能需要在不同的上下文中(例如,不同的网格或边界条件)。

        prescribedPipeInletFvPatchVectorField
        (
            const prescribedPipeInletFvPatchVectorField&,
            const DimensionedField<vector, volMesh>&
        );

构造并返回内部流场引用的克隆

        //- Construct and return a clone setting internal field reference
        virtual tmp<fvPatchVectorField> clone
        (
            const DimensionedField<vector, volMesh>& iF
        ) const
        {
            return tmp<fvPatchVectorField>
            (
                new prescribedPipeInletFvPatchVectorField(*this, iF)
            );
        }

从patch、内部场和dictionary构造

这个构造函数除了接受fvPatch和DimensionedField<vector, volMesh>外,还接受一个dictionary(可能包含边界条件的详细设置)。这个构造函数允许从配置文件或字典中读取额外的参数来初始化对象。

        //- Construct from patch, internal field and dictionary
        prescribedPipeInletFvPatchVectorField//从patch,内部场以及dictionary中构造的构造函数
        (
            const fvPatch&,
            const DimensionedField<vector, volMesh>&,
            const dictionary&,
            const bool valueRequired=true
        );

通过映射构造

这个构造函数接受一个现有的prescribedPipeInletFvPatchVectorField对象、一个新的fvPatch、一个新的体积网格上的向量场以及一个fvPatchFieldMapper对象。它允许将一个现有的边界片向量场映射到新的边界片上,同时保留或转换其特性。这对于在网格细化或重新网格化过程中保持边界条件的一致性非常有用。

        //- Construct by mapping given prescribedPipeInletFvPatchVectorField//通过映射prescribedPipeInletFvPatchVectorField到一个新的patch构造的构造函数
        //  onto a new patch
        prescribedPipeInletFvPatchVectorField
        (
            const prescribedPipeInletFvPatchVectorField&,
            const fvPatch&,
            const DimensionedField<vector, volMesh>&,
            const fvPatchFieldMapper&,
            const bool mappingRequired=true
        );

在未设置内部场的时候不允许复制

        //- Disallow copy without setting internal field reference
        prescribedPipeInletFvPatchVectorField(const prescribedPipeInletFvPatchVectorField&) = delete;。

更新与patch相关的系数

    // Member functions

        // Evaluation functions

            //- Update the coefficients associated with the patch field
            virtual void updateCoeffs();

输出数据


        // I-O

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

} // End namespace Foam

#endif

prescribedPipeInletFvPatchVectorField.C

#include "prescribedPipeInletFvPatchVectorField.H"

// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
//调用默认的构造器以确保类中的数据会被初始化。把默认值赋给成员变量
Foam::prescribedPipeInletFvPatchVectorField::prescribedPipeInletFvPatchVectorField
(
    const fvPatch& p,
    const DimensionedField<vector, volMesh>& iF
)
:
    // NOTE: call the default constructor to make sure everything gets initialised properly
    fixedValueFvPatchVectorField(p, iF),
    // NOTE: assign default values to the members using an initialiser list
    approximationType_("exponential"),
    flowSpeed_(0.),
	deltaByR_(0.),
	centrepoint_(vector::zero),
	R_(0.),
	lambda_(0.)
{}
//在指定的文件夹下的U文件中读取边界条件的控制参数,然后输出到这里作为边界条件的参考值
Foam::prescribedPipeInletFvPatchVectorField::prescribedPipeInletFvPatchVectorField
(
    const fvPatch& p,
    const DimensionedField<vector, volMesh>& iF,
    const dictionary& dict,
    const bool valueRequired
)
:
    // NOTE: this constructor reads all of the control parameters from the boundary
    // condition definition specified in the time folder U file, imported here
    // as a dictionary reference.
    fixedValueFvPatchVectorField(p, iF),
    approximationType_("exponential"),
    flowSpeed_(0.),
	deltaByR_(0.),
	centrepoint_(vector::zero),
	R_(0.),
	lambda_(0.)
{
    // NOTE: calls the = operator to assign the value to the faces held by this BC
    fvPatchVectorField::operator=(vectorField("value", dict, p.size()));

    // NOTE: looks up the necessary paramters
    approximationType_ = dict.lookupOrDefault<word>("approximationType","exponential");
    dict.lookup("flowSpeed") >> flowSpeed_;
	dict.lookup("deltaByR") >> deltaByR_;
	centrepoint_ = dict.lookupOrDefault<vector>("centrepoint",vector::zero);
	dict.lookup("R") >> R_;
	lambda_ = dict.lookupOrDefault<scalar>("lambda",0.);

    // NOTE: calls the .updateCoeffs() method to calculate the inlet profile in
    // accordance with the controls which have just been read.
	updateCoeffs();
}

Foam::prescribedPipeInletFvPatchVectorField::prescribedPipeInletFvPatchVectorField
(
    const prescribedPipeInletFvPatchVectorField& ptf,
    const fvPatch& p,
    const DimensionedField<vector, volMesh>& iF,
    const fvPatchFieldMapper& mapper,
    const bool mappingRequired
)
:
    // NOTE: this constructor, and the two subsequent ones, transfer data to the
    // instance being created from another one.
    fixedValueFvPatchVectorField(ptf, p, iF, mapper),
    approximationType_(ptf.approximationType_),
    flowSpeed_(ptf.flowSpeed_),
	deltaByR_(ptf.deltaByR_),
	centrepoint_(ptf.centrepoint_),
	R_(ptf.R_),
	lambda_(ptf.lambda_)
{}

Foam::prescribedPipeInletFvPatchVectorField::prescribedPipeInletFvPatchVectorField
(
    const prescribedPipeInletFvPatchVectorField& rifvpvf,
    const DimensionedField<vector, volMesh>& iF
)
:
    fixedValueFvPatchVectorField(rifvpvf, iF),
    approximationType_(rifvpvf.approximationType_),
    flowSpeed_(rifvpvf.flowSpeed_),
    deltaByR_(rifvpvf.deltaByR_),
    centrepoint_(rifvpvf.centrepoint_),
    R_(rifvpvf.R_),
    lambda_(rifvpvf.lambda_)
{}

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

// NOTE: this is the key method which implements the actual maths for calculating
// the inlet profiles.

存在疑问

void Foam::prescribedPipeInletFvPatchVectorField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

	// assign inlet velocity normal to the patch
	// by convention, patch faces point outside of the domain
    //把总的流速分解为x,y,z三个方向的值,得到的向量与面垂直。patch().Sf()得到面的单位法向量;patch().magSf()得到面的法向量的模。
	vectorField Uin = (-1.)*(patch().Sf()/patch().magSf()) * flowSpeed_;

    // go over each face and add the BL profile for faces close to the wall
    //patch()面中心位置
	forAll(patch().Cf(), faceI)
	{
        // non-dimensional distance away from the wall
        //计算当前位置距边界的距离
          scalar yOverDelta ( (1.-mag(centrepoint_ - patch().Cf()[faceI])/R_)/deltaByR_ );

		if (approximationType_.compare("parabolic") == 0)
		{
			if (yOverDelta < 1.0)//如果yOverDelta小于1(即面在边界层内)
				Uin[faceI] *= (2*yOverDelta-pow(yOverDelta,2.0));//抛物线型速度分布
		}
		else if (approximationType_.compare("Polhausen") == 0)
		{
			if (yOverDelta < 1.0)
				Uin[faceI] *= 1.-(1.+yOverDelta)*pow(1.-yOverDelta,3.) + lambda_/6.*yOverDelta*pow(1.-yOverDelta,3.);
		}
		else if (approximationType_.compare("exponential") == 0)
		{
			if (yOverDelta < 1.0)
				Uin[faceI] *= pow(yOverDelta,1./7.);//指数型
		}
		else//错误提示
		{
			FatalErrorIn
		    (
		        "prescribedPipeInletFvPatchVectorField::updateCoeffs()"
		    )   << "Unknown boundary layer profile approximation type " << approximationType_ << nl << nl
		        << "Valid types are :" << nl
		        << tab << "parabolic" << nl
		        << tab << "Polhausen" << nl
		        << tab << "exponential" << nl
		        << exit(FatalError);
		}
	}



	// set the value_ of this patch to the newly computed flow speed
    this->operator==(Uin);

    // call the base class method to make sure all the other bits and pieces get updated
    fixedValueFvPatchVectorField::updateCoeffs();
}

写出文件

void Foam::prescribedPipeInletFvPatchVectorField::write(Ostream& os) const
{
    fvPatchVectorField::write(os);
    os.writeKeyword("approximationType") << approximationType_ << token::END_STATEMENT << nl;
    os.writeKeyword("flowSpeed") << flowSpeed_ << token::END_STATEMENT << nl;
    os.writeKeyword("deltaByR") << deltaByR_ << token::END_STATEMENT << nl;
    os.writeKeyword("centrepoint") << centrepoint_ << token::END_STATEMENT << nl;
    os.writeKeyword("R") << R_ << token::END_STATEMENT << nl;
    os.writeKeyword("lambda") << lambda_ << token::END_STATEMENT << nl;
    writeEntry(os, "value", *this);
}


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace Foam
{
    makePatchTypeField
    (
        fvPatchVectorField,
        prescribedPipeInletFvPatchVectorField
    );
}

Make

files

输出文件有lib前缀,表示编译成库

prescribedPipeInletFvPatchVectorField.C
LIB = $(FOAM_USER_LIBBIN)/libprescribedPipeInlet

Allwmake

将边界条件编译成库
wmake输出的是可执行文件,如求解器。
wmake libso输出的是.so文件,即动态链接库。

#!/bin/sh
wmake libso

Allwclean

解构库

#!/bin/sh

wclean libso

# ----------------------------------------------------------------- end-of-file

testCase

组成

Allrun.mesh

#!/bin/bash

# read values from the dictionary
controlFile="system/runConditions"
#从system/runConditions文件中查找包含Lpipe的行,提取这些行的第二个字段作为Lpipe的值,并去除该值末尾可能存在的分号,然后将这个处理后的值赋给变量Lpipe
Lpipe=$(awk '/Lpipe/{print $2}' $controlFile | sed 's/;$//')
Rpipe=$(awk '/Rpipe/{print $2}' $controlFile | sed 's/;$//')
Nx=$(awk '/Nx/{print $2}' $controlFile | sed 's/;$//')
NRinner=$(awk '/NRinner/{print $2}' $controlFile | sed 's/;$//')
NRouter=$(awk '/NRouter/{print $2}' $controlFile | sed 's/;$//')
expRatWall=$(awk '/expRatWall/{print $2}' $controlFile | sed 's/;$//')
noQuarters=$(awk '/noQuarters/{print $2}' $controlFile | sed 's/;$//')

# update values in the blockMesh dictionary (optionally could also include the file in the dict
# and use the variables directly - nice to explore different options to do the same thing though)
#将以Nx开头的行替换为Nx   $Nx
sed -i "s/Nx.*;/Nx   $Nx;/g" system/blockMeshDict
sed -i "s/NRinner.*;/NRinner   $NRinner;/g" system/blockMeshDict
sed -i "s/NRouter.*;/NRouter   $NRouter;/g" system/blockMeshDict
sed -i "s/expRatWall.*;/expRatWall   $expRatWall;/g" system/blockMeshDict

# create the baseline mesh of a 1/4 of pipe with unit length and radius
blockMesh

# scale to give the mesh the desired size
#缩放比
transformPoints "scale=(${Lpipe} ${Rpipe} ${Rpipe})"
#该行使用错误,应为
transformPoints -scale "(${Lpipe} ${Rpipe} ${Rpipe})"

# mirror the grid as required
#设置为沿Y轴正方向的单位向量
sed -i "s/normalVector.*;/normalVector (0 1 0);/g" system/mirrorMeshDict

if (( $noQuarters == 2 ))
then
	mirrorMesh -overwrite
fi

if (( $noQuarters == 4 ))
then
	mirrorMesh -overwrite
	sed -i "s/normalVector.*;/normalVector (0 0 1);/g" system/mirrorMeshDict
	mirrorMesh -overwrite
fi

# renumber to optimise parallel running
renumberMesh -overwrite

# ----------------------------------------------------------------- end-of-file

Allrun

可以利用不同求解器计算不同场

#!/bin/bash

./Allrun.mesh > log.mesh 2>&1

cp -r 0.org 0

potentialFoam > log.potentialFoam 2>&1

decomposePar > log.decomposePar 2>&1

echo "Finished preparing, running the solver."

mpirun -np 4 simpleFoam -parallel > log.run 2>&1

reconstructPar -latestTime > log.reconstruct 2>&1

simpleFoam -postProcess -func yPlus -latestTime > log.yPlus
simpleFoam -postProcess -func sample -latestTime > log.sample

rm -r processor*

echo "Done."

# ----------------------------------------------------------------- end-of-file

system/controlDict

其中purgeWrit决定了写过程是否覆盖,如果0则不覆盖,大于0为覆盖,比如:2,case文件家中只有输出文件
比如6和7,当算到8时候,会覆盖6,9会覆盖7,以此类推

posted @ 2024-08-14 19:29  ouqiyo  阅读(52)  评论(0)    收藏  举报