Commit 425d51a9 authored by Henry's avatar Henry
Browse files

MMULES: new development of the MULES limiter to support limiting the sum of phase-fractions

multiphaseInterFoam: Upgraded to use the new MMULES algorithm
parent 9e02bcc0
......@@ -27,11 +27,13 @@ License
#include "alphaContactAngleFvPatchScalarField.H"
#include "Time.H"
#include "subCycle.H"
#include "fvCFD.H"
#include "MULES.H"
#include "fvcSnGrad.H"
#include "fvcFlux.H"
// * * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * //
const scalar Foam::multiphaseMixture::convertToRad =
const Foam::scalar Foam::multiphaseMixture::convertToRad =
Foam::constant::mathematical::pi/180.0;
......@@ -249,10 +251,6 @@ void Foam::multiphaseMixture::solve()
label nAlphaSubCycles(readLabel(pimpleDict.lookup("nAlphaSubCycles")));
label nAlphaCorr(readLabel(pimpleDict.lookup("nAlphaCorr")));
bool cycleAlpha(Switch(pimpleDict.lookup("cycleAlpha")));
scalar cAlpha(readScalar(pimpleDict.lookup("cAlpha")));
......@@ -269,7 +267,7 @@ void Foam::multiphaseMixture::solve()
!(++alphaSubCycle).end();
)
{
solveAlphas(nAlphaCorr, cycleAlpha, cAlpha);
solveAlphas(cAlpha);
rhoPhiSum += (runTime.deltaT()/totalDeltaT)*rhoPhi_;
}
......@@ -277,7 +275,7 @@ void Foam::multiphaseMixture::solve()
}
else
{
solveAlphas(nAlphaCorr, cycleAlpha, cAlpha);
solveAlphas(cAlpha);
}
}
......@@ -481,8 +479,6 @@ Foam::multiphaseMixture::nearInterface() const
void Foam::multiphaseMixture::solveAlphas
(
const label nAlphaCorr,
const bool cycleAlpha,
const scalar cAlpha
)
{
......@@ -490,92 +486,108 @@ void Foam::multiphaseMixture::solveAlphas
nSolves++;
word alphaScheme("div(phi,alpha)");
word alphacScheme("div(phirb,alpha)");
tmp<fv::convectionScheme<scalar> > mvConvection
(
fv::convectionScheme<scalar>::New
(
mesh_,
alphaTable_,
phi_,
mesh_.divScheme(alphaScheme)
)
);
word alpharScheme("div(phirb,alpha)");
surfaceScalarField phic(mag(phi_/mesh_.magSf()));
phic = min(cAlpha*phic, max(phic));
for (int gCorr=0; gCorr<nAlphaCorr; gCorr++)
{
phase* refPhasePtr = &refPhase_;
if (cycleAlpha)
{
PtrDictionary<phase>::iterator refPhaseIter = phases_.begin();
for (label i=0; i<nSolves%phases_.size(); i++)
{
++refPhaseIter;
}
refPhasePtr = &refPhaseIter();
}
PtrList<surfaceScalarField> phiAlphaCorrs(phases_.size());
int phasei = 0;
phase& refPhase = *refPhasePtr;
forAllIter(PtrDictionary<phase>, phases_, iter)
{
phase& alpha = iter();
volScalarField refPhaseNew(refPhase);
refPhaseNew == 1.0;
phiAlphaCorrs.set
(
phasei,
new surfaceScalarField
(
fvc::flux
(
phi_,
alpha,
alphaScheme
)
)
);
rhoPhi_ = phi_*refPhase.rho();
surfaceScalarField& phiAlphaCorr = phiAlphaCorrs[phasei];
forAllIter(PtrDictionary<phase>, phases_, iter)
forAllIter(PtrDictionary<phase>, phases_, iter2)
{
phase& alpha = iter();
phase& alpha2 = iter2();
if (&alpha2 == &alpha) continue;
if (&alpha == &refPhase) continue;
surfaceScalarField phir(phic*nHatf(alpha, alpha2));
fvScalarMatrix alphaEqn
phiAlphaCorr += fvc::flux
(
fvm::ddt(alpha)
+ mvConvection->fvmDiv(phi_, alpha)
-fvc::flux(-phir, alpha2, alpharScheme),
alpha,
alpharScheme
);
}
forAllIter(PtrDictionary<phase>, phases_, iter2)
{
phase& alpha2 = iter2();
if (&alpha2 == &alpha) continue;
surfaceScalarField phir(phic*nHatf(alpha, alpha2));
surfaceScalarField phirb12
(
-fvc::flux(-phir, alpha2, alphacScheme)
);
MULES::limit
(
geometricOneField(),
alpha,
phi_,
phiAlphaCorr,
zeroField(),
zeroField(),
1,
0,
3,
true
);
phasei++;
}
alphaEqn += fvm::div(phirb12, alpha, alphacScheme);
}
MULES::limitSum(phiAlphaCorrs);
alphaEqn.solve(mesh_.solver("alpha"));
rhoPhi_ = 0.0*phi_*refPhase_.rho();
volScalarField sumAlpha("sumAlpha", 0.0*refPhase_);
phasei = 0;
rhoPhi_ += alphaEqn.flux()*(alpha.rho() - refPhase.rho());
forAllIter(PtrDictionary<phase>, phases_, iter)
{
phase& alpha = iter();
Info<< alpha.name() << " volume fraction, min, max = "
<< alpha.weightedAverage(mesh_.V()).value()
<< ' ' << min(alpha).value()
<< ' ' << max(alpha).value()
<< endl;
surfaceScalarField& phiAlpha = phiAlphaCorrs[phasei];
phiAlpha += upwind<scalar>(mesh_, phi_).flux(alpha);
refPhaseNew == refPhaseNew - alpha;
}
MULES::explicitSolve
(
geometricOneField(),
alpha,
phiAlpha,
zeroField(),
zeroField()
);
rhoPhi_ += phiAlpha*alpha.rho();
Info<< alpha.name() << " volume fraction, min, max = "
<< alpha.weightedAverage(mesh_.V()).value()
<< ' ' << min(alpha).value()
<< ' ' << max(alpha).value()
<< endl;
refPhase == refPhaseNew;
sumAlpha += alpha;
Info<< refPhase.name() << " volume fraction, min, max = "
<< refPhase.weightedAverage(mesh_.V()).value()
<< ' ' << min(refPhase).value()
<< ' ' << max(refPhase).value()
<< endl;
phasei++;
}
Info<< "Phase-sum volume fraction, min, max = "
<< sumAlpha.weightedAverage(mesh_.V()).value()
<< ' ' << min(sumAlpha).value()
<< ' ' << max(sumAlpha).value()
<< endl;
calcAlphas();
}
......
......@@ -168,12 +168,7 @@ private:
void calcAlphas();
void solveAlphas
(
const label nAlphaCorr,
const bool cycleAlpha,
const scalar cAlpha
);
void solveAlphas(const scalar cAlpha);
tmp<surfaceVectorField> nHatfv
(
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2006-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -80,4 +80,60 @@ void Foam::MULES::implicitSolve
}
void Foam::MULES::limitSum(UPtrList<scalarField>& phiPsiCorrs)
{
forAll(phiPsiCorrs[0], facei)
{
scalar sumPos = 0;
scalar sumNeg = 0;
for (int phasei=0; phasei<phiPsiCorrs.size(); phasei++)
{
if (phiPsiCorrs[phasei][facei] > 0)
{
sumPos += phiPsiCorrs[phasei][facei];
}
else
{
sumNeg += phiPsiCorrs[phasei][facei];
}
}
scalar sum = sumPos + sumNeg;
if (sum > 0 && sumPos > VSMALL)
{
scalar lambda = -sumNeg/sumPos;
for (int phasei=0; phasei<phiPsiCorrs.size(); phasei++)
{
if (phiPsiCorrs[phasei][facei] > 0)
{
phiPsiCorrs[phasei][facei] *= lambda;
}
}
}
else if (sum < 0 && sumNeg < -VSMALL)
{
scalar lambda = -sumPos/sumNeg;
for (int phasei=0; phasei<phiPsiCorrs.size(); phasei++)
{
if (phiPsiCorrs[phasei][facei] < 0)
{
phiPsiCorrs[phasei][facei] *= lambda;
}
}
}
else
{
for (int phasei=0; phasei<phiPsiCorrs.size(); phasei++)
{
phiPsiCorrs[phasei][facei] = 0;
}
}
}
}
// ************************************************************************* //
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2006-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -45,18 +45,27 @@ SourceFiles
#include "volFields.H"
#include "surfaceFieldsFwd.H"
#include "primitiveFieldsFwd.H"
#include "zero.H"
#include "geometricOneField.H"
#include "zero.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace MULES
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace MULES
{
template<class RhoType, class SpType, class SuType>
void explicitSolve
(
const RhoType& rho,
volScalarField& psi,
const surfaceScalarField& phiPsi,
const SpType& Sp,
const SuType& Su
);
template<class RhoType, class SpType, class SuType>
void explicitSolve
......@@ -117,10 +126,29 @@ void limiter
const label nLimiterIter
);
} // End namespace MULES
template<class RhoType, class SpType, class SuType>
void limit
(
const RhoType& rho,
const volScalarField& psi,
const surfaceScalarField& phi,
surfaceScalarField& phiPsi,
const SpType& Sp,
const SuType& Su,
const scalar psiMax,
const scalar psiMin,
const label nLimiterIter,
const bool returnCorr
);
void limitSum(UPtrList<scalarField>& phiPsiCorrs);
template<class SurfaceScalarFieldList>
void limitSum(SurfaceScalarFieldList& phiPsiCorrs);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace MULES
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2006-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -43,58 +43,14 @@ void Foam::MULES::explicitSolve
(
const RhoType& rho,
volScalarField& psi,
const surfaceScalarField& phi,
surfaceScalarField& phiPsi,
const surfaceScalarField& phiPsi,
const SpType& Sp,
const SuType& Su,
const scalar psiMax,
const scalar psiMin
const SuType& Su
)
{
Info<< "MULES: Solving for " << psi.name() << endl;
const fvMesh& mesh = psi.mesh();
psi.correctBoundaryConditions();
surfaceScalarField phiBD(upwind<scalar>(psi.mesh(), phi).flux(psi));
surfaceScalarField& phiCorr = phiPsi;
phiCorr -= phiBD;
scalarField allLambda(mesh.nFaces(), 1.0);
slicedSurfaceScalarField lambda
(
IOobject
(
"lambda",
mesh.time().timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
mesh,
dimless,
allLambda,
false // Use slices for the couples
);
limiter
(
allLambda,
rho,
psi,
phiBD,
phiCorr,
Sp,
Su,
psiMax,
psiMin,
3
);
phiPsi = phiBD + lambda*phiCorr;
scalarField& psiIf = psi;
const scalarField& psi0 = psi.oldTime();
......@@ -127,6 +83,25 @@ void Foam::MULES::explicitSolve
}
template<class RhoType, class SpType, class SuType>
void Foam::MULES::explicitSolve
(
const RhoType& rho,
volScalarField& psi,
const surfaceScalarField& phi,
surfaceScalarField& phiPsi,
const SpType& Sp,
const SuType& Su,
const scalar psiMax,
const scalar psiMin
)
{
psi.correctBoundaryConditions();
limit(rho, psi, phi, phiPsi, Sp, Su, psiMax, psiMin, 3, false);
explicitSolve(rho, psi, phiPsi, Sp, Su);
}
template<class RhoType, class SpType, class SuType>
void Foam::MULES::implicitSolve
(
......@@ -614,4 +589,100 @@ void Foam::MULES::limiter
}
template<class RhoType, class SpType, class SuType>
void Foam::MULES::limit
(
const RhoType& rho,
const volScalarField& psi,
const surfaceScalarField& phi,
surfaceScalarField& phiPsi,
const SpType& Sp,
const SuType& Su,
const scalar psiMax,
const scalar psiMin,
const label nLimiterIter,
const bool returnCorr
)
{
const fvMesh& mesh = psi.mesh();
surfaceScalarField phiBD(upwind<scalar>(psi.mesh(), phi).flux(psi));
surfaceScalarField& phiCorr = phiPsi;
phiCorr -= phiBD;
scalarField allLambda(mesh.nFaces(), 1.0);
slicedSurfaceScalarField lambda
(
IOobject
(
"lambda",
mesh.time().timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
mesh,
dimless,
allLambda,
false // Use slices for the couples
);
limiter
(
allLambda,
rho,
psi,
phiBD,
phiCorr,
Sp,
Su,
psiMax,
psiMin,
nLimiterIter
);
if (returnCorr)
{
phiCorr *= lambda;
}
else
{
phiPsi = phiBD + lambda*phiCorr;
}
}
template<class SurfaceScalarFieldList>
void Foam::MULES::limitSum(SurfaceScalarFieldList& phiPsiCorrs)
{
{
UPtrList<scalarField> phiPsiCorrsInternal(phiPsiCorrs.size());
forAll(phiPsiCorrs, phasei)
{
phiPsiCorrsInternal.set(phasei, &phiPsiCorrs[phasei]);
}
limitSum(phiPsiCorrsInternal);
}
forAll(phiPsiCorrs[0].boundaryField(), patchi)
{
UPtrList<scalarField> phiPsiCorrsPatch(phiPsiCorrs.size());
forAll(phiPsiCorrs, phasei)
{
phiPsiCorrsPatch.set
(
phasei,
&phiPsiCorrs[phasei].boundaryField()[patchi]
);
}
limitSum(phiPsiCorrsPatch);
}
}
// ************************************************************************* //
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volVectorField;
location "0";
object U;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //