Projection Methods
本文最后更新于:2021年1月14日 上午
This post is for projection methods in CFD.
PISO Algorithm
// Pressure-velocity PISO corrector
{
// Solve the Momentum equation
MRF.correctBoundaryVelocity(U);
fvVectorMatrix UEqn
(
fvm::ddt(U) + fvm::div(phi, U)
+ MRF.DDt(U)
+ turbulence->divDevSigma(U)
==
fvOptions(U)
);
UEqn.relax();
fvOptions.constrain(UEqn);
if (piso.momentumPredictor())
{
solve(UEqn == -fvc::grad(p));
fvOptions.correct(U);
}
// --- PISO loop
while (piso.correct())
{
volScalarField rAU(1.0/UEqn.A());
volVectorField HbyA(constrainHbyA(rAU*UEqn.H(), U, p));
surfaceScalarField phiHbyA
(
"phiHbyA",
fvc::flux(HbyA)
+ MRF.zeroFilter(fvc::interpolate(rAU)*fvc::ddtCorr(U, phi))
);
MRF.makeRelative(phiHbyA);
adjustPhi(phiHbyA, U, p);
// Update the pressure BCs to ensure flux consistency
constrainPressure(p, U, phiHbyA, rAU, MRF);
// Non-orthogonal pressure corrector loop
while (piso.correctNonOrthogonal())
{
// Pressure corrector
fvScalarMatrix pEqn
(
fvm::laplacian(rAU, p) == fvc::div(phiHbyA)
);
pEqn.setReference(pRefCell, pRefValue);
pEqn.solve();
if (piso.finalNonOrthogonalIter())
{
phi = phiHbyA - pEqn.flux();
}
}
#include "continuityErrs.H"
U = HbyA - rAU*fvc::grad(p);
U.correctBoundaryConditions();
fvOptions.correct(U);
}
}
PIMPLE Algorithm
while (pimple.run(runTime))
{
#include "readDyMControls.H"
if (LTS)
{
#include "setRDeltaT.H"
}
else
{
#include "CourantNo.H"
#include "setDeltaT.H"
}
runTime++;
Info<< "Time = " << runTime.timeName() << nl << endl;
// --- Pressure-velocity PIMPLE corrector loop
while (pimple.loop())
{
if (pimple.firstPimpleIter() || moveMeshOuterCorrectors)
{
mesh.update();
if (mesh.changing())
{
MRF.update();
if (correctPhi)
{
// Calculate absolute flux
// from the mapped surface velocity
phi = mesh.Sf() & Uf();
CorrectPhi
(
U,
phi,
p,
dimensionedScalar("rAUf", dimTime, 1),
geometricZeroField(),
pimple,
true
);
// Make the flux relative to the mesh motion
fvc::makeRelative(phi, U);
}
if (checkMeshCourantNo)
{
#include "meshCourantNo.H"
}
}
}
MRF.correctBoundaryVelocity(U);
tmp<fvVectorMatrix> tUEqn
(
fvm::ddt(U) + fvm::div(phi, U)
+ MRF.DDt(U)
+ turbulence->divDevSigma(U)
==
fvOptions(U)
);
fvVectorMatrix& UEqn = tUEqn.ref();
UEqn.relax();
fvOptions.constrain(UEqn);
if (pimple.momentumPredictor())
{
solve(UEqn == -fvc::grad(p));
fvOptions.correct(U);
}
// --- Pressure corrector loop
while (pimple.correct())
{
volScalarField rAU(1.0/UEqn.A());
volVectorField HbyA(constrainHbyA(rAU*UEqn.H(), U, p));
surfaceScalarField phiHbyA
(
"phiHbyA",
fvc::flux(HbyA)
+ MRF.zeroFilter(fvc::interpolate(rAU)*fvc::ddtCorr(U, phi, Uf))
);
MRF.makeRelative(phiHbyA);
if (p.needReference())
{
fvc::makeRelative(phiHbyA, U);
adjustPhi(phiHbyA, U, p);
fvc::makeAbsolute(phiHbyA, U);
}
tmp<volScalarField> rAtU(rAU);
if (pimple.consistent())
{
rAtU = 1.0/max(1.0/rAU - UEqn.H1(), 0.1/rAU);
phiHbyA +=
fvc::interpolate(rAtU() - rAU)*fvc::snGrad(p)*mesh.magSf();
HbyA -= (rAU - rAtU())*fvc::grad(p);
}
if (pimple.nCorrPiso() <= 1)
{
tUEqn.clear();
}
// Update the pressure BCs to ensure flux consistency
constrainPressure(p, U, phiHbyA, rAtU(), MRF);
// Non-orthogonal pressure corrector loop
while (pimple.correctNonOrthogonal())
{
fvScalarMatrix pEqn
(
fvm::laplacian(rAtU(), p) == fvc::div(phiHbyA)
);
pEqn.setReference(pRefCell, pRefValue);
pEqn.solve();
if (pimple.finalNonOrthogonalIter())
{
phi = phiHbyA - pEqn.flux();
}
}
#include "continuityErrs.H"
// Explicitly relax pressure for momentum corrector
p.relax();
U = HbyA - rAtU*fvc::grad(p);
U.correctBoundaryConditions();
fvOptions.correct(U);
// Correct Uf if the mesh is moving
fvc::correctUf(Uf, U, phi);
// Make the fluxes relative to the mesh motion
fvc::makeRelative(phi, U);
}
if (pimple.turbCorr())
{
laminarTransport.correct();
turbulence->correct();
}
}
}
Runge kutta Algorithm
U 4th order p 2nd order
for (int cycle =0; cycle < rkCoeff.size(); cycle++)
{
phi = (fvc::interpolate(U) & mesh.Sf()); // evaluate flux
dU = runTime.deltaT()*(fvc::laplacian(turbulence->nuEff(), U) - fvc::div(phi,U));
Uc = Uc + rkCoeff[cycle]*dU;
U = Uold + rkCoeff1[cycle]*dU;
if(cycle==3) U=Uc;
U.correctBoundaryConditions();
solve( pEqn == fvc::div(U)/runTime.deltaT());
U = U -fvc::grad(p)*runTime.deltaT();
U.correctBoundaryConditions();
if(cycle==1) p2 = p;
if(cycle==3) p = 4*p - 3*p2;
}
phi = (fvc::interpolate(U) & mesh.Sf());
turbulence->correct();
#include "continuityErrs.H"
Rhie-Chow Algorithm
U p 2nd order
while (runTime.loop())
{
Info<< "Time = " << runTime.timeName() << nl << endl;
#include "readPISOControls.H"
#include "CourantNo.H"
// Non-iterative projection scheme
{
//linearization of convective flux using second order extrapolation
surfaceScalarField phi_o(0.5*(3.0*phi.oldTime()-phi.oldTime().oldTime()));
// Momentum step
fvVectorMatrix UEqn
(
fvm::ddt(U)
+ fvm::div(phi_o, U)
+ turbulence->divDevReff(U)
);
solve(UEqn == -fvc::grad(p));
// Projection step
dimensionedScalar dt=runTime.deltaT();
scalar rDeltaT=1.0/dt.value();
U += dt*fvc::grad(p);
U.correctBoundaryConditions();
phi= (fvc::interpolate(U) & mesh.Sf());
adjustPhi(phi, U, p);
for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
{
fvScalarMatrix pEqn
(
fvm::laplacian(dt, p) == fvc::div(phi)
);
pEqn.setReference(pRefCell, pRefValue);
if(nonOrth == nNonOrthCorr)
{
pEqn.solve(mesh.solver("pFinal"));
}
else
{
pEqn.solve();
}
if (nonOrth == nNonOrthCorr)
{
phi -= pEqn.flux();
}
}
#include "continuityErrs.H"
U -= dt*fvc::grad(p);
U.correctBoundaryConditions();
}
turbulence->correct();
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!