向DPMFoam或MPPICFoam求解器中添加源项

OpenFOAM-2.3.x版本中的DPMFoam与MPPICFoam求解器无法对用户自定义源操作(即fvOptions)进行处理,需要修改DPMFoam以及MPPICFoam求解器的源码,以实现其对fvOptions的处理。

在对OpenFOAM中给定的算例进行分析时发现,$FOAM_TUTORIALS/incompressible/pimpleFoam算例的

而DPMFoam及MPPICFoam中流体求解部分采取的是PIMPLE方法,因此可以借鉴pimpleFoam求解器对于fvOptions的处理,并对照pimpleFoam求解器的源码将fvOptions加入到DPMFoam以及MPPICFoam求解器中。

求解器分析

实际上,MPPICFoam求解器与DPMFoam求解器基本一致,只是对颗粒的部分处理方式不一样,这从MPPICFoam求解器源码也可以看出:

// MPPICFoam.C
#define MPPIC

#include "DPMFoam.C"

因此,对DPMFoam求解器的修改也就自然包含了对MPPICFoam求解器的修改。DPMFoam求解器的主程序如下:

// DPMFoam.C

#include "fvCFD.H"
#include "singlePhaseTransportModel.H"
#include "PhaseIncompressibleTurbulenceModel.H"
#include "pimpleControl.H"
#include "fixedFluxPressureFvPatchScalarField.H"

#ifdef MPPIC
    #include "basicKinematicMPPICCloud.H"
    #define basicKinematicTypeCloud basicKinematicMPPICCloud
#else
    #include "basicKinematicCollidingCloud.H"
    #define basicKinematicTypeCloud basicKinematicCollidingCloud
#endif

int main(int argc, char *argv[])
{
    argList::addOption
    (
        "cloudName",
        "name",
        "specify alternative cloud name. default is 'kinematicCloud'"
    );

    #include "setRootCase.H"
    #include "createTime.H"
    #include "createMesh.H"
    #include "readGravitationalAcceleration.H"
    #include "createFields.H"
    #include "initContinuityErrs.H"

    pimpleControl pimple(mesh);

    Info<< "\nStarting time loop\n" << endl;

    while (runTime.run())
    {
        #include "readTimeControls.H"
        #include "CourantNo.H"
        #include "setDeltaT.H"

        runTime++;

        Info<< "Time = " << runTime.timeName() << nl << endl;

        continuousPhaseTransport.correct();
        muc = rhoc*continuousPhaseTransport.nu();

        Info<< "Evolving " << kinematicCloud.name() << endl;
        kinematicCloud.evolve();

        // Update continuous phase volume fraction field
        alphac = max(1.0 - kinematicCloud.theta(), alphacMin);
        alphac.correctBoundaryConditions();
        alphacf = fvc::interpolate(alphac);
        alphaPhic = alphacf*phic;

        fvVectorMatrix cloudSU(kinematicCloud.SU(Uc));
        volVectorField cloudVolSUSu
        (
            IOobject
            (
                "cloudVolSUSu",
                runTime.timeName(),
                mesh
            ),
            mesh,
            dimensionedVector
            (
                "0",
                cloudSU.dimensions()/dimVolume,
                vector::zero
            ),
            zeroGradientFvPatchVectorField::typeName
        );

        cloudVolSUSu.internalField() = -cloudSU.source()/mesh.V();
        cloudVolSUSu.correctBoundaryConditions();
        cloudSU.source() = vector::zero;

        // --- Pressure-velocity PIMPLE corrector loop
        while (pimple.loop())
        {
            #include "UcEqn.H"

            // --- PISO loop
            while (pimple.correct())
            {
                #include "pEqn.H"
            }

            if (pimple.turbCorr())
            {
                continuousPhaseTurbulence->correct();
            }
        }

        runTime.write();

        Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
            << "  ClockTime = " << runTime.elapsedClockTime() << " s"
            << nl << endl;
    }

    Info<< "End\n" << endl;

    return 0;
}

可以发现其中并不包含对fvOptions的处理。此外可以发现DPMFoam求解器在对流场进行求解时使用的是PIMPLE算法,而OpenFOAM的不可压缩流体求解器pimpleFoam是可以对fvOptions进行处理的,因而可以借鉴pimpleFoam源码中对fvOptions的处理方式,对DPMFoam源码进行修改。

pimpleFoam求解器的主程序如下,程序中为了处理fvOptions所添加的头文件已通过注释标示出:

// pimpleFoam.C

#include "fvCFD.H"
#include "singlePhaseTransportModel.H"
#include "turbulenceModel.H"
#include "pimpleControl.H"

// !!! Here
#include "fvIOoptionList.H"
#include "IOporosityModelList.H"
#include "IOMRFZoneList.H"

#include "fixedFluxPressureFvPatchScalarField.H"

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

int main(int argc, char *argv[])
{
    #include "setRootCase.H"
    #include "createTime.H"
    #include "createMesh.H"
    #include "createFields.H"

    // !!! Here
    #include "createFvOptions.H"

    #include "initContinuityErrs.H"

    pimpleControl pimple(mesh);

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

    Info<< "\nStarting time loop\n" << endl;

    while (runTime.run())
    {
        #include "readTimeControls.H"
        #include "CourantNo.H"
        #include "setDeltaT.H"

        runTime++;

        Info<< "Time = " << runTime.timeName() << nl << endl;

        // --- Pressure-velocity PIMPLE corrector loop
        while (pimple.loop())
        {
            #include "UEqn.H"

            // --- Pressure corrector loop
            while (pimple.correct())
            {
                #include "pEqn.H"
            }

            if (pimple.turbCorr())
            {
                turbulence->correct();
            }
        }

        runTime.write();

        Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
            << "  ClockTime = " << runTime.elapsedClockTime() << " s"
            << nl << endl;
    }

    Info<< "End\n" << endl;

    return 0;
}

此外,PIMPLE算法循环中的速度方程UEqn.H以及压力方程pEqn.H中均对fvOptions进行了处理,因此在对DPMFoam求解器进行修改的时候,也需要考虑速度方程以及压力方程的修改。

求解器修改

首先需要将OpenFOAM初始的DPMFoam求解器备份:

cd $FOAM_APP/solvers/lagrangian
cp -rfv DPMFoam DPMFoam-bak

然后再修改DPMFoam求解器。

DPMFoam.C

对照pimpleFoam.C,可以初步将fvOptions相关的头文件加入到DPMFoam.C中,如下:

// DPMFoam.C

#include "fvCFD.H"
#include "singlePhaseTransportModel.H"
#include "PhaseIncompressibleTurbulenceModel.H"
#include "pimpleControl.H"
#include "fvIOoptionList.H"
#include "IOporosityModelList.H"
#include "IOMRFZoneList.H"
#include "fixedFluxPressureFvPatchScalarField.H"

#ifdef MPPIC
    #include "basicKinematicMPPICCloud.H"
    #define basicKinematicTypeCloud basicKinematicMPPICCloud
#else
    #include "basicKinematicCollidingCloud.H"
    #define basicKinematicTypeCloud basicKinematicCollidingCloud
#endif

int main(int argc, char *argv[])
{
    argList::addOption
    (
        "cloudName",
        "name",
        "specify alternative cloud name. default is 'kinematicCloud'"
    );

    #include "setRootCase.H"
    #include "createTime.H"
    #include "createMesh.H"
    #include "readGravitationalAcceleration.H"
    #include "createFields.H"
    #include "createFvOptions.H"
    #include "initContinuityErrs.H"

    pimpleControl pimple(mesh);

    // ......
}

UEqn.H

对照pimpleFoam中包含的UEqn.H文件:

// Solve the Momentum equation

tmp<fvVectorMatrix> UEqn
(
    fvm::ddt(U)
  + fvm::div(phi, U)
  + turbulence->divDevReff(U)
 ==
    fvOptions(U)
);

UEqn().relax();

fvOptions.constrain(UEqn());

volScalarField rAU(1.0/UEqn().A());

if (pimple.momentumPredictor())
{
    solve(UEqn() == -fvc::grad(p));

    fvOptions.correct(U);
}

可以将DPMFoam中包含的UEqn.H文件修改为:


// fvOptions is added in the UcEqn.
fvVectorMatrix UcEqn
(
    fvm::ddt(alphac, Uc) + fvm::div(alphaPhic, Uc)
  - fvm::Sp(fvc::ddt(alphac) + fvc::div(alphaPhic), Uc)
  + continuousPhaseTurbulence->divDevRhoReff(Uc)
 ==
    (1.0/rhoc)*cloudSU
  + fvOptions(Uc)
);

UcEqn.relax();

// fvOptions is added here.
fvOptions.constrain(UcEqn);

volScalarField rAUc(1.0/UcEqn.A());
surfaceScalarField rAUcf("Dp", fvc::interpolate(rAUc));

surfaceScalarField phicForces
(
   (fvc::interpolate(rAUc*cloudVolSUSu/rhoc) & mesh.Sf())
 + rAUcf*(g & mesh.Sf())
);

if (pimple.momentumPredictor())
{
    solve
    (
        UcEqn
     ==
        fvc::reconstruct
        (
            phicForces/rAUcf - fvc::snGrad(p)*mesh.magSf()
        )
    );

    // fvOptions is added here.
    fvOptions.correct(Uc);
}

pEqn.H

对照pimpleFoam中包含的pEqn.H文件:

surfaceScalarField rAUf("rAUf", fvc::interpolate(rAU));

volVectorField HbyA("HbyA", U);
HbyA = rAU*UEqn().H();

if (pimple.nCorrPISO() <= 1)
{
    UEqn.clear();
}

surfaceScalarField phiHbyA
(
    "phiHbyA",
    (fvc::interpolate(HbyA) & mesh.Sf())
  + rAUf*fvc::ddtCorr(U, phi)
);

fvOptions.makeRelative(phiHbyA);

adjustPhi(phiHbyA, U, p);

// Update the fixedFluxPressure BCs to ensure flux consistency
setSnGrad<fixedFluxPressureFvPatchScalarField>
(
    p.boundaryField(),
    (
        phiHbyA.boundaryField()
      - fvOptions.relative(mesh.Sf().boundaryField() & U.boundaryField())
    )/(mesh.magSf().boundaryField()*rAUf.boundaryField())
);

// Non-orthogonal pressure corrector loop
while (pimple.correctNonOrthogonal())
{
    // Pressure corrector
    fvScalarMatrix pEqn
    (
        fvm::laplacian(rAUf, p) == fvc::div(phiHbyA)
    );

    pEqn.setReference(pRefCell, pRefValue);

    pEqn.solve(mesh.solver(p.select(pimple.finalInnerIter())));

    if (pimple.finalNonOrthogonalIter())
    {
        phi = phiHbyA - pEqn.flux();
    }
}

#include "continuityErrs.H"

// Explicitly relax pressure for momentum corrector
p.relax();

U = HbyA - rAU*fvc::grad(p);
U.correctBoundaryConditions();
fvOptions.correct(U);

可以将DPMFoam中包含的pEqn.H文件修改为:

{
    volVectorField HbyA("HbyA", Uc);
    HbyA = rAUc*UcEqn.H();

    surfaceScalarField phiHbyA
    (
        "phiHbyA",
        (
           (fvc::interpolate(HbyA) & mesh.Sf())
         + alphacf*rAUcf*fvc::ddtCorr(Uc, phic)
         + phicForces
        )
    );

    // fvOptions is added here.
    fvOptions.makeRelative(phiHbyA);

    // fvOptions is added here.
    // Update the fixedFluxPressure BCs to ensure flux consistency
    setSnGrad<fixedFluxPressureFvPatchScalarField>
    (
        p.boundaryField(),
        (
            phiHbyA.boundaryField()
          - fvOptions.relative(mesh.Sf().boundaryField() & Uc.boundaryField())
        )/(mesh.magSf().boundaryField()*rAUcf.boundaryField())
    );

    // Non-orthogonal pressure corrector loop
    while (pimple.correctNonOrthogonal())
    {
        fvScalarMatrix pEqn
        (
            fvm::laplacian(alphacf*rAUcf, p)
         ==
            fvc::ddt(alphac) + fvc::div(alphacf*phiHbyA)
        );

        pEqn.setReference(pRefCell, pRefValue);

        pEqn.solve(mesh.solver(p.select(pimple.finalInnerIter())));

        if (pimple.finalNonOrthogonalIter())
        {
            phic = phiHbyA - pEqn.flux()/alphacf;

            p.relax();

            Uc = HbyA
              + rAUc*fvc::reconstruct((phicForces - pEqn.flux()/alphacf)/rAUcf);
            Uc.correctBoundaryConditions();

            // fvOptions is added here.
            fvOptions.correct(Uc);
        }
    }
}

#include "continuityErrs.H"

其他文件修改

Make/options

在该文件中的EXE_INC选项中添加-I$(LIB_SRC)/fvOptions/lnInclude-I$(LIB_SRC)/sampling/lnInclude。在该文件中的EXE_LIBS选项中添加-lfvOptions-lsamping。这里要注意每行行尾的转义字符\

添加这些选项的原因是使用OpenFOAM自带的编译工具wmake进行编译时,可以通过EXE_INCEXE_LIBS来寻找需要包含的源文件以及需要链接的库文件。增加fvOptions相关的源文件及库文件路径可以保证编译的顺利进行。

MPPICFoam/make/options

该文件的修改方式与Make/options文件的修改方式相同。

编译

在DPMFoam目录中执行如下命令:

./Allwclean
./Allwmake

即可以实现修改后求解器的编译。

你可能感兴趣的:(#,OpenFOAM技术总结,OpenFOAM,MPPIC)