compressibleInterFoam: Improved mass conservation

using the continuity error correction formulation developed for
twoPhaseEulerFoam and reactingEulerFoam.
This commit is contained in:
Henry Weller
2017-06-22 14:42:36 +01:00
parent 7bdbab7f4e
commit e8daaa5c76
18 changed files with 162 additions and 76 deletions

View File

@ -113,6 +113,8 @@
phiCN, phiCN,
upwind<scalar>(mesh, phiCN) upwind<scalar>(mesh, phiCN)
).fvmDiv(phiCN, alpha1) ).fvmDiv(phiCN, alpha1)
// - fvm::Sp(fvc::ddt(dimensionedScalar("1", dimless, 1), mesh)
// + fvc::div(phiCN), alpha1)
== ==
Su + fvm::Sp(Sp + divU, alpha1) Su + fvm::Sp(Sp + divU, alpha1)
); );
@ -125,19 +127,19 @@
<< " Max(" << alpha1.name() << ") = " << max(alpha1).value() << " Max(" << alpha1.name() << ") = " << max(alpha1).value()
<< endl; << endl;
tmp<surfaceScalarField> talphaPhiUD(alpha1Eqn.flux()); tmp<surfaceScalarField> talphaPhi1UD(alpha1Eqn.flux());
alphaPhi = talphaPhiUD(); alphaPhi10 = talphaPhi1UD();
if (alphaApplyPrevCorr && talphaPhiCorr0.valid()) if (alphaApplyPrevCorr && talphaPhi1Corr0.valid())
{ {
Info<< "Applying the previous iteration compression flux" << endl; Info<< "Applying the previous iteration compression flux" << endl;
MULES::correct(alpha1, alphaPhi, talphaPhiCorr0.ref(), 1, 0); MULES::correct(alpha1, alphaPhi10, talphaPhi1Corr0.ref(), 1, 0);
alphaPhi += talphaPhiCorr0(); alphaPhi10 += talphaPhi1Corr0();
} }
// Cache the upwind-flux // Cache the upwind-flux
talphaPhiCorr0 = talphaPhiUD; talphaPhi1Corr0 = talphaPhi1UD;
alpha2 = 1.0 - alpha1; alpha2 = 1.0 - alpha1;
@ -151,7 +153,7 @@
surfaceScalarField phir(phic*mixture.nHatf()); surfaceScalarField phir(phic*mixture.nHatf());
tmp<surfaceScalarField> talphaPhiUn tmp<surfaceScalarField> talphaPhi1Un
( (
fvc::flux fvc::flux
( (
@ -169,15 +171,15 @@
if (MULESCorr) if (MULESCorr)
{ {
tmp<surfaceScalarField> talphaPhiCorr(talphaPhiUn() - alphaPhi); tmp<surfaceScalarField> talphaPhi1Corr(talphaPhi1Un() - alphaPhi10);
volScalarField alpha10("alpha10", alpha1); volScalarField alpha10("alpha10", alpha1);
MULES::correct MULES::correct
( (
geometricOneField(), geometricOneField(),
alpha1, alpha1,
talphaPhiUn(), talphaPhi1Un(),
talphaPhiCorr.ref(), talphaPhi1Corr.ref(),
Sp, Sp,
(-Sp*alpha1)(), (-Sp*alpha1)(),
1, 1,
@ -187,24 +189,24 @@
// Under-relax the correction for all but the 1st corrector // Under-relax the correction for all but the 1st corrector
if (aCorr == 0) if (aCorr == 0)
{ {
alphaPhi += talphaPhiCorr(); alphaPhi10 += talphaPhi1Corr();
} }
else else
{ {
alpha1 = 0.5*alpha1 + 0.5*alpha10; alpha1 = 0.5*alpha1 + 0.5*alpha10;
alphaPhi += 0.5*talphaPhiCorr(); alphaPhi10 += 0.5*talphaPhi1Corr();
} }
} }
else else
{ {
alphaPhi = talphaPhiUn; alphaPhi10 = talphaPhi1Un;
MULES::explicitSolve MULES::explicitSolve
( (
geometricOneField(), geometricOneField(),
alpha1, alpha1,
phiCN, phiCN,
alphaPhi, alphaPhi10,
Sp, Sp,
(Su + divU*min(alpha1(), scalar(1)))(), (Su + divU*min(alpha1(), scalar(1)))(),
1, 1,
@ -219,34 +221,37 @@
if (alphaApplyPrevCorr && MULESCorr) if (alphaApplyPrevCorr && MULESCorr)
{ {
talphaPhiCorr0 = alphaPhi - talphaPhiCorr0; talphaPhi1Corr0 = alphaPhi10 - talphaPhi1Corr0;
talphaPhiCorr0.ref().rename("alphaPhiCorr0"); talphaPhi1Corr0.ref().rename("alphaPhi1Corr0");
} }
else else
{ {
talphaPhiCorr0.clear(); talphaPhi1Corr0.clear();
} }
#include "rhofs.H"
if if
( (
word(mesh.ddtScheme("ddt(rho,U)")) word(mesh.ddtScheme("ddt(rho,U)"))
== fv::EulerDdtScheme<vector>::typeName == fv::EulerDdtScheme<vector>::typeName
|| word(mesh.ddtScheme("ddt(rho,U)"))
== fv::localEulerDdtScheme<vector>::typeName
) )
{ {
#include "rhofs.H" rhoPhi = alphaPhi10*(rho1f - rho2f) + phiCN*rho2f;
rhoPhi = alphaPhi*(rho1f - rho2f) + phiCN*rho2f;
} }
else else
{ {
if (ocCoeff > 0) if (ocCoeff > 0)
{ {
// Calculate the end-of-time-step alpha flux // Calculate the end-of-time-step alpha flux
alphaPhi = (alphaPhi - (1.0 - cnCoeff)*alphaPhi.oldTime())/cnCoeff; alphaPhi10 =
(alphaPhi10 - (1.0 - cnCoeff)*alphaPhi10.oldTime())/cnCoeff;
} }
// Calculate the end-of-time-step mass flux // Calculate the end-of-time-step mass flux
#include "rhofs.H" rhoPhi = alphaPhi10*(rho1f - rho2f) + phi*rho2f;
rhoPhi = alphaPhi*(rho1f - rho2f) + phi*rho2f;
} }
Info<< "Phase-1 volume fraction = " Info<< "Phase-1 volume fraction = "

View File

@ -1,20 +1,20 @@
IOobject alphaPhiHeader IOobject alphaPhi10Header
( (
"alphaPhi", "alphaPhi10",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
); );
const bool alphaRestart = alphaPhiHeader.headerOk(); const bool alphaRestart = alphaPhi10Header.headerOk();
// MULES flux from previous time-step // MULES flux from previous time-step
surfaceScalarField alphaPhi surfaceScalarField alphaPhi10
( (
alphaPhiHeader, alphaPhi10Header,
phi*fvc::interpolate(alpha1) phi*fvc::interpolate(alpha1)
); );
// MULES Correction // MULES Correction
tmp<surfaceScalarField> talphaPhiCorr0; tmp<surfaceScalarField> talphaPhi1Corr0;

View File

@ -1,8 +1,8 @@
{ {
fvScalarMatrix TEqn fvScalarMatrix TEqn
( (
fvm::ddt(rho, T) fvm::ddt(rho, T) + fvm::div(rhoPhi, T)
+ fvm::div(rhoPhi, T) - fvm::Sp(contErr, T)
- fvm::laplacian(mixture.alphaEff(turbulence->mut()), T) - fvm::laplacian(mixture.alphaEff(turbulence->mut()), T)
+ ( + (
fvc::div(fvc::absolute(phi, U), p) fvc::div(fvc::absolute(phi, U), p)

View File

@ -1,6 +1,7 @@
fvVectorMatrix UEqn fvVectorMatrix UEqn
( (
fvm::ddt(rho, U) + fvm::div(rhoPhi, U) fvm::ddt(rho, U) + fvm::div(rhoPhi, U)
- fvm::Sp(contErr, U)
+ MRF.DDt(rho, U) + MRF.DDt(rho, U)
+ turbulence->divDevRhoReff(U) + turbulence->divDevRhoReff(U)
== ==

View File

@ -24,14 +24,14 @@ volScalarField::Internal Su
forAll(dgdt, celli) forAll(dgdt, celli)
{ {
if (dgdt[celli] > 0.0 && alpha1[celli] > 0.0) if (dgdt[celli] > 0.0)
{ {
Sp[celli] -= dgdt[celli]*alpha1[celli]; Sp[celli] -= dgdt[celli]/max(1.0 - alpha1[celli], 1e-4);
Su[celli] += dgdt[celli]*alpha1[celli]; Su[celli] += dgdt[celli]/max(1.0 - alpha1[celli], 1e-4);
} }
else if (dgdt[celli] < 0.0 && alpha1[celli] < 1.0) else if (dgdt[celli] < 0.0)
{ {
Sp[celli] += dgdt[celli]*(1.0 - alpha1[celli]); Sp[celli] += dgdt[celli]/max(alpha1[celli], 1e-4);
} }
} }

View File

@ -1,3 +1,69 @@
tmp<surfaceScalarField> talphaPhi1(alphaPhi10);
if (nAlphaSubCycles > 1)
{ {
#include "alphaEqnSubCycle.H" dimensionedScalar totalDeltaT = runTime.deltaT();
talphaPhi1 = new surfaceScalarField
(
IOobject
(
"alphaPhi1",
runTime.timeName(),
mesh
),
mesh,
dimensionedScalar("0", alphaPhi10.dimensions(), 0)
);
surfaceScalarField rhoPhiSum
(
IOobject
(
"rhoPhiSum",
runTime.timeName(),
mesh
),
mesh,
dimensionedScalar("0", rhoPhi.dimensions(), 0)
);
tmp<volScalarField> trSubDeltaT;
if (LTS)
{
trSubDeltaT =
fv::localEulerDdt::localRSubDeltaT(mesh, nAlphaSubCycles);
}
for
(
subCycle<volScalarField> alphaSubCycle(alpha1, nAlphaSubCycles);
!(++alphaSubCycle).end();
)
{
#include "alphaEqn.H"
talphaPhi1.ref() += (runTime.deltaT()/totalDeltaT)*alphaPhi10;
rhoPhiSum += (runTime.deltaT()/totalDeltaT)*rhoPhi;
}
rhoPhi = rhoPhiSum;
} }
else
{
#include "alphaEqn.H"
}
rho == alpha1*rho1 + alpha2*rho2;
const surfaceScalarField& alphaPhi1 = talphaPhi1();
surfaceScalarField alphaPhi2("alphaPhi2", phi - alphaPhi1);
volScalarField::Internal contErr
(
(
fvc::ddt(rho) + fvc::div(rhoPhi)
- (fvOptions(alpha1, mixture.thermo1().rho())&rho1)
- (fvOptions(alpha2, mixture.thermo2().rho())&rho2)
)()
);

View File

@ -146,8 +146,6 @@ int main(int argc, char *argv[])
#include "alphaControls.H" #include "alphaControls.H"
#include "compressibleAlphaEqnSubCycle.H" #include "compressibleAlphaEqnSubCycle.H"
solve(fvm::ddt(rho) + fvc::div(rhoPhi));
#include "UEqn.H" #include "UEqn.H"
#include "TEqn.H" #include "TEqn.H"

View File

@ -56,13 +56,29 @@
} }
else else
{ {
#include "rhofs.H"
p_rghEqnComp1 = p_rghEqnComp1 =
fvc::ddt(rho1) + psi1*correction(fvm::ddt(p_rgh)) pos(alpha1)
+ fvc::div(phi, rho1) - fvc::Sp(fvc::div(phi), rho1); *(
(
fvc::ddt(alpha1, rho1) + fvc::div(alphaPhi1*rho1f)
- (fvOptions(alpha1, mixture.thermo1().rho())&rho1)
)/rho1
- fvc::ddt(alpha1) - fvc::div(alphaPhi1)
+ (alpha1*psi1/rho1)*correction(fvm::ddt(p_rgh))
);
p_rghEqnComp2 = p_rghEqnComp2 =
fvc::ddt(rho2) + psi2*correction(fvm::ddt(p_rgh)) pos(alpha2)
+ fvc::div(phi, rho2) - fvc::Sp(fvc::div(phi), rho2); *(
(
fvc::ddt(alpha2, rho2) + fvc::div(alphaPhi2*rho2f)
- (fvOptions(alpha2, mixture.thermo2().rho())&rho2)
)/rho2
- fvc::ddt(alpha2) - fvc::div(alphaPhi2)
+ (alpha2*psi2/rho2)*correction(fvm::ddt(p_rgh))
);
} }
// Cache p_rgh prior to solve for density update // Cache p_rgh prior to solve for density update
@ -78,11 +94,7 @@
solve solve
( (
( p_rghEqnComp1() + p_rghEqnComp2() + p_rghEqnIncomp,
(max(alpha1, scalar(0))/rho1)*p_rghEqnComp1()
+ (max(alpha2, scalar(0))/rho2)*p_rghEqnComp2()
)
+ p_rghEqnIncomp,
mesh.solver(p_rgh.select(pimple.finalInnerIter())) mesh.solver(p_rgh.select(pimple.finalInnerIter()))
); );
@ -93,8 +105,8 @@
dgdt = dgdt =
( (
pos(alpha2)*(p_rghEqnComp2 & p_rgh)/rho2 alpha1*(p_rghEqnComp2 & p_rgh)
- pos(alpha1)*(p_rghEqnComp1 & p_rgh)/rho1 - alpha2*(p_rghEqnComp1 & p_rgh)
); );
phi = phiHbyA + p_rghEqnIncomp.flux(); phi = phiHbyA + p_rghEqnIncomp.flux();

View File

@ -105,9 +105,7 @@ int main(int argc, char *argv[])
while (pimple.loop()) while (pimple.loop())
{ {
#include "alphaControls.H" #include "alphaControls.H"
#include "alphaEqnSubCycle.H" #include "compressibleAlphaEqnSubCycle.H"
solve(fvm::ddt(rho) + fvc::div(rhoPhi));
#include "UEqn.H" #include "UEqn.H"
#include "TEqn.H" #include "TEqn.H"

View File

@ -89,7 +89,7 @@ surfaceScalarField rhoPhi
volScalarField dgdt volScalarField dgdt
( (
pos(alpha2)*fvc::div(phi)/max(alpha2, scalar(0.0001)) pos0(alpha2)*fvc::div(phi)/max(alpha2, scalar(0.0001))
); );
// Construct compressible turbulence model // Construct compressible turbulence model

View File

@ -53,13 +53,29 @@
} }
else else
{ {
#include "rhofs.H"
p_rghEqnComp1 = p_rghEqnComp1 =
fvc::ddt(rho1) + psi1*correction(fvm::ddt(p_rgh)) pos(alpha1)
+ fvc::div(phi, rho1) - fvc::Sp(fvc::div(phi), rho1); *(
(
fvc::ddt(alpha1, rho1) + fvc::div(alphaPhi1*rho1f)
- (fvOptions(alpha1, mixture.thermo1().rho())&rho1)
)/rho1
- fvc::ddt(alpha1) - fvc::div(alphaPhi1)
+ (alpha1*psi1/rho1)*correction(fvm::ddt(p_rgh))
);
p_rghEqnComp2 = p_rghEqnComp2 =
fvc::ddt(rho2) + psi2*correction(fvm::ddt(p_rgh)) pos(alpha2)
+ fvc::div(phi, rho2) - fvc::Sp(fvc::div(phi), rho2); *(
(
fvc::ddt(alpha2, rho2) + fvc::div(alphaPhi2*rho2f)
- (fvOptions(alpha2, mixture.thermo2().rho())&rho2)
)/rho2
- fvc::ddt(alpha2) - fvc::div(alphaPhi2)
+ (alpha2*psi2/rho2)*correction(fvm::ddt(p_rgh))
);
} }
// Cache p_rgh prior to solve for density update // Cache p_rgh prior to solve for density update
@ -75,11 +91,7 @@
solve solve
( (
( p_rghEqnComp1() + p_rghEqnComp2() + p_rghEqnIncomp,
(max(alpha1, scalar(0))/rho1)*p_rghEqnComp1()
+ (max(alpha2, scalar(0))/rho2)*p_rghEqnComp2()
)
+ p_rghEqnIncomp,
mesh.solver(p_rgh.select(pimple.finalInnerIter())) mesh.solver(p_rgh.select(pimple.finalInnerIter()))
); );
@ -90,8 +102,8 @@
dgdt = dgdt =
( (
pos(alpha2)*(p_rghEqnComp2 & p_rgh)/rho2 alpha1*(p_rghEqnComp2 & p_rgh)
- pos(alpha1)*(p_rghEqnComp1 & p_rgh)/rho1 - alpha2*(p_rghEqnComp1 & p_rgh)
); );
phi = phiHbyA + p_rghEqnIncomp.flux(); phi = phiHbyA + p_rghEqnIncomp.flux();

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2013-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2013-2017 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -951,7 +951,7 @@ Foam::multiphaseMixtureThermo::nearInterface() const
forAllConstIter(PtrDictionary<phaseModel>, phases_, phase) forAllConstIter(PtrDictionary<phaseModel>, phases_, phase)
{ {
tnearInt.ref() = tnearInt.ref() =
max(tnearInt(), pos(phase() - 0.01)*pos(0.99 - phase())); max(tnearInt(), pos0(phase() - 0.01)*pos0(0.99 - phase()));
} }
return tnearInt; return tnearInt;

View File

@ -104,7 +104,7 @@
) )
{ {
phase().dgdt() = phase().dgdt() =
pos(phase()) pos0(phase())
*(p_rghEqnComps[phasei] & p_rgh)/phase().thermo().rho(); *(p_rghEqnComps[phasei] & p_rgh)/phase().thermo().rho();
} }

View File

@ -129,7 +129,7 @@ int main(int argc, char *argv[])
// if the mesh topology changed // if the mesh topology changed
if (mesh.topoChanging()) if (mesh.topoChanging())
{ {
talphaPhiCorr0.clear(); talphaPhi1Corr0.clear();
} }
gh = (g & mesh.C()) - ghRef; gh = (g & mesh.C()) - ghRef;

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -433,7 +433,7 @@ const Foam::surfaceScalarField& Foam::fvMesh::phi() const
// Set zero current time // Set zero current time
// mesh motion fluxes if the time has been incremented // mesh motion fluxes if the time has been incremented
if (phiPtr_->timeIndex() != time().timeIndex()) if (!time().subCycling() && phiPtr_->timeIndex() != time().timeIndex())
{ {
(*phiPtr_) = dimensionedScalar("0", dimVolume/dimTime, 0.0); (*phiPtr_) = dimensionedScalar("0", dimVolume/dimTime, 0.0);
} }

View File

@ -31,8 +31,6 @@ divSchemes
div(phirb,alpha) Gauss linear; div(phirb,alpha) Gauss linear;
div(rhoPhi,U) Gauss vanLeerV; div(rhoPhi,U) Gauss vanLeerV;
div(phi,thermo:rho.water) Gauss linear;
div(phi,thermo:rho.air) Gauss linear;
div(rhoPhi,T) Gauss vanLeer; div(rhoPhi,T) Gauss vanLeer;
div(rhoPhi,K) Gauss linear; div(rhoPhi,K) Gauss linear;
div((phi+meshPhi),p) Gauss linear; div((phi+meshPhi),p) Gauss linear;

View File

@ -31,8 +31,6 @@ divSchemes
div(phirb,alpha) Gauss linear; div(phirb,alpha) Gauss linear;
div(rhoPhi,U) Gauss upwind; div(rhoPhi,U) Gauss upwind;
div(phi,thermo:rho.water) Gauss upwind;
div(phi,thermo:rho.air) Gauss upwind;
div(rhoPhi,T) Gauss upwind; div(rhoPhi,T) Gauss upwind;
div(rhoPhi,K) Gauss upwind; div(rhoPhi,K) Gauss upwind;
div(phi,p) Gauss upwind; div(phi,p) Gauss upwind;

View File

@ -31,8 +31,6 @@ divSchemes
div(phirb,alpha) Gauss linear; div(phirb,alpha) Gauss linear;
div(rhoPhi,U) Gauss upwind; div(rhoPhi,U) Gauss upwind;
div(phi,thermo:rho.water) Gauss upwind;
div(phi,thermo:rho.air) Gauss upwind;
div(rhoPhi,T) Gauss upwind; div(rhoPhi,T) Gauss upwind;
div(rhoPhi,K) Gauss upwind; div(rhoPhi,K) Gauss upwind;
div(phi,p) Gauss upwind; div(phi,p) Gauss upwind;