compressibleInterFoam: Completed LTS and semi-implicit MULES support

Now the interFoam and compressibleInterFoam families of solvers use the same
alphaEqn formulation and supporting all of the MULES options without
code-duplication.

The semi-implicit MULES support allows running with significantly larger
time-steps but this does reduce the interface sharpness.
This commit is contained in:
Henry Weller 2017-02-09 17:31:57 +00:00
parent 6fc2a3dc58
commit b167c95f19
37 changed files with 251 additions and 167 deletions

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -79,6 +79,8 @@
if (MULESCorr)
{
#include "alphaSuSp.H"
fvScalarMatrix alpha1Eqn
(
(
@ -92,6 +94,8 @@
phiCN,
upwind<scalar>(mesh, phiCN)
).fvmDiv(phiCN, alpha1)
==
Su + fvm::Sp(Sp + divU, alpha1)
);
alpha1Eqn.solve();
@ -124,6 +128,8 @@
for (int aCorr=0; aCorr<nAlphaCorr; aCorr++)
{
#include "alphaSuSp.H"
surfaceScalarField phir(phic*mixture.nHatf());
tmp<surfaceScalarField> talphaPhiUn
@ -154,7 +160,17 @@
tmp<surfaceScalarField> talphaPhiCorr(talphaPhiUn() - alphaPhi);
volScalarField alpha10("alpha10", alpha1);
MULES::correct(alpha1, talphaPhiUn(), talphaPhiCorr.ref(), 1, 0);
MULES::correct
(
geometricOneField(),
alpha1,
talphaPhiUn(),
talphaPhiCorr.ref(),
Sp,
(-Sp*alpha1)(),
1,
0
);
// Under-relax the correction for all but the 1st corrector
if (aCorr == 0)
@ -171,7 +187,17 @@
{
alphaPhi = talphaPhiUn;
MULES::explicitSolve(alpha1, phiCN, alphaPhi, 1, 0);
MULES::explicitSolve
(
geometricOneField(),
alpha1,
phiCN,
alphaPhi,
Sp,
(Su + divU*min(alpha1(), scalar(1)))(),
1,
0
);
}
alpha2 = 1.0 - alpha1;
@ -195,7 +221,8 @@
== fv::EulerDdtScheme<vector>::typeName
)
{
rhoPhi = alphaPhi*(rho1 - rho2) + phiCN*rho2;
#include "rhofs.H"
rhoPhi = alphaPhi*(rho1f - rho2f) + phiCN*rho2f;
}
else
{
@ -206,7 +233,8 @@
}
// Calculate the end-of-time-step mass flux
rhoPhi = alphaPhi*(rho1 - rho2) + phi*rho2;
#include "rhofs.H"
rhoPhi = alphaPhi*(rho1f - rho2f) + phi*rho2f;
}
Info<< "Phase-1 volume fraction = "

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -1,6 +1,6 @@
EXE_INC = \
-I. \
-I../interFoam \
-I../VoF \
-ItwoPhaseMixtureThermo \
-I$(LIB_SRC)/transportModels/compressible/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \

View File

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

View File

@ -1,5 +0,0 @@
const dictionary& alphaControls = mesh.solverDict(alpha1.name());
label nAlphaCorr(readLabel(alphaControls.lookup("nAlphaCorr")));
label nAlphaSubCycles(readLabel(alphaControls.lookup("nAlphaSubCycles")));

View File

@ -1,51 +0,0 @@
{
word alphaScheme("div(phi,alpha)");
word alpharScheme("div(phirb,alpha)");
surfaceScalarField phir(phic*mixture.nHatf());
for (int gCorr=0; gCorr<nAlphaCorr; gCorr++)
{
#include "alphaSuSp.H"
surfaceScalarField alphaPhi1
(
fvc::flux
(
phi,
alpha1,
alphaScheme
)
+ fvc::flux
(
-fvc::flux(-phir, alpha2, alpharScheme),
alpha1,
alpharScheme
)
);
MULES::explicitSolve
(
geometricOneField(),
alpha1,
phi,
alphaPhi1,
Sp,
Su,
1,
0
);
surfaceScalarField rho1f(fvc::interpolate(rho1));
surfaceScalarField rho2f(fvc::interpolate(rho2));
rhoPhi = alphaPhi1*(rho1f - rho2f) + phi*rho2f;
alpha2 = scalar(1) - alpha1;
}
Info<< "Liquid phase volume fraction = "
<< alpha1.weightedAverage(mesh.V()).value()
<< " Min(" << alpha1.name() << ") = " << min(alpha1).value()
<< " Min(" << alpha2.name() << ") = " << min(alpha2).value()
<< endl;
}

View File

@ -1,38 +0,0 @@
{
surfaceScalarField phic(mag(phi/mesh.magSf()));
phic = min(mixture.cAlpha()*phic, max(phic));
volScalarField divU(fvc::div(fvc::absolute(phi, U)));
if (nAlphaSubCycles > 1)
{
dimensionedScalar totalDeltaT = runTime.deltaT();
surfaceScalarField rhoPhiSum
(
IOobject
(
"rhoPhiSum",
runTime.timeName(),
mesh
),
mesh,
dimensionedScalar("0", rhoPhi.dimensions(), 0)
);
for
(
subCycle<volScalarField> alphaSubCycle(alpha1, nAlphaSubCycles);
!(++alphaSubCycle).end();
)
{
#include "alphaEqn.H"
rhoPhiSum += (runTime.deltaT()/totalDeltaT)*rhoPhi;
}
rhoPhi = rhoPhiSum;
}
else
{
#include "alphaEqn.H"
}
}

View File

@ -1,37 +1,43 @@
volScalarField::Internal Sp
(
IOobject
(
"Sp",
runTime.timeName(),
mesh
),
mesh,
dimensionedScalar("Sp", dgdt.dimensions(), 0.0)
);
volScalarField::Internal Sp
(
IOobject
(
"Sp",
runTime.timeName(),
mesh
),
mesh,
dimensionedScalar("Sp", dgdt.dimensions(), 0)
);
volScalarField::Internal Su
(
IOobject
(
"Su",
runTime.timeName(),
mesh
),
// Divergence term is handled explicitly to be
// consistent with the explicit transport solution
divU*min(alpha1, scalar(1))
);
volScalarField::Internal Su
(
IOobject
(
"Su",
runTime.timeName(),
mesh
),
mesh,
dimensionedScalar("Su", dgdt.dimensions(), 0)
);
forAll(dgdt, celli)
{
if (dgdt[celli] > 0.0 && alpha1[celli] > 0.0)
{
Sp[celli] -= dgdt[celli]*alpha1[celli];
Su[celli] += dgdt[celli]*alpha1[celli];
}
else if (dgdt[celli] < 0.0 && alpha1[celli] < 1.0)
{
Sp[celli] += dgdt[celli]*(1.0 - alpha1[celli]);
}
}
forAll(dgdt, celli)
{
if (dgdt[celli] > 0.0 && alpha1[celli] > 0.0)
{
Sp[celli] -= dgdt[celli]*alpha1[celli];
Su[celli] += dgdt[celli]*alpha1[celli];
}
else if (dgdt[celli] < 0.0 && alpha1[celli] < 1.0)
{
Sp[celli] += dgdt[celli]*(1.0 - alpha1[celli]);
}
}
volScalarField::Internal divU
(
mesh.moving()
? fvc::div(phiCN() + mesh.phi())
: fvc::div(phiCN())
);

View File

@ -0,0 +1,3 @@
{
#include "alphaEqnSubCycle.H"
}

View File

@ -1,6 +1,7 @@
EXE_INC = \
-I. \
-I.. \
-I../../interFoam \
-I../../VoF \
-I../twoPhaseMixtureThermo \
-I$(LIB_SRC)/transportModels/compressible/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \

View File

@ -39,7 +39,10 @@ Description
#include "fvCFD.H"
#include "dynamicFvMesh.H"
#include "MULES.H"
#include "CMULES.H"
#include "EulerDdtScheme.H"
#include "localEulerDdtScheme.H"
#include "CrankNicolsonDdtScheme.H"
#include "subCycle.H"
#include "twoPhaseMixture.H"
#include "twoPhaseMixtureThermo.H"
@ -47,7 +50,6 @@ Description
#include "pimpleControl.H"
#include "fvOptions.H"
#include "CorrectPhi.H"
#include "localEulerDdtScheme.H"
#include "fvcSmooth.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -141,7 +143,7 @@ int main(int argc, char *argv[])
}
#include "alphaControls.H"
#include "alphaEqnSubCycle.H"
#include "compressibleAlphaEqnSubCycle.H"
solve(fvm::ddt(rho) + fvc::div(rhoPhi));

View File

@ -8,6 +8,7 @@
fvc::flux(HbyA)
+ fvc::interpolate(rho*rAU)*fvc::ddtCorr(U, Uf)
);
MRF.makeRelative(phiHbyA);
surfaceScalarField phig
(
@ -20,7 +21,7 @@
phiHbyA += phig;
// Update the pressure BCs to ensure flux consistency
constrainPressure(p_rgh, U, phiHbyA, rAUf);
constrainPressure(p_rgh, U, phiHbyA, rAUf, MRF);
// Make the fluxes relative to the mesh motion
fvc::makeRelative(phiHbyA, U);

View File

@ -36,7 +36,10 @@ Description
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "MULES.H"
#include "CMULES.H"
#include "EulerDdtScheme.H"
#include "localEulerDdtScheme.H"
#include "CrankNicolsonDdtScheme.H"
#include "subCycle.H"
#include "rhoThermo.H"
#include "twoPhaseMixture.H"
@ -44,7 +47,6 @@ Description
#include "turbulentFluidThermoModel.H"
#include "pimpleControl.H"
#include "fvOptions.H"
#include "localEulerDdtScheme.H"
#include "fvcSmooth.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -63,6 +63,7 @@ dimensionedScalar pMin
);
mesh.setFluxRequired(p_rgh.name());
mesh.setFluxRequired(alpha1.name());
#include "readGravitationalAcceleration.H"
@ -99,3 +100,22 @@ autoPtr<compressible::turbulenceModel> turbulence
Info<< "Creating field kinetic energy K\n" << endl;
volScalarField K("K", 0.5*magSqr(U));
// MULES flux from previous time-step
surfaceScalarField alphaPhi
(
IOobject
(
"alphaPhi",
runTime.timeName(),
mesh,
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
),
phi*fvc::interpolate(alpha1)
);
// MULES Correction
tmp<surfaceScalarField> talphaPhiCorr0;
#include "createMRF.H"

View File

@ -8,6 +8,7 @@
fvc::flux(HbyA)
+ fvc::interpolate(rho*rAU)*fvc::ddtCorr(U, phi)
);
MRF.makeRelative(phiHbyA);
surfaceScalarField phig
(
@ -20,7 +21,7 @@
phiHbyA += phig;
// Update the pressure BCs to ensure flux consistency
constrainPressure(p_rgh, U, phiHbyA, rAUf);
constrainPressure(p_rgh, U, phiHbyA, rAUf, MRF);
tmp<fvScalarMatrix> p_rghEqnComp1;
tmp<fvScalarMatrix> p_rghEqnComp2;

View File

@ -0,0 +1,2 @@
surfaceScalarField rho1f(fvc::interpolate(rho1));
surfaceScalarField rho2f(fvc::interpolate(rho2));

View File

@ -1,5 +1,6 @@
EXE_INC = \
-I. \
-I../VoF \
-I../interFoam \
-ImultiphaseMixtureThermo/lnInclude \
-I$(LIB_SRC)/transportModels/compressible/lnInclude \

View File

@ -1,4 +1,5 @@
EXE_INC = \
-I../VoF \
-I$(LIB_SRC)/transportModels/twoPhaseMixture/lnInclude \
-I$(LIB_SRC)/transportModels \
-I$(LIB_SRC)/transportModels/incompressible/lnInclude \

View File

@ -0,0 +1,3 @@
zeroField Su;
zeroField Sp;
zeroField divU;

View File

@ -1,6 +1,7 @@
EXE_INC = \
-I. \
-I.. \
-I../../VoF \
-I$(LIB_SRC)/transportModels/twoPhaseMixture/lnInclude \
-I$(LIB_SRC)/transportModels \
-I$(LIB_SRC)/transportModels/incompressible/lnInclude \

View File

@ -28,7 +28,7 @@
phiHbyA += phig;
// Update the pressure BCs to ensure flux consistency
constrainPressure(p_rgh, U, phiHbyA, rAUf);
constrainPressure(p_rgh, U, phiHbyA, rAUf, MRF);
while (pimple.correctNonOrthogonal())
{

View File

@ -1,6 +1,7 @@
EXE_INC = \
-I. \
-I.. \
-I../../VoF \
-I$(LIB_SRC)/transportModels/twoPhaseMixture/lnInclude \
-IimmiscibleIncompressibleThreePhaseMixture \
-IincompressibleThreePhaseMixture \

View File

@ -0,0 +1,2 @@
const dimensionedScalar& rho1f(rho1);
const dimensionedScalar& rho2f(rho2);

View File

@ -1,5 +1,6 @@
EXE_INC = \
-I. \
-I../VoF \
-I../interFoam \
-ImultiphaseMixture/lnInclude \
-I$(LIB_SRC)/transportModels \

View File

@ -1,5 +1,6 @@
EXE_INC = \
-I.. \
-I../../VoF \
-I../../interFoam/interDyMFoam \
-I../../interFoam \
-I../multiphaseMixture/lnInclude \

View File

@ -1,6 +1,6 @@
EXE_INC = \
-I. \
-I../interFoam \
-I../VoF \
-I$(LIB_SRC)/transportModels/twoPhaseMixture/lnInclude \
-I$(LIB_SRC)/transportModels \
-I$(LIB_SRC)/transportModels/incompressible/lnInclude \

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -66,6 +66,10 @@ public:
inline scalar operator[](const label) const;
inline zeroField field() const;
inline zeroField operator()() const;
inline zeroField operator-() const;
};

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -39,4 +39,80 @@ inline Foam::zeroField Foam::zeroField::field() const
}
inline Foam::zeroField Foam::zeroField::operator()() const
{
return zeroField();
}
inline Foam::zeroField Foam::zeroField::operator-() const
{
return zeroField();
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
inline const zeroField operator+(const zeroField&, const zeroField&)
{
return zeroField();
}
template<class Type>
inline const Type& operator+(const Type& t, const zeroField&)
{
return t;
}
template<class Type>
inline const Type& operator+(const zeroField&, const Type& t)
{
return t;
}
inline const zeroField operator-(const zeroField&, const zeroField&)
{
return zeroField();
}
template<class Type>
inline const Type& operator-(const Type& t, const zeroField&)
{
return t;
}
template<class Type>
inline Type operator-(const zeroField&, const Type& t)
{
return -t;
}
template<class Type>
inline zeroField operator*(const Type& t, const zeroField&)
{
return zeroField();
}
template<class Type>
inline zeroField operator*(const zeroField&, const Type& t)
{
return zeroField();
}
template<class Type>
inline zeroField operator/(const zeroField&, const Type& t)
{
return zeroField();
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -72,6 +72,8 @@ public:
inline zeroField field() const;
inline zeroField operator()() const;
inline zeroField oldTime() const;
inline zeroFieldField boundaryField() const;
@ -84,7 +86,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "geometricZeroFieldI.H"
#include "geometricZeroFieldI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -42,6 +42,11 @@ inline Foam::zeroField Foam::geometricZeroField::field() const
return zeroField();
}
inline Foam::zeroField Foam::geometricZeroField::operator()() const
{
return zeroField();
}
inline Foam::zeroField Foam::geometricZeroField::oldTime() const
{
return zeroField();

View File

@ -29,15 +29,15 @@ deltaT 0.0001;
writeControl adjustableRunTime;
writeInterval 0.005;
writeInterval 0.01;
purgeWrite 0;
writeFormat ascii;
writeFormat binary;
writePrecision 8;
writeCompression compressed;
writeCompression off;
timeFormat general;
@ -47,10 +47,9 @@ runTimeModifiable yes;
adjustTimeStep yes;
maxCo 0.25;
maxCo 0.5;
maxAlphaCo 0.5;
maxDeltaT 1;
maxAlphaCo 1;
// ************************************************************************* //

View File

@ -17,11 +17,19 @@ FoamFile
solvers
{
alpha.water
"alpha.water.*"
{
nAlphaCorr 1;
nAlphaSubCycles 1;
nAlphaSubCycles 2;
cAlpha 1;
MULESCorr no;
nLimiterIter 5;
solver smoothSolver;
smoother symGaussSeidel;
tolerance 1e-8;
relTol 0;
}
".*(rho|rhoFinal)"

View File

@ -29,7 +29,7 @@ deltaT 0.0001;
writeControl adjustableRunTime;
writeInterval 0.005;
writeInterval 0.01;
purgeWrite 0;
@ -47,10 +47,9 @@ runTimeModifiable yes;
adjustTimeStep yes;
maxCo 0.25;
maxCo 0.5;
maxAlphaCo 0.5;
maxDeltaT 1;
maxAlphaCo 1;
// ************************************************************************* //

View File

@ -17,11 +17,19 @@ FoamFile
solvers
{
alpha.water
"alpha.water.*"
{
nAlphaCorr 1;
nAlphaSubCycles 1;
nAlphaSubCycles 2;
cAlpha 1;
MULESCorr no;
nLimiterIter 5;
solver smoothSolver;
smoother symGaussSeidel;
tolerance 1e-8;
relTol 0;
}
pcorr