这些内容适用于已经OpenFOAM入门的用户。下列代码均通过OpenFOAM-10的测试。不过应该也适用于OpenFOAM-8以后的版本。若不通过可以随时联系勘误。

OpenFOAM代码汇总

第一部分:下列代码需要在算例文件中植入。例如算例文件的0文件夹中的某个变量内部。

随位置变化的进口

inlet
{
    type            codedFixedValue;
    name            dummy;
    value           uniform (0 0 0);
        
    redirectType    inletLaminarSquareProfile;
    code
    #{
         const vectorField& Cf = patch().Cf(); 

         const scalar H	= 0.0052; 
         const scalar Umax = 0.879542893; 

         forAll(Cf, faceI) // loop over all the patch faces
         {
            const scalar y = Cf[faceI].y() - 0.0049; 
            (*this)[faceI] = vector(Umax*(4*y/H-4*sqr(y/H)), 0, 0);
         }
     #};
 }

随时间变化的进口

inlet
{
    type            uniformFixedValue;
    uniformValue    coded;

    name            pulse;

    codeInclude
    #{
        #include "mathematicalConstants.H"
    #};

    code
    #{
        return vector
        (
            0,
            0.5*(1 - cos(constant::mathematical::twoPi*x)),
            0
        );
    #};
}

边界条件中调用fvc

INLET
{
    type            codedFixedValue;
    value           uniform (10 0 0); 
    name            linearTBC1; 
    codeInclude
    #{
        #include "fvCFD.H"
    #};
    codeOptions
    #{
        -I$(LIB_SRC)/finiteVolume/lnInclude \
        -I$(LIB_SRC)/meshTools/lnInclude
    #};
    codeLibs
    #{
        -lmeshTools \
        -lfiniteVolume
    #};
    code
    #{
        const fvMesh& mesh = this->patch().boundaryMesh().mesh();
        const fvPatch& inletPatch = this->patch();
        const volVectorField& U = mesh.lookupObject<volVectorField>("U");
        volTensorField gradU = fvc::grad(U);
    #};
}

边界条件中调用mesh

INLET
{
    type            codedFixedValue;
    value           uniform (10 0 0); 
    name            linearTBC1; 
    code
    #{
        const fvMesh& mesh = this->patch().boundaryMesh().mesh();
    #};
}

边界条件中计算patch的面积

INLET
{
    type            codedFixedValue;
    value           uniform (10 0 0); 
    name            linearTBC1; 
    code
    #{
        const fvMesh& mesh = this->patch().boundaryMesh().mesh();
        // 计算inlet的面积
        label patchID = mesh.boundaryMesh().findPatchID("inlet");
        const polyPatch& myPatch = mesh.boundaryMesh()[patchID];
        scalar patchArea = 0.0;
        forAll(myPatch, faceI)
        {
            patchArea += mesh.magSf().boundaryField()[patchID][faceI];
        } 
    #};
}

边界条件中调用字典文件

wall
{
    type            codedFixedValue;
    value           uniform (10 0 0);
    name            linearTBC1;
    code
    #{
        const fvMesh& mesh = this->patch().boundaryMesh().mesh();
        dictionary C = mesh.lookupObject<dictionary>("physicalProperties");
        scalar test(readScalar(C.lookup("test")));
    #};
}

边界条件中调用时间步长

INLET
{
    type            codedFixedValue;
    value           uniform (10 0 0); 
    name            linearTBC1; 
    code
    #{
        const fvMesh& mesh = this->patch().boundaryMesh().mesh();
        const scalar deltaT = mesh.time().deltaT().value();
    #};
}

边界条件中更改某个场的值

inlet
{
    type            codedFixedValue;
    value           uniform (10 0 0);
    name            linearTBC1;
    code
    #{
        const fvMesh& mesh = this->patch().boundaryMesh().mesh();
        volVectorField& U = mesh.lookupObjectRef<volVectorField>("U");
    #};
}

第二部分:下列代码需要在程序中植入。例如myFoam.C文件中。

常用CFD变量

tmp<volTensorField> tgradU = fvc::grad(U);

// 形变率的双点积
volScalarField S(magSqr(symm(tgradU())));

声明字典文件

IOdictionary physicalProperties
(
    IOobject
    (
        "physicalProperties",
        runTime.constant(),
        mesh,
        IOobject::MUST_READ_IF_MODIFIED,
        IOobject::NO_WRITE
    )
);

声明体心场

volScalarField T
(
    IOobject
    (
        "T",
        runTime.timeName(),
        mesh,
        IOobject::MUST_READ,
        IOobject::AUTO_WRITE
    ),
    mesh
);

声明面心场

surfaceScalarField phi
(
    IOobject
    (
        "phi",
        runTime.timeName(),
        mesh,
        IOobject::NO_READ,
        IOobject::AUTO_WRITE
    ),
    mesh,
    dimensionedScalar(dimless, 0.0)
);

声明带单位的值

dimensionedScalar DT
(
    "DT",
    dimensionSet(0,0,0,0,0),
    1.0
);

声明不带边界的体心场

// 一个scalarField
volScalarField::Internal TInternal("TInternal", T);

调用内部场常量:

Info<< U.primitiveField();

调用可更改的内部场:

U.primitiveFieldRef() = ...
U.ref() = ...

调用边界场常量:

Info<< U.boundaryField();

调用可更改的边界场:

U.boundaryFieldRef() = ...

禁用log输出

SolverPerformance<scalar>::debug = 0;

创建2套网格

fvMesh mesh1
(
    IOobject
    (
        "mesh1",
        runTime.timeName(),
        runTime,
        IOobject::MUST_READ
    )
);

fvMesh mesh2
(
    IOobject
    (
        "mesh2",
        runTime.timeName(),
        runTime,
        IOobject::MUST_READ
    )
);

读取scalar的值

scalar RR(readScalar(generalProperties.lookup("RR")));

读取bool的值

bool RR(readBool(generalProperties.lookup("RR")));

网格相关量

const scalarField& V = mesh.V();                            // 网格体积
const surfaceVectorField& Sf = mesh.Sf();                   // 网格面矢量
const surfaceScalarField& magSf = mesh.magSf();             // 网格面积的模
const surfaceVectorField& N = Sf/magSf;                     // 网格面法向

更改变量近壁网格体心值

label patchID = mesh.boundaryMesh().findPatchID("wall");
const scalarField TfaceCell 
  = T.boundaryField()[patchID].patchInternalField();
k.boundaryFieldRef()[patchID] == sqrt(TfaceCell);

判断wall边界类型

#include "wallFvPatch.H"

forAll(mesh.boundary(), patchi)
{
    if (isA<wallFvPatch>(mesh.boundary()[patchi]))
    {

    }
}

判断fixedValue边界类型

#include "wallFvPatch.H"

forAll(U.boundaryField(), patchi)
{
    if
    (
        isA<fixedValueFvPatchScalarField>
        (
            T.boundaryField()[patchi]
        ) 
    )
    {

    }
}

判断processor边界类型

forAll(U.boundaryField(), patchi)
{
    if
    (
        isA<processorPolyPatch>
        (
            mesh.boundaryMesn()[patchi]
        ) 
    )
    {

    }
}

把A的边界条件类型赋给B

volScalarField B
(
    IOobject
    (
        "B",
        runTime.timeName(),
        mesh,
        IOobject::NO_READ,
        IOobject::AUTO_WRITE
    ),
    mesh,
    dimensionedScalar(dimless, 0.0),
    A.boundaryField().types()
);

强制边界条件类型

volScalarField B
(
    IOobject
    (
        "B",
        runTime.timeName(),
        mesh,
        IOobject::NO_READ,
        IOobject::AUTO_WRITE
    ),
    mesh,
    dimensionedScalar(dimless, 0.0),
    zeroGradientFvPatchScalarField::typeName
);

寻找并调用某个场

const volScalarField& T(mesh().lookupObject<volScalarField>("T"));

一个动态调整的数组

List<label> markedCell;

for (int i = 0; i < 10; i++)
{
    markedCell.append(i);
}

矩阵操作

scalarSquareMatrix squareMatrix(3, Zero);
squareMatrix(0, 0) = 4;
squareMatrix(0, 1) = 12;
squareMatrix(0, 2) = -16;
squareMatrix(1, 0) = 12;
squareMatrix(1, 1) = 37;
squareMatrix(1, 2) = -43;
squareMatrix(2, 0) = -16;
squareMatrix(2, 1) = -43;
squareMatrix(2, 2) = 98;
const scalarField S(3, 1);

LUscalarMatrix L(squareMatrix);

scalarSquareMatrix inv(3); //矩阵求逆
L.inv(inv);

scalarField x(3, Zero);
scalarField Mx = squareMatrix*x; //矩阵乘以向量

scalarField x(L.solve(S)); //计算L \cdot x = S

声明壁面距离场

#include "wallDist.H"

volScalarField y(wallDist::New(mesh).y());

声明多个场

PtrList<surfaceScalarField> abPosCoeff(4);                                                           
                                                                                                     
forAll(abPosCoeff, i)
{                                                                                                    
    abPosCoeff.set
    (                                                                                                
        i,                                                                                           
        new surfaceScalarField                                                                       
        (                                                                                            
            IOobject                                                                                 
            (                                                                                        
                "abPosCoeff" + name(i),                                                              
                mesh.time().timeName(),                                                              
                mesh,                                                                                
                IOobject::NO_READ,                                                                   
                IOobject::NO_WRITE                                                                   
            ),                                                                                       
            mesh,                                                                                    
            dimensionedScalar(inv(dimLength), 0.0)                                                   
        )                                                                                            
    );                                                                                               
} 

修改const变量

volScalarField& alphat =
    const_cast<volScalarField&>(mesh().lookupObject<volScalarField>("alphat"));  

声明tmp变量

tmp<volScalarField> deltaLambdaT   
(
    volScalarField::New
    (
        "deltaLambdaT",
        mesh,
        dimensionedScalar(dimless, 1.0)
    )   
);  

监控代码计算时间

#include <chrono>

auto start = std::chrono::steady_clock::now();                                                   
// Functions here
auto end = std::chrono::steady_clock::now();                                                     
auto diff = end - start;
Info<< "Calculate nodes and weights, using " 
    << std::chrono::duration <double, std::milli> (diff).count()                                 
    << " ms" << endl;

在文件夹中输出scalarField

IOField<scalar> utau
(
    IOobject
    (
        "utau",
         runTime.constant(),
        "../postProcessing",//输出到postProcessing文件夹中
        mesh,
        IOobject::NO_READ,
        IOobject::AUTO_WRITE 
    ),
    scalarField(totalFSize,0.0)
);

对某个变量做界限

bound(S, dimensionedScalar(S.dimensions(), 0));

下面的代码,可以放到算例文件的controlDict中执行。

输出时间平均值

functions
{
    #includeFunc fieldAverage(U, p, prime2Mean = yes)
    #includeFunc mag(UPrime2Mean)
    #includeFunc multiply(half, mag(UPrime2Mean), result = k)
}

输出重组速度场

functions
{
    #includeFunc reconstruct(phi)
}

转换坐标系

functions
{
    cartesianToCylindrical
    {
        type        cylindrical;
        libs        ("libfieldFunctionObjects.so");

        origin      (0 0 0);
        axis        (1 0 0);

        field       U;

        writeControl    outputTime;
        writeInterval   1;
    }
}

屏蔽迭代求解器输出

DebugSwitches
{
    SolverPerformance   0;
}

输出空气龄

functions
{
    age
    {
        libs            ("libfieldFunctionObjects.so");
        type            age;

        diffusion       on;

        writeControl    writeTime;
        executeControl  writeTime;
    }
}

输出舒适度

functions
{
    comfort
    {
        libs            ("libfieldFunctionObjects.so");
        type            comfort;

        clothing        0.5;
        metabolicRate   1.2;
        extWork         0;
        relHumidity     60;

        writeControl    writeTime;
        executeControl  writeTime;
    }
}

输出缓存场

cacheTemporaryObjects
(
    kEpsilon:G
);

functions
{
    #includeFunc writeObjects(kEpsilon:G)
}

输出热通量

functions
{
    wallHeatFlux1
    {
        type        wallHeatFlux;
        libs        ("libfieldFunctionObjects.so");
        region      fluid;
        patches     (".*Wall");
    }
}

输出速度分量

functions
{
    #includeFunc components(U)
}

输出变量

functions
{
    setDeltaT
    {
        type coded;
        libs            ("libutilityFunctionObjects.so");
        writeControl    writeTime;
        executeControl  writeTime;

        code
        #{
        #};

        codeExecute
        #{
            const volVectorField& U
            (
                mesh().lookupObject<volVectorField>("U")
            ); 
            volScalarField strainRate(sqrt(2.0)*mag(symm(fvc::grad(U))));
            strainRate.write();
        #};
    }
}

自定义deltaT

functions
{
    setDeltaT
    {
        type coded;
        libs            ("libutilityFunctionObjects.so");
        codeExecute
        #{
            const Time& runTime = mesh().time();
            if (runTime.userTimeValue() >= -15.0)
            {
                const_cast<Time&>(runTime).setDeltaT
                (
                    runTime.userTimeToTime(0.025)
                );
            }
        #};
    }
}

输出马赫数

functions
{
    #includeFunc MachNo
}

输出yPlus

functions
{
    #includeFunc yPlus
}

输出涡量相关场

functions
{
    #includeFunc Q
    #includeFunc vorticity
    #includeFunc Lambda2
}

输出示踪颗粒

functions
{
    particles
    {
        libs        ("liblagrangianFunctionObjects.so");
        type        particles;
    }
}

输出多相界面

libs
(
    "libwaves.so"
);

functions
{
    #includeFunc isoSurface(isoField=alpha.water, isoValue=0.5, fields=())
}

输出界面高度

libs
(
    "libwaves.so"
);

functions
{
    interfaceHeight1
    {
        type            interfaceHeight;
        libs            ("libfieldFunctionObjects.so");
        locations       ((300 0 0) (450 0 0) (600 0 0));
        alpha           alpha.water;
    }
}

输出变量最大值的网格单元

functions
{
    #includeFunc cellMax(p)
}

输出传输标量

functions
{
    #includeFunc scalarTransport(s)
}

输出某个场的最大值

functions
{
    minMaxp
    {
        type        fieldMinMax;
        functionObjectLibs ("libfieldFunctionObjects.so");
        fields
        (
             U
        );
        location        no;
        writeControl    timeStep;
        writeInterval   1;
    }
}

输出阻力系数

functions
{
    forces
    {
        type            forceCoeffs;
        libs            ("libforces.so");
        writeControl    timeStep;
        writeInterval   1;
    
        patches         ("motorBike.*");
        rho             rhoInf;      // Indicates incompressible
        log             true;
        rhoInf          1;           // Redundant for incompressible
        liftDir         (0 0 1);
        dragDir         (1 0 0);
        CofR            (0.72 0 0);  // Axle midpoint on ground
        pitchAxis       (0 1 0);
        magUInf         20;
        lRef            1.42;        // Wheelbase length
        Aref            0.75;        // Estimated
    }
}

输出流线图1

functions
{
    streamlines
    {
        type            streamlines;
    
        libs            ("libfieldFunctionObjects.so");
    
        // Output every
        writeControl    writeTime;
    
        // Write format
        setFormat       vtk;
    
        // Track forward (+U) or backward (-U) or both
        direction       forward;
    
        // Names of fields to sample. Should contain above velocity field!
        fields (p U);
    
        // Steps particles can travel before being removed
        lifeTime        10000;
    
        // Number of steps per cell (estimate). Set to 1 to disable subcycling.
        nSubCycle 5;
    
        // Cloud name to use
        cloudName       particleTracks;
    
        // Seeding method.
        seedSampleSet
        {
            type        lineUniform;
            start       (-1.001 1e-7 0.0011);
            end         (-1.001 1e-7 1.0011);
            nPoints     20;
        }
    }
}

输出流线图2

functions
{
    #includeFunc streamlinesLine(funcName=streamlines, start=(0 0.5 0), end=(9 0.5 0), nPoints=24, U)
}

输出残差

functions
{
    residuals
    {
        type            residuals;

        libs            ("libutilityFunctionObjects.so");

        writeControl    timeStep;
        writeInterval   1;
        fields
        (
            U
            p
        );
    }
}

监控流率

functions
{
    #includeFunc patchFlowRate(patch=outlet1)
    #includeFunc faceZoneFlowRate(name=fz1)
    #includeFunc patchFlowRate(patch=outlet2)
    #includeFunc faceZoneFlowRate(name=fz2)
}

输出平均值

functions
{
    #includeFunc patchAverage(patch=outlet, fields=(p U))
    #includeFunc patchAverage(patch=inlet, fields=(p U))
}

对体场做积分操作(如总体积)

functions
{
    volFieldValue1
    {
        type            volFieldValue;
        libs            ("libfieldFunctionObjects.so");
        writeControl    writeTime;
        log             yes;
        writeFields     no;
        regionType      all;
        name            outlet;
        operation       volIntegrate;//min, max, etc.
        //weightField     phi;
        fields
        (
            alpha
        );
    }
}

对体场做积分操作(例如平均温度)

functions
{
    volFieldValue1
    {
        type            volFieldValue;
        libs            ("libfieldFunctionObjects.so");
        writeControl    writeTime;
        log             yes;
        writeFields     no;
        regionType      all;
        name            outlet;
        operation       volAverage;//min, max, etc.
        fields
        (
            T
        );
    }
}