mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
INT: Org integration of VOF, Euler phase solvers and models.
Integration of VOF MULES new interfaces. Update of VOF solvers and all instances of MULES in the code. Integration of reactingTwoPhaseEuler and reactingMultiphaseEuler solvers and sub-models Updating reactingEuler tutorials accordingly (most of them tested) New eRefConst thermo used in tutorials. Some modifications at thermo specie level affecting mostly eThermo. hThermo mostly unaffected New chtMultiRegionTwoPhaseEulerFoam solver for quenching and tutorial. Phases sub-models for reactingTwoPhaseEuler and reactingMultiphaseEuler were moved to src/phaseSystemModels/reactingEulerFoam in order to be used by BC for chtMultiRegionTwoPhaseEulerFoam. Update of interCondensatingEvaporatingFoam solver.
This commit is contained in:
committed by
Andrew Heather
parent
0628bfb017
commit
8170f2ad92
@ -0,0 +1,5 @@
|
||||
derivedFvPatchFields/turbulentTemperatureTwoPhaseRadCoupledMixed/turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField.C
|
||||
../solid/solidRegionDiffNo.C
|
||||
chtMultiRegionTwoPhaseEulerFoam.C
|
||||
|
||||
EXE = $(FOAM_APPBIN)/chtMultiRegionTwoPhaseEulerFoam
|
||||
@ -0,0 +1,41 @@
|
||||
EXE_INC = \
|
||||
-I. \
|
||||
-I.. \
|
||||
-I$(FOAM_SOLVERS)/multiphase/reactingEulerFoam/reactingTwoPhaseEulerFoam \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/reactingTwoPhaseEulerFoam/twoPhaseSystem/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/reactingTwoPhaseEulerFoam/twoPhaseCompressibleTurbulenceModels/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/phaseSystems/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/interfacialModels/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/interfacialCompositionModels/lnInclude \
|
||||
-I./fluid \
|
||||
-I../solid \
|
||||
-I../fluid \
|
||||
-I../include \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/sampling/lnInclude \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/transportModels/compressible/lnInclude \
|
||||
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
|
||||
-I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \
|
||||
-I$(LIB_SRC)/thermophysicalModels/solidThermo/lnInclude \
|
||||
-I$(LIB_SRC)/thermophysicalModels/radiation/lnInclude \
|
||||
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
|
||||
-I$(LIB_SRC)/TurbulenceModels/compressible/lnInclude \
|
||||
-I$(LIB_SRC)/TurbulenceModels/phaseCompressible/lnInclude \
|
||||
-I$(LIB_SRC)/regionModels/regionModel/lnInclude
|
||||
|
||||
|
||||
EXE_LIBS = \
|
||||
-lcompressibleTransportModels \
|
||||
-lfluidThermophysicalModels \
|
||||
-lspecie \
|
||||
-lsolidThermo \
|
||||
-ltwoPhaseReactingTurbulenceModels \
|
||||
-lmeshTools \
|
||||
-lfiniteVolume \
|
||||
-lfvOptions \
|
||||
-lradiationModels \
|
||||
-lregionModels \
|
||||
-lsampling \
|
||||
-lreactingTwoPhaseSystem \
|
||||
|
||||
@ -0,0 +1,166 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Application
|
||||
chtMultiRegionTwoPhaseEulerFoam
|
||||
|
||||
Group
|
||||
grpHeatTransferSolvers
|
||||
|
||||
Description
|
||||
Transient solver for buoyant, turbulent fluid flow and solid heat
|
||||
conduction with conjugate heat transfer between solid and fluid regions.
|
||||
|
||||
It solves a two-phase Euler approach on the fluid region.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fvCFD.H"
|
||||
#include "turbulentFluidThermoModel.H"
|
||||
|
||||
#include "twoPhaseSystem.H"
|
||||
#include "phaseCompressibleTurbulenceModel.H"
|
||||
#include "pimpleControl.H"
|
||||
#include "fixedGradientFvPatchFields.H"
|
||||
#include "regionProperties.H"
|
||||
#include "solidRegionDiffNo.H"
|
||||
#include "solidThermo.H"
|
||||
#include "radiationModel.H"
|
||||
#include "fvOptions.H"
|
||||
#include "coordinateSystem.H"
|
||||
#include "loopControl.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::addNote
|
||||
(
|
||||
"Transient solver for buoyant, turbulent two phase fluid flow and"
|
||||
"solid heat conduction with conjugate heat transfer "
|
||||
"between solid and fluid regions."
|
||||
);
|
||||
|
||||
#define NO_CONTROL
|
||||
#define CREATE_MESH createMeshesPostProcess.H
|
||||
#include "postProcess.H"
|
||||
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
#include "createMeshes.H"
|
||||
#include "createFields.H"
|
||||
#include "initContinuityErrs.H"
|
||||
#include "createTimeControls.H"
|
||||
#include "readSolidTimeControls.H"
|
||||
#include "compressibleMultiRegionCourantNo.H"
|
||||
#include "solidRegionDiffusionNo.H"
|
||||
#include "setInitialMultiRegionDeltaT.H"
|
||||
|
||||
while (runTime.run())
|
||||
{
|
||||
#include "readTimeControls.H"
|
||||
#include "readSolidTimeControls.H"
|
||||
#include "readPIMPLEControls.H"
|
||||
|
||||
#include "compressibleMultiRegionCourantNo.H"
|
||||
#include "solidRegionDiffusionNo.H"
|
||||
#include "setMultiRegionDeltaT.H"
|
||||
|
||||
++runTime;
|
||||
|
||||
Info<< "Time = " << runTime.timeName() << nl << endl;
|
||||
|
||||
if (nOuterCorr != 1)
|
||||
{
|
||||
forAll(fluidRegions, i)
|
||||
{
|
||||
#include "storeOldFluidFields.H"
|
||||
}
|
||||
}
|
||||
|
||||
// --- PIMPLE loop
|
||||
for (int oCorr=0; oCorr<nOuterCorr; ++oCorr)
|
||||
{
|
||||
const bool finalIter = (oCorr == nOuterCorr-1);
|
||||
|
||||
forAll(fluidRegions, i)
|
||||
{
|
||||
Info<< "\nSolving for fluid region "
|
||||
<< fluidRegions[i].name() << endl;
|
||||
#include "setRegionFluidFields.H"
|
||||
#include "readFluidMultiRegionPIMPLEControls.H"
|
||||
#include "solveFluid.H"
|
||||
}
|
||||
|
||||
forAll(solidRegions, i)
|
||||
{
|
||||
Info<< "\nSolving for solid region "
|
||||
<< solidRegions[i].name() << endl;
|
||||
#include "setRegionSolidFields.H"
|
||||
#include "readSolidMultiRegionPIMPLEControls.H"
|
||||
#include "solveSolid.H"
|
||||
}
|
||||
|
||||
// Additional loops for energy solution only
|
||||
if (!oCorr && nOuterCorr > 1)
|
||||
{
|
||||
loopControl looping(runTime, pimple, "energyCoupling");
|
||||
|
||||
while (looping.loop())
|
||||
{
|
||||
Info<< nl << looping << nl;
|
||||
|
||||
forAll(fluidRegions, i)
|
||||
{
|
||||
Info<< "\nSolving for fluid region "
|
||||
<< fluidRegions[i].name() << endl;
|
||||
#include "setRegionFluidFields.H"
|
||||
#include "readFluidMultiRegionPIMPLEControls.H"
|
||||
frozenFlow = true;
|
||||
#include "solveFluid.H"
|
||||
}
|
||||
|
||||
forAll(solidRegions, i)
|
||||
{
|
||||
Info<< "\nSolving for solid region "
|
||||
<< solidRegions[i].name() << endl;
|
||||
#include "setRegionSolidFields.H"
|
||||
#include "readSolidMultiRegionPIMPLEControls.H"
|
||||
#include "solveSolid.H"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runTime.write();
|
||||
|
||||
runTime.printExecutionTime(Info);
|
||||
}
|
||||
|
||||
Info<< "End\n" << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,516 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "fvPatchFieldMapper.H"
|
||||
#include "volFields.H"
|
||||
#include "phaseSystem.H"
|
||||
#include "mappedPatchBase.H"
|
||||
#include "solidThermo.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
const Foam::Enum
|
||||
<
|
||||
Foam::compressible::
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::regionType
|
||||
>
|
||||
Foam::compressible::
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::regionTypeNames_
|
||||
{
|
||||
{ regionType::solid, "solid" },
|
||||
{ regionType::fluid, "fluid" },
|
||||
};
|
||||
|
||||
|
||||
const Foam::Enum
|
||||
<
|
||||
Foam::compressible::
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::KMethodType
|
||||
>
|
||||
Foam::compressible::
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::KMethodTypeNames_
|
||||
{
|
||||
{ KMethodType::mtSolidThermo, "solidThermo" },
|
||||
{ KMethodType::mtLookup, "lookup" },
|
||||
{ KMethodType::mtPhaseSystem, "phaseSystem" }
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
|
||||
Foam::tmp<Foam::scalarField> Foam::compressible::
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::
|
||||
kappa
|
||||
(
|
||||
const scalarField& Tp
|
||||
) const
|
||||
{
|
||||
const polyMesh& mesh = patch().boundaryMesh().mesh();
|
||||
const label patchi = patch().index();
|
||||
|
||||
switch (method_)
|
||||
{
|
||||
case mtSolidThermo:
|
||||
{
|
||||
const solidThermo& thermo =
|
||||
mesh.lookupObject<solidThermo>(basicThermo::dictName);
|
||||
|
||||
return thermo.kappa(patchi);
|
||||
break;
|
||||
}
|
||||
|
||||
case mtLookup:
|
||||
{
|
||||
if (mesh.foundObject<volScalarField>(kappaName_))
|
||||
{
|
||||
return patch().lookupPatchField<volScalarField, scalar>
|
||||
(
|
||||
kappaName_
|
||||
);
|
||||
}
|
||||
else if (mesh.foundObject<volSymmTensorField>(kappaName_))
|
||||
{
|
||||
const symmTensorField& KWall =
|
||||
patch().lookupPatchField<volSymmTensorField, scalar>
|
||||
(
|
||||
kappaName_
|
||||
);
|
||||
|
||||
const vectorField n(patch().nf());
|
||||
|
||||
return n & KWall & n;
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Did not find field " << kappaName_
|
||||
<< " on mesh " << mesh.name() << " patch " << patch().name()
|
||||
<< nl
|
||||
<< " Please set 'kappa' to the name of a volScalarField"
|
||||
<< " or volSymmTensorField."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case mtPhaseSystem:
|
||||
{
|
||||
// Lookup the fluid model
|
||||
const phaseSystem& fluid =
|
||||
(
|
||||
mesh.lookupObject<phaseSystem>("phaseProperties")
|
||||
);
|
||||
|
||||
tmp<scalarField> kappaEff
|
||||
(
|
||||
new scalarField(patch().size(), 0.0)
|
||||
);
|
||||
|
||||
forAll(fluid.phases(), phasei)
|
||||
{
|
||||
const phaseModel& phase = fluid.phases()[phasei];
|
||||
|
||||
const fvPatchScalarField& alpha = phase.boundaryField()[patchi];
|
||||
|
||||
kappaEff.ref() += alpha*phase.kappaEff(patchi)();
|
||||
}
|
||||
|
||||
return kappaEff;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Unimplemented method " << KMethodTypeNames_[method_] << nl
|
||||
<< "Please set 'kappaMethod' to one of "
|
||||
<< flatOutput(KMethodTypeNames_.sortedToc()) << nl
|
||||
<< "and 'kappa' to the name of the volScalar"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
return scalarField(0);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace compressible
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
(
|
||||
const fvPatch& p,
|
||||
const DimensionedField<scalar, volMesh>& iF
|
||||
)
|
||||
:
|
||||
mixedFvPatchScalarField(p, iF),
|
||||
regionType_(fluid),
|
||||
method_(mtLookup),
|
||||
kappaName_("none"),
|
||||
otherPhaseName_("vapor"),
|
||||
TnbrName_("undefined-Tnbr"),
|
||||
qrNbrName_("undefined-qrNbr"),
|
||||
qrName_("undefined-qr")
|
||||
{
|
||||
this->refValue() = 0.0;
|
||||
this->refGrad() = 0.0;
|
||||
this->valueFraction() = 1.0;
|
||||
}
|
||||
|
||||
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
(
|
||||
const turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField& psf,
|
||||
const fvPatch& p,
|
||||
const DimensionedField<scalar, volMesh>& iF,
|
||||
const fvPatchFieldMapper& mapper
|
||||
)
|
||||
:
|
||||
mixedFvPatchScalarField(psf, p, iF, mapper),
|
||||
regionType_(psf.regionType_),
|
||||
method_(psf.method_),
|
||||
kappaName_(psf.kappaName_),
|
||||
otherPhaseName_(psf.otherPhaseName_),
|
||||
TnbrName_(psf.TnbrName_),
|
||||
qrNbrName_(psf.qrNbrName_),
|
||||
qrName_(psf.qrName_)
|
||||
{}
|
||||
|
||||
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
(
|
||||
const fvPatch& p,
|
||||
const DimensionedField<scalar, volMesh>& iF,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
mixedFvPatchScalarField(p, iF),
|
||||
regionType_(regionTypeNames_.read(dict.lookup("region"))),
|
||||
method_(KMethodTypeNames_.get("kappaMethod", dict)),
|
||||
kappaName_(dict.lookupOrDefault<word>("kappa", "none")),
|
||||
otherPhaseName_(dict.lookup("otherPhase")),
|
||||
TnbrName_(dict.lookupOrDefault<word>("Tnbr", "T")),
|
||||
qrNbrName_(dict.lookupOrDefault<word>("qrNbr", "none")),
|
||||
qrName_(dict.lookupOrDefault<word>("qr", "none"))
|
||||
{
|
||||
if (!isA<mappedPatchBase>(this->patch().patch()))
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "' not type '" << mappedPatchBase::typeName << "'"
|
||||
<< "\n for patch " << p.name()
|
||||
<< " of field " << internalField().name()
|
||||
<< " in file " << internalField().objectPath()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
fvPatchScalarField::operator=(scalarField("value", dict, p.size()));
|
||||
|
||||
if (dict.found("refValue"))
|
||||
{
|
||||
// Full restart
|
||||
refValue() = scalarField("refValue", dict, p.size());
|
||||
refGrad() = scalarField("refGradient", dict, p.size());
|
||||
valueFraction() = scalarField("valueFraction", dict, p.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Start from user entered data. Assume fixedValue.
|
||||
refValue() = *this;
|
||||
refGrad() = 0.0;
|
||||
valueFraction() = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
(
|
||||
const turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField& psf,
|
||||
const DimensionedField<scalar, volMesh>& iF
|
||||
)
|
||||
:
|
||||
mixedFvPatchScalarField(psf, iF),
|
||||
regionType_(psf.regionType_),
|
||||
method_(psf.method_),
|
||||
kappaName_(psf.kappaName_),
|
||||
otherPhaseName_(psf.otherPhaseName_),
|
||||
TnbrName_(psf.TnbrName_),
|
||||
qrNbrName_(psf.qrNbrName_),
|
||||
qrName_(psf.qrName_)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::
|
||||
updateCoeffs()
|
||||
{
|
||||
if (updated())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const polyMesh& mesh = patch().boundaryMesh().mesh();
|
||||
|
||||
// Since we're inside initEvaluate/evaluate there might be processor
|
||||
// comms underway. Change the tag we use.
|
||||
int oldTag = UPstream::msgType();
|
||||
UPstream::msgType() = oldTag+1;
|
||||
|
||||
// Get the coupling information from the mappedPatchBase
|
||||
const label patchi = patch().index();
|
||||
const mappedPatchBase& mpp =
|
||||
refCast<const mappedPatchBase>(patch().patch());
|
||||
const polyMesh& nbrMesh = mpp.sampleMesh();
|
||||
const label samplePatchi = mpp.samplePolyPatch().index();
|
||||
const fvPatch& nbrPatch =
|
||||
refCast<const fvMesh>(nbrMesh).boundary()[samplePatchi];
|
||||
|
||||
scalarField& Tp = *this;
|
||||
|
||||
const turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField&
|
||||
nbrField = refCast
|
||||
<const turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField>
|
||||
(
|
||||
nbrPatch.lookupPatchField<volScalarField, scalar>(TnbrName_)
|
||||
);
|
||||
|
||||
// Swap to obtain full local values of neighbour internal field
|
||||
scalarField TcNbr(nbrField.patchInternalField());
|
||||
mpp.distribute(TcNbr);
|
||||
|
||||
|
||||
// Swap to obtain full local values of neighbour K*delta
|
||||
scalarField KDeltaNbr;
|
||||
KDeltaNbr = nbrField.kappa(nbrField)*nbrPatch.deltaCoeffs();
|
||||
mpp.distribute(KDeltaNbr);
|
||||
|
||||
scalarField KDelta(kappa(Tp)*patch().deltaCoeffs());
|
||||
|
||||
scalarField qr(Tp.size(), 0.0);
|
||||
if (qrName_ != "none")
|
||||
{
|
||||
qr = patch().lookupPatchField<volScalarField, scalar>(qrName_);
|
||||
}
|
||||
|
||||
scalarField qrNbr(Tp.size(), 0.0);
|
||||
if (qrNbrName_ != "none")
|
||||
{
|
||||
qrNbr = nbrPatch.lookupPatchField<volScalarField, scalar>(qrNbrName_);
|
||||
mpp.distribute(qrNbr);
|
||||
}
|
||||
|
||||
|
||||
if (regionType_ == solid)
|
||||
{
|
||||
// Lookup the fluid model in the nbrFvMesh
|
||||
const phaseSystem& fluid =
|
||||
(
|
||||
nbrMesh.lookupObject<phaseSystem>("phaseProperties")
|
||||
);
|
||||
|
||||
// The BC is applied to the liquid phase of the fluid
|
||||
const phaseModel& liquid
|
||||
(
|
||||
fluid.phases()[nbrField.internalField().group()]
|
||||
);
|
||||
|
||||
const phaseModel& vapor(fluid.phases()[otherPhaseName_]);
|
||||
|
||||
|
||||
scalarField KDeltaLiqNbr;
|
||||
const fvPatchScalarField& alphal = liquid.boundaryField()[samplePatchi];
|
||||
KDeltaLiqNbr =
|
||||
alphal*(liquid.kappaEff(samplePatchi))*nbrPatch.deltaCoeffs();
|
||||
mpp.distribute(KDeltaLiqNbr);
|
||||
|
||||
scalarField KDeltaVapNbr;
|
||||
const fvPatchScalarField& alphav = vapor.boundaryField()[samplePatchi];
|
||||
KDeltaVapNbr =
|
||||
alphav*(vapor.kappaEff(samplePatchi))*nbrPatch.deltaCoeffs();
|
||||
mpp.distribute(KDeltaVapNbr);
|
||||
|
||||
scalarField TvNbr;
|
||||
const fvPatchScalarField& Tv =
|
||||
vapor.thermo().T().boundaryField()[samplePatchi];
|
||||
TvNbr = Tv.patchInternalField();
|
||||
mpp.distribute(TvNbr);
|
||||
|
||||
// TcNbr: liquid Tp
|
||||
// TvNbr: vapour Tp
|
||||
scalarField c(TcNbr*KDeltaLiqNbr + TvNbr*KDeltaVapNbr);
|
||||
|
||||
valueFraction() = KDeltaNbr/(KDeltaNbr + KDelta);
|
||||
refValue() = c/KDeltaNbr;
|
||||
refGrad() = (qr + qrNbr)/kappa(Tp);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
scalar Q = gSum(kappa(Tp)*patch().magSf()*snGrad());
|
||||
|
||||
Info<< "T solid : " << nl << endl;
|
||||
|
||||
Info
|
||||
<< " heat transfer rate from solid:" << Q
|
||||
<< " walltemperature "
|
||||
<< " min:" << gMin(Tp)
|
||||
<< " max:" << gMax(Tp)
|
||||
<< " avg:" << gAverage(Tp)
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
else if (regionType_ == fluid)
|
||||
{
|
||||
const phaseSystem& fluid =
|
||||
(
|
||||
mesh.lookupObject<phaseSystem>("phaseProperties")
|
||||
);
|
||||
|
||||
const phaseModel& liquid
|
||||
(
|
||||
fluid.phases()[internalField().group()]
|
||||
);
|
||||
|
||||
const phaseModel& vapor(fluid.phases()[otherPhaseName_]);
|
||||
|
||||
const fvPatchScalarField& Tv =
|
||||
vapor.thermo().T().boundaryField()[patchi];
|
||||
|
||||
const fvPatchScalarField& alphav = vapor.boundaryField()[patchi];
|
||||
|
||||
const scalarField KdeltaVap
|
||||
(
|
||||
alphav*(vapor.kappaEff(patchi))*patch().deltaCoeffs()
|
||||
);
|
||||
|
||||
const fvPatchScalarField& alphal = liquid.boundaryField()[patchi];
|
||||
|
||||
const scalarField KdeltaLiq
|
||||
(
|
||||
alphal*(liquid.kappaEff(patchi))*patch().deltaCoeffs()
|
||||
);
|
||||
|
||||
// TcNbr: solid Tp
|
||||
// Tv: vapour Tp
|
||||
const scalarField c(TcNbr*KDeltaNbr + Tv.patchInternalField()*KdeltaVap);
|
||||
|
||||
const scalarField a(KdeltaVap + KDeltaNbr);
|
||||
|
||||
valueFraction() = a/(a + KdeltaLiq);
|
||||
refValue() = c/a;
|
||||
refGrad() = (qr + qrNbr)/kappa(Tp);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
scalarField Tc(patchInternalField());
|
||||
scalarField qLiq((Tp - Tc)*KdeltaLiq);
|
||||
scalarField qVap((Tp - Tv.patchInternalField())*KdeltaVap);
|
||||
|
||||
Info<< "T flow : " << nl << endl;
|
||||
|
||||
Info<< " qLiq: " << gMin(qLiq) << " - " << gMax(qLiq) << endl;
|
||||
Info<< " qVap: " << gMin(qVap) << " - " << gMax(qVap) << endl;
|
||||
|
||||
scalar QLiq = gSum(qLiq*patch().magSf());
|
||||
scalar QVap = gSum(qVap*patch().magSf());
|
||||
|
||||
Info<< " Heat transfer to Liq: " << QLiq << endl;
|
||||
Info<< " Heat transfer to Vap: " << QVap << endl;
|
||||
|
||||
Info<< " walltemperature "
|
||||
<< " min:" << gMin(Tp)
|
||||
<< " max:" << gMax(Tp)
|
||||
<< " avg:" << gAverage(Tp)
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Unknown phase type. Valid types are: "
|
||||
<< regionTypeNames_ << nl << exit(FatalError);
|
||||
}
|
||||
|
||||
mixedFvPatchScalarField::updateCoeffs();
|
||||
|
||||
// Restore tag
|
||||
UPstream::msgType() = oldTag;
|
||||
}
|
||||
|
||||
|
||||
void turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField::write
|
||||
(
|
||||
Ostream& os
|
||||
) const
|
||||
{
|
||||
mixedFvPatchScalarField::write(os);
|
||||
os.writeEntry("kappaMethod", KMethodTypeNames_[method_]);
|
||||
os.writeEntryIfDifferent<word>("kappa","none", kappaName_);
|
||||
|
||||
os.writeEntry("Tnbr", TnbrName_);
|
||||
|
||||
os.writeEntryIfDifferent<word>("qrNbr", "none", qrNbrName_);
|
||||
os.writeEntryIfDifferent<word>("qr", "none", qrName_);
|
||||
|
||||
os.writeKeyword("region") << regionTypeNames_[regionType_]
|
||||
<< token::END_STATEMENT << nl;
|
||||
|
||||
os.writeKeyword("otherPhase") << otherPhaseName_ << token::END_STATEMENT
|
||||
<< nl;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
makePatchTypeField
|
||||
(
|
||||
fvPatchScalarField,
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace compressible
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,252 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::compressible::
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
|
||||
Description
|
||||
Mixed boundary condition for temperature and radiation heat transfer
|
||||
to be used for in multiregion cases with two phase Euler system
|
||||
|
||||
Usage
|
||||
\table
|
||||
Property | Description | Required | Default value
|
||||
Tnbr | name of the field | no | T
|
||||
qrNbr | name of the radiative flux in the nbr region | no | none
|
||||
qr | name of the radiative flux in this region | no | none
|
||||
region | region to which this BC belongs | yes
|
||||
otherPhase | name of the vapour phase in the fluid region | yes
|
||||
kappaMethod | inherited from temperatureCoupledBase | inherited |
|
||||
kappa | inherited from temperatureCoupledBase | inherited |
|
||||
\endtable
|
||||
|
||||
Example of the boundary condition specification on the fluid region:
|
||||
\verbatim
|
||||
<patchName>
|
||||
{
|
||||
type compressible::turbulentTemperatureTwoPhaseRadCoupledMixed;
|
||||
Tnbr T;
|
||||
qrNbr none;
|
||||
qr none;
|
||||
kappaMethod phaseSystem;
|
||||
region fluid;
|
||||
otherPhase gas;
|
||||
value uniform 300;
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Example of the boundary condition specification on the solid region:
|
||||
\verbatim
|
||||
<patchName>
|
||||
{
|
||||
type compressible::turbulentTemperatureTwoPhaseRadCoupledMixed;
|
||||
Tnbr T.liquid;
|
||||
qrNbr none;
|
||||
qr none;
|
||||
kappaMethod solidThermo;
|
||||
region solid;
|
||||
otherPhase gas;
|
||||
value uniform 300;
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Needs to be on underlying mapped(Wall)FvPatch.
|
||||
|
||||
|
||||
SourceFiles
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField_H
|
||||
#define turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField_H
|
||||
|
||||
#include "mixedFvPatchFields.H"
|
||||
#include "scalarList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace compressible
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
:
|
||||
public mixedFvPatchScalarField
|
||||
{
|
||||
public:
|
||||
|
||||
// Public enumerations
|
||||
|
||||
//- Type of supplied Kappa
|
||||
enum KMethodType
|
||||
{
|
||||
mtSolidThermo,
|
||||
mtLookup,
|
||||
mtPhaseSystem
|
||||
};
|
||||
|
||||
// Data types
|
||||
|
||||
//- Enumeration listing the region
|
||||
enum regionType
|
||||
{
|
||||
solid,
|
||||
fluid
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
//- Heat source type names
|
||||
static const Enum<regionType> regionTypeNames_;
|
||||
|
||||
//- Kappa method types
|
||||
static const Enum<KMethodType> KMethodTypeNames_;
|
||||
|
||||
//- Heat source type
|
||||
regionType regionType_;
|
||||
|
||||
//- How to get K
|
||||
const KMethodType method_;
|
||||
|
||||
//- Name of thermal conductivity field (if looked up from database)
|
||||
const word kappaName_;
|
||||
|
||||
//- name of the other phase (vapor/liquid phase)
|
||||
word otherPhaseName_;
|
||||
|
||||
//- Name of field on the neighbour region
|
||||
const word TnbrName_;
|
||||
|
||||
//- Name of the radiative heat flux in the neighbour region
|
||||
const word qrNbrName_;
|
||||
|
||||
//- Name of the radiative heat flux in local region
|
||||
const word qrName_;
|
||||
|
||||
|
||||
// Private members
|
||||
|
||||
//- Given patch temperature calculate corresponding K field
|
||||
tmp<scalarField> kappa(const scalarField& Tp) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("compressible::turbulentTemperatureTwoPhaseRadCoupledMixed");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from patch and internal field
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
(
|
||||
const fvPatch&,
|
||||
const DimensionedField<scalar, volMesh>&
|
||||
);
|
||||
|
||||
//- Construct from patch, internal field and dictionary
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
(
|
||||
const fvPatch&,
|
||||
const DimensionedField<scalar, volMesh>&,
|
||||
const dictionary&
|
||||
);
|
||||
|
||||
//- Construct by mapping given
|
||||
// turbulentTemperatureCoupledBaffleMixedFvPatchScalarField onto a
|
||||
// new patch
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
(
|
||||
const
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField&,
|
||||
const fvPatch&,
|
||||
const DimensionedField<scalar, volMesh>&,
|
||||
const fvPatchFieldMapper&
|
||||
);
|
||||
|
||||
//- Construct and return a clone
|
||||
virtual tmp<fvPatchScalarField> clone() const
|
||||
{
|
||||
return tmp<fvPatchScalarField>
|
||||
(
|
||||
new turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
(
|
||||
*this
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//- Construct as copy setting internal field reference
|
||||
turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
(
|
||||
const turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField&,
|
||||
const DimensionedField<scalar, volMesh>&
|
||||
);
|
||||
|
||||
//- Construct and return a clone setting internal field reference
|
||||
virtual tmp<fvPatchScalarField> clone
|
||||
(
|
||||
const DimensionedField<scalar, volMesh>& iF
|
||||
) const
|
||||
{
|
||||
return tmp<fvPatchScalarField>
|
||||
(
|
||||
new turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField
|
||||
(
|
||||
*this,
|
||||
iF
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
//- Update the coefficients associated with the patch field
|
||||
virtual void updateCoeffs();
|
||||
|
||||
//- Write
|
||||
virtual void write(Ostream&) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace compressible
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,51 @@
|
||||
scalar CoNum = -GREAT;
|
||||
|
||||
forAll(fluidRegions, regioni)
|
||||
{
|
||||
if (fluidRegions[regioni].nInternalFaces())
|
||||
{
|
||||
const surfaceScalarField& phi =
|
||||
phaseSystemFluid[regioni].phi();
|
||||
|
||||
scalarField sumPhi
|
||||
(
|
||||
fvc::surfaceSum(mag(phi))().primitiveField()
|
||||
);
|
||||
|
||||
const surfaceScalarField& phi1 =
|
||||
phaseSystemFluid[regioni].phase1().phiRef();
|
||||
|
||||
const surfaceScalarField& phi2 =
|
||||
phaseSystemFluid[regioni].phase2().phiRef();
|
||||
|
||||
sumPhi = max
|
||||
(
|
||||
sumPhi,
|
||||
fvc::surfaceSum(mag(phi1))().primitiveField()
|
||||
);
|
||||
|
||||
sumPhi = max
|
||||
(
|
||||
sumPhi,
|
||||
fvc::surfaceSum(mag(phi2))().primitiveField()
|
||||
);
|
||||
|
||||
|
||||
CoNum =
|
||||
0.5*gMax
|
||||
(
|
||||
sumPhi/fluidRegions[regioni].V().field()
|
||||
)*runTime.deltaTValue();
|
||||
|
||||
scalar UrCoNum = 0.5*gMax
|
||||
(
|
||||
fvc::surfaceSum(mag(phi1 - phi2))().primitiveField()
|
||||
/ fluidRegions[regioni].V().field()
|
||||
)*runTime.deltaTValue(),
|
||||
|
||||
CoNum = max(UrCoNum, CoNum);
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "Courant Number max: " << CoNum << endl;
|
||||
|
||||
@ -0,0 +1,147 @@
|
||||
// Initialise fluid field pointer lists
|
||||
PtrList<twoPhaseSystem> phaseSystemFluid(fluidRegions.size());
|
||||
|
||||
PtrList<volScalarField> ghFluid(fluidRegions.size());
|
||||
PtrList<surfaceScalarField> ghfFluid(fluidRegions.size());
|
||||
PtrList<uniformDimensionedScalarField> hRefFluid(fluidRegions.size());
|
||||
|
||||
PtrList<volScalarField> p_rghFluid(fluidRegions.size());
|
||||
|
||||
PtrList<multivariateSurfaceInterpolationScheme<scalar>::fieldTable>
|
||||
fieldsFluid(fluidRegions.size());
|
||||
|
||||
List<scalar> initialMassFluid(fluidRegions.size());
|
||||
List<bool> frozenFlowFluid(fluidRegions.size(), false);
|
||||
|
||||
List<label> pRefCellFluid(fluidRegions.size());
|
||||
List<scalar> pRefValueFluid(fluidRegions.size());
|
||||
PtrList<dimensionedScalar> pMinFluid(fluidRegions.size());
|
||||
|
||||
const uniformDimensionedVectorField& g = meshObjects::gravity::New(runTime);
|
||||
|
||||
PtrList<pimpleControl> pimpleFluid(fluidRegions.size());
|
||||
|
||||
// Populate fluid field pointer lists
|
||||
forAll(fluidRegions, i)
|
||||
{
|
||||
Info<< "*** Reading fluid mesh thermophysical properties for region "
|
||||
<< fluidRegions[i].name() << nl << endl;
|
||||
|
||||
pimpleFluid.set
|
||||
(
|
||||
i,
|
||||
new pimpleControl(fluidRegions[i])
|
||||
);
|
||||
|
||||
Info<< " Adding to phaseSystemFluid\n" << endl;
|
||||
phaseSystemFluid.set(i, twoPhaseSystem::New(fluidRegions[i]).ptr());
|
||||
|
||||
Info<< " Adding hRefFluid\n" << endl;
|
||||
hRefFluid.set
|
||||
(
|
||||
i,
|
||||
new uniformDimensionedScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"hRef",
|
||||
runTime.constant(),
|
||||
fluidRegions[i],
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
dimensionedScalar("hRef", dimLength, Zero)
|
||||
)
|
||||
);
|
||||
|
||||
Info<< " Adding ghRef\n" << endl;
|
||||
dimensionedScalar ghRef
|
||||
(
|
||||
mag(g.value()) > SMALL
|
||||
? g & (cmptMag(g.value())/mag(g.value()))*hRefFluid[i]
|
||||
: dimensionedScalar("ghRef", g.dimensions()*dimLength, 0)
|
||||
);
|
||||
|
||||
ghFluid.set
|
||||
(
|
||||
i,
|
||||
new volScalarField
|
||||
(
|
||||
"gh",
|
||||
(g & fluidRegions[i].C()) - ghRef
|
||||
)
|
||||
);
|
||||
|
||||
ghfFluid.set
|
||||
(
|
||||
i,
|
||||
new surfaceScalarField
|
||||
(
|
||||
"ghf",
|
||||
(g & fluidRegions[i].Cf()) - ghRef
|
||||
)
|
||||
);
|
||||
|
||||
Info<< " Adding p_rghFluid\n" << endl;
|
||||
p_rghFluid.set
|
||||
(
|
||||
i,
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"p_rgh",
|
||||
runTime.timeName(),
|
||||
fluidRegions[i],
|
||||
IOobject::MUST_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
fluidRegions[i]
|
||||
)
|
||||
);
|
||||
|
||||
Info<< " Correcting p_rghFluid\n" << endl;
|
||||
|
||||
// Force p_rgh to be consistent with p
|
||||
p_rghFluid[i] =
|
||||
phaseSystemFluid[i].phase1().thermo().p()
|
||||
- phaseSystemFluid[i].phase1().thermo().rho()*ghFluid[i];
|
||||
|
||||
fluidRegions[i].setFluxRequired(p_rghFluid[i].name());
|
||||
|
||||
Info<< " Correcting initialMassFluid\n" << endl;
|
||||
initialMassFluid[i] =
|
||||
fvc::domainIntegrate(phaseSystemFluid[i].rho()).value();
|
||||
|
||||
const dictionary& pimpleDict =
|
||||
fluidRegions[i].solutionDict().subDict("PIMPLE");
|
||||
|
||||
pimpleDict.readIfPresent("frozenFlow", frozenFlowFluid[i]);
|
||||
|
||||
pRefCellFluid[i] = -1;
|
||||
pRefValueFluid[i] = 0.0;
|
||||
|
||||
Info<< " Setting reference\n" << endl;
|
||||
if (p_rghFluid[i].needReference())
|
||||
{
|
||||
setRefCell
|
||||
(
|
||||
phaseSystemFluid[i].phase1().thermoRef().p(),
|
||||
p_rghFluid[i],
|
||||
pimpleDict,
|
||||
pRefCellFluid[i],
|
||||
pRefValueFluid[i]
|
||||
);
|
||||
}
|
||||
|
||||
pMinFluid.set
|
||||
(
|
||||
i,
|
||||
new dimensionedScalar
|
||||
(
|
||||
"pMin",
|
||||
dimPressure,
|
||||
phaseSystemFluid[i]
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
PtrList<uniformDimensionedScalarField> cumulativeContErrIO(fluidRegions.size());
|
||||
forAll(cumulativeContErrIO, i)
|
||||
{
|
||||
#include "setRegionFluidFields.H"
|
||||
cumulativeContErrIO.set
|
||||
(
|
||||
i,
|
||||
new uniformDimensionedScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"cumulativeContErr",
|
||||
runTime.timeName(),
|
||||
"uniform",
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
dimensionedScalar(dimless, Zero)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
UPtrList<scalar> cumulativeContErr(cumulativeContErrIO.size());
|
||||
forAll(cumulativeContErrIO, i)
|
||||
{
|
||||
cumulativeContErr.set(i, &cumulativeContErrIO[i].value());
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
const dictionary& pimpleDict = mesh.solutionDict().subDict("PIMPLE");
|
||||
|
||||
Switch faceMomentum
|
||||
(
|
||||
pimpleDict.lookupOrDefault<Switch>("faceMomentum", false)
|
||||
);
|
||||
|
||||
int nEnergyCorrectors
|
||||
(
|
||||
pimpleDict.lookupOrDefault<int>("nEnergyCorrectors", 1)
|
||||
);
|
||||
@ -0,0 +1,58 @@
|
||||
fvMesh& mesh = fluidRegions[i];
|
||||
|
||||
twoPhaseSystem& fluid = phaseSystemFluid[i];
|
||||
|
||||
phaseModel& phase1 = fluid.phase1();
|
||||
phaseModel& phase2 = fluid.phase2();
|
||||
|
||||
const volScalarField& alpha1 = phase1;
|
||||
const volScalarField& alpha2 = phase2;
|
||||
|
||||
volVectorField& U1 = phase1.URef();
|
||||
surfaceScalarField& phi1 = phase1.phiRef();
|
||||
const surfaceScalarField& alphaPhi1 = phase1.alphaPhi();
|
||||
|
||||
volVectorField& U2 = phase2.URef();
|
||||
surfaceScalarField& phi2 = phase2.phiRef();
|
||||
const surfaceScalarField& alphaPhi2 = phase2.alphaPhi();
|
||||
|
||||
surfaceScalarField& phi = fluid.phi();
|
||||
|
||||
rhoThermo& thermo1 = phase1.thermoRef();
|
||||
rhoThermo& thermo2 = phase2.thermoRef();
|
||||
|
||||
thermo1.validate(args.executable(), "h", "e");
|
||||
thermo2.validate(args.executable(), "h", "e");
|
||||
|
||||
volScalarField& rho1 = thermo1.rho();
|
||||
const volScalarField& psi1 = thermo1.psi();
|
||||
|
||||
volScalarField& rho2 = thermo2.rho();
|
||||
const volScalarField& psi2 = thermo2.psi();
|
||||
|
||||
const IOMRFZoneList& MRF = fluid.MRF();
|
||||
fv::options& fvOptions = fluid.fvOptions();
|
||||
|
||||
volScalarField& p = thermo1.p();
|
||||
|
||||
volScalarField& p_rgh = p_rghFluid[i];
|
||||
|
||||
//const dimensionedVector& g = gFluid[i];
|
||||
const volScalarField& gh = ghFluid[i];
|
||||
const surfaceScalarField& ghf = ghfFluid[i];
|
||||
|
||||
const dimensionedScalar initialMass
|
||||
(
|
||||
"initialMass",
|
||||
dimMass,
|
||||
initialMassFluid[i]
|
||||
);
|
||||
|
||||
bool frozenFlow = frozenFlowFluid[i];
|
||||
|
||||
//const label pRefCell = pRefCellFluid[i];
|
||||
//const scalar pRefValue = pRefValueFluid[i];
|
||||
|
||||
pimpleControl& pimple = pimpleFluid[i];
|
||||
|
||||
const dimensionedScalar& pMin = pMinFluid[i];
|
||||
@ -0,0 +1,39 @@
|
||||
if (finalIter)
|
||||
{
|
||||
mesh.data::add("finalIteration", true);
|
||||
}
|
||||
|
||||
if (frozenFlow)
|
||||
{
|
||||
#include "EEqns.H"
|
||||
}
|
||||
else
|
||||
{
|
||||
fluid.solve();
|
||||
fluid.correct();
|
||||
|
||||
#include "YEqns.H"
|
||||
|
||||
if (faceMomentum)
|
||||
{
|
||||
#include "pUf/UEqns.H"
|
||||
#include "EEqns.H"
|
||||
#include "pUf/pEqn.H"
|
||||
}
|
||||
else
|
||||
{
|
||||
#include "pU/UEqns.H"
|
||||
#include "EEqns.H"
|
||||
#include "pU/pEqn.H"
|
||||
}
|
||||
|
||||
fluid.correctKinematics();
|
||||
|
||||
// Update alpha's for new U
|
||||
fluid.correctTurbulence();
|
||||
}
|
||||
|
||||
if (finalIter)
|
||||
{
|
||||
mesh.data::remove("finalIteration");
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
p_rghFluid[i].storePrevIter();
|
||||
//rhoFluid[i].storePrevIter();
|
||||
@ -137,7 +137,8 @@
|
||||
alphaPhi10,
|
||||
talphaPhi1Corr0.ref(),
|
||||
zeroField(), zeroField(),
|
||||
1, 0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
alphaPhi10 += talphaPhi1Corr0();
|
||||
@ -187,8 +188,8 @@
|
||||
talphaPhi1Corr.ref(),
|
||||
Sp,
|
||||
(-Sp*alpha1)(),
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
// Under-relax the correction for all but the 1st corrector
|
||||
@ -214,8 +215,8 @@
|
||||
alphaPhi10,
|
||||
Sp,
|
||||
(Su + divU*min(alpha1(), scalar(1)))(),
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -133,7 +133,15 @@
|
||||
if (alphaApplyPrevCorr && talphaPhi1Corr0.valid())
|
||||
{
|
||||
Info<< "Applying the previous iteration compression flux" << endl;
|
||||
MULES::correct(alpha1, alphaPhi10, talphaPhi1Corr0.ref(), 1, 0);
|
||||
MULES::correct
|
||||
(
|
||||
geometricOneField(),
|
||||
alpha1,
|
||||
alphaPhi10,
|
||||
talphaPhi1Corr0.ref(),
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
alphaPhi10 += talphaPhi1Corr0();
|
||||
}
|
||||
@ -182,8 +190,8 @@
|
||||
talphaPhi1Corr.ref(),
|
||||
Sp,
|
||||
(-Sp*alpha1)(),
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
// Under-relax the correction for all but the 1st corrector
|
||||
@ -209,8 +217,8 @@
|
||||
alphaPhi10,
|
||||
Sp,
|
||||
(Su + divU*min(alpha1(), scalar(1)))(),
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -330,6 +330,25 @@ Foam::tmp<Foam::scalarField> Foam::twoPhaseMixtureThermo::kappa
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::volScalarField> Foam::twoPhaseMixtureThermo::alphahe() const
|
||||
{
|
||||
return
|
||||
alpha1()*thermo1_->alphahe()
|
||||
+ alpha2()*thermo2_->alphahe();
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::scalarField> Foam::twoPhaseMixtureThermo::alphahe
|
||||
(
|
||||
const label patchi
|
||||
) const
|
||||
{
|
||||
return
|
||||
alpha1().boundaryField()[patchi]*thermo1_->alphahe(patchi)
|
||||
+ alpha2().boundaryField()[patchi]*thermo2_->alphahe(patchi);
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::volScalarField> Foam::twoPhaseMixtureThermo::kappaEff
|
||||
(
|
||||
const volScalarField& alphat
|
||||
|
||||
@ -268,6 +268,13 @@ public:
|
||||
const label patchi
|
||||
) const;
|
||||
|
||||
|
||||
//- Thermal diffusivity for energy of mixture [kg/m/s]
|
||||
virtual tmp<volScalarField> alphahe() const;
|
||||
|
||||
//- Thermal diffusivity for energy of mixture for patch [kg/m/s]
|
||||
virtual tmp<scalarField> alphahe(const label patchi) const;
|
||||
|
||||
//- Effective thermal diffusivity of mixture [J/m/s/K]
|
||||
virtual tmp<volScalarField> kappaEff
|
||||
(
|
||||
|
||||
@ -45,6 +45,9 @@ namespace Foam
|
||||
defineTypeNameAndDebug(multiphaseMixtureThermo, 0);
|
||||
}
|
||||
|
||||
const Foam::scalar Foam::multiphaseMixtureThermo::convertToRad =
|
||||
Foam::constant::mathematical::pi/180.0;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
@ -605,6 +608,45 @@ Foam::tmp<Foam::scalarField> Foam::multiphaseMixtureThermo::kappa
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::volScalarField> Foam::multiphaseMixtureThermo::alphahe() const
|
||||
{
|
||||
PtrDictionary<phaseModel>::const_iterator phasei = phases_.begin();
|
||||
|
||||
tmp<volScalarField> talphaEff(phasei()*phasei().thermo().alphahe());
|
||||
|
||||
for (++phasei; phasei != phases_.end(); ++phasei)
|
||||
{
|
||||
talphaEff.ref() += phasei()*phasei().thermo().alphahe();
|
||||
}
|
||||
|
||||
return talphaEff;
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::scalarField> Foam::multiphaseMixtureThermo::alphahe
|
||||
(
|
||||
const label patchi
|
||||
) const
|
||||
{
|
||||
PtrDictionary<phaseModel>::const_iterator phasei = phases_.begin();
|
||||
|
||||
tmp<scalarField> talphaEff
|
||||
(
|
||||
phasei().boundaryField()[patchi]
|
||||
*phasei().thermo().alphahe(patchi)
|
||||
);
|
||||
|
||||
for (++phasei; phasei != phases_.end(); ++phasei)
|
||||
{
|
||||
talphaEff.ref() +=
|
||||
phasei().boundaryField()[patchi]
|
||||
*phasei().thermo().alphahe(patchi);
|
||||
}
|
||||
|
||||
return talphaEff;
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::volScalarField> Foam::multiphaseMixtureThermo::kappaEff
|
||||
(
|
||||
const volScalarField& alphat
|
||||
@ -1042,8 +1084,8 @@ void Foam::multiphaseMixtureThermo::solveAlphas
|
||||
alphaPhiCorr,
|
||||
zeroField(),
|
||||
zeroField(),
|
||||
1,
|
||||
0,
|
||||
oneField(),
|
||||
zeroField(),
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
@ -138,6 +138,10 @@ private:
|
||||
//- Stabilisation for normalisation of the interface normal
|
||||
const dimensionedScalar deltaN_;
|
||||
|
||||
//- Conversion factor for degrees into radians
|
||||
static const scalar convertToRad;
|
||||
|
||||
|
||||
|
||||
// Private member functions
|
||||
|
||||
@ -388,6 +392,13 @@ public:
|
||||
const label patchi
|
||||
) const;
|
||||
|
||||
|
||||
//- Thermal diffusivity for energy of mixture [kg/m/s]
|
||||
virtual tmp<volScalarField> alphahe() const;
|
||||
|
||||
//- Thermal diffusivity for energy of mixture for patch [kg/m/s]
|
||||
virtual tmp<scalarField> alphahe(const label patchi) const;
|
||||
|
||||
//- Effective thermal diffusivity of mixture [J/m/s/K]
|
||||
virtual tmp<volScalarField> kappaEff
|
||||
(
|
||||
|
||||
@ -32,11 +32,12 @@
|
||||
|
||||
MULES::correct
|
||||
(
|
||||
geometricOneField(),
|
||||
alpha1,
|
||||
alphaPhi,
|
||||
talphaPhiCorr0.ref(),
|
||||
mixture.alphaMax(),
|
||||
0
|
||||
UniformField<scalar>(mixture.alphaMax()),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
alphaPhi += talphaPhiCorr0();
|
||||
@ -71,11 +72,12 @@
|
||||
|
||||
MULES::correct
|
||||
(
|
||||
geometricOneField(),
|
||||
alpha1,
|
||||
talphaPhiUn(),
|
||||
talphaPhiCorr.ref(),
|
||||
mixture.alphaMax(),
|
||||
0
|
||||
UniformField<scalar>(mixture.alphaMax()),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
// Under-relax the correction for all but the 1st corrector
|
||||
@ -95,11 +97,12 @@
|
||||
|
||||
MULES::explicitSolve
|
||||
(
|
||||
geometricOneField(),
|
||||
alpha1,
|
||||
phi,
|
||||
alphaPhi,
|
||||
mixture.alphaMax(),
|
||||
0
|
||||
UniformField<scalar>(mixture.alphaMax()),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ MultiComponentPhaseModel
|
||||
|
||||
species_ = thermoPtr_->composition().species();
|
||||
|
||||
inertIndex_ = species_[thermoPtr_->getWord("inertSpecie")];
|
||||
inertIndex_ = species_[thermoPtr_().template get<word>("inertSpecie")];
|
||||
|
||||
X_.setSize(thermoPtr_->composition().species().size());
|
||||
|
||||
@ -104,6 +104,7 @@ MultiComponentPhaseModel
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
template<class BasePhaseModel, class phaseThermo>
|
||||
void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>
|
||||
::calculateVolumeFractions()
|
||||
@ -190,7 +191,7 @@ void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>::solveYi
|
||||
|
||||
const dictionary& MULEScontrols = mesh.solverDict(alpha1.name());
|
||||
|
||||
scalar cAlpha(MULEScontrols.get<scalar>("cYi"));
|
||||
scalar cAlpha(readScalar(MULEScontrols.lookup("cYi")));
|
||||
|
||||
PtrList<surfaceScalarField> phiYiCorrs(species_.size());
|
||||
const surfaceScalarField& phi = this->fluid().phi();
|
||||
@ -201,7 +202,7 @@ void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>::solveYi
|
||||
|
||||
surfaceScalarField phir(0.0*phi);
|
||||
|
||||
forAllConstIters(this->fluid().phases(),iter2)
|
||||
forAllConstIter(phaseSystem::phaseModelTable,this->fluid().phases(),iter2)
|
||||
{
|
||||
const volScalarField& alpha2 = iter2()();
|
||||
if (&alpha2 == &alpha1)
|
||||
@ -250,7 +251,10 @@ void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>::solveYi
|
||||
|
||||
surfaceScalarField& phiYiCorr = phiYiCorrs[i];
|
||||
|
||||
forAllConstIters(this->fluid().phases(), iter2)
|
||||
forAllConstIter
|
||||
(
|
||||
phaseSystem::phaseModelTable, this->fluid().phases(), iter2
|
||||
)
|
||||
{
|
||||
//const volScalarField& alpha2 = iter2()().oldTime();
|
||||
const volScalarField& alpha2 = iter2()();
|
||||
@ -298,8 +302,8 @@ void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>::solveYi
|
||||
phiYiCorr,
|
||||
Sp[i],
|
||||
Su[i],
|
||||
1,
|
||||
0,
|
||||
oneField(),
|
||||
zeroField(),
|
||||
true
|
||||
);
|
||||
}
|
||||
@ -354,8 +358,8 @@ void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>::solveYi
|
||||
phiYiCorr,
|
||||
Sp[i],
|
||||
Su[i],
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -369,8 +373,8 @@ void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>::solveYi
|
||||
phiYiCorr,
|
||||
Sp[i],
|
||||
Su[i],
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
Yt += Yi;
|
||||
|
||||
@ -213,6 +213,18 @@ Foam::tmp<Foam::scalarField> Foam::phaseModel::kappa(const label patchI) const
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::volScalarField> Foam::phaseModel::alphahe() const
|
||||
{
|
||||
return thermo().alphahe();
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::scalarField> Foam::phaseModel::alphahe(const label patchI) const
|
||||
{
|
||||
return thermo().alphahe(patchI);
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::volScalarField>Foam::phaseModel::kappaEff
|
||||
(
|
||||
const volScalarField& kappat
|
||||
|
||||
@ -226,6 +226,12 @@ public:
|
||||
//- Thermal diffusivity for temperature of phase for patch [J/m/s/K]
|
||||
tmp<scalarField> kappa(const label patchi) const;
|
||||
|
||||
//- Thermal diffusivity for energy of mixture [kg/m/s]
|
||||
tmp<volScalarField> alphahe() const;
|
||||
|
||||
//- Thermal diffusivity for energy of mixture for patch [kg/m/s]
|
||||
tmp<scalarField> alphahe(const label patchi) const;
|
||||
|
||||
//- Effective thermal diffusivity for temperature of phase [J/m/s/K]
|
||||
tmp<volScalarField> kappaEff(const volScalarField&) const;
|
||||
|
||||
|
||||
@ -414,8 +414,8 @@ void Foam::multiphaseSystem::solve()
|
||||
phiAlphaCorr,
|
||||
Sp,
|
||||
Su,
|
||||
1,
|
||||
0,
|
||||
oneField(),
|
||||
zeroField(),
|
||||
true
|
||||
);
|
||||
++phasei;
|
||||
@ -485,8 +485,8 @@ void Foam::multiphaseSystem::solve()
|
||||
phiAlpha,
|
||||
(alphaSubCycle.index()*Sp)(),
|
||||
(Su - (alphaSubCycle.index() - 1)*Sp*alpha1)(),
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
if (alphaSubCycle.index() == 1)
|
||||
@ -511,8 +511,8 @@ void Foam::multiphaseSystem::solve()
|
||||
phiAlpha,
|
||||
Sp,
|
||||
Su,
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
phase.alphaPhi() = phiAlpha;
|
||||
|
||||
@ -649,6 +649,48 @@ Foam::tmp<Foam::scalarField> Foam::phaseSystem::kappa(const label patchI) const
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::volScalarField> Foam::phaseSystem::alphahe() const
|
||||
{
|
||||
phaseModelTable::const_iterator phaseModelIter = phaseModels_.begin();
|
||||
|
||||
tmp<volScalarField> talphaEff
|
||||
(
|
||||
phaseModelIter()()*phaseModelIter()->alphahe()
|
||||
);
|
||||
|
||||
for (; phaseModelIter != phaseModels_.end(); ++phaseModelIter)
|
||||
{
|
||||
talphaEff.ref() += phaseModelIter()()*phaseModelIter()->alphahe();
|
||||
}
|
||||
|
||||
return talphaEff;
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::scalarField> Foam::phaseSystem::alphahe
|
||||
(
|
||||
const label patchi
|
||||
) const
|
||||
{
|
||||
phaseModelTable::const_iterator phaseModelIter = phaseModels_.begin();
|
||||
|
||||
tmp<scalarField> talphaEff
|
||||
(
|
||||
phaseModelIter()().boundaryField()[patchi]
|
||||
*phaseModelIter()->alphahe(patchi)
|
||||
);
|
||||
|
||||
for (; phaseModelIter != phaseModels_.end(); ++phaseModelIter)
|
||||
{
|
||||
talphaEff.ref() +=
|
||||
phaseModelIter()().boundaryField()[patchi]
|
||||
*phaseModelIter()->alphahe(patchi);
|
||||
}
|
||||
|
||||
return talphaEff;
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::volScalarField>Foam::phaseSystem::kappaEff
|
||||
(
|
||||
const volScalarField& kappat
|
||||
|
||||
@ -396,6 +396,12 @@ public:
|
||||
const label patchi
|
||||
) const;
|
||||
|
||||
//- Thermal diffusivity for energy of mixture [kg/m/s]
|
||||
virtual tmp<volScalarField> alphahe() const;
|
||||
|
||||
//- Thermal diffusivity for energy of mixture for patch [kg/m/s]
|
||||
virtual tmp<scalarField> alphahe(const label patchi) const;
|
||||
|
||||
//- Effective thermal diffusivity for temperature
|
||||
// of mixture [J/m/s/K]
|
||||
virtual tmp<volScalarField> kappaEff
|
||||
|
||||
@ -1,17 +1,11 @@
|
||||
{
|
||||
tmp<volScalarField> tcp(thermo->Cp());
|
||||
const volScalarField& cp = tcp();
|
||||
|
||||
rhoCp = rho*cp;
|
||||
|
||||
kappaEff = thermo->kappa() + rho*cp*turbulence->nut()/Prt;
|
||||
|
||||
pDivU = dimensionedScalar("pDivU", p.dimensions()/dimTime, Zero);
|
||||
|
||||
if (thermo->pDivU())
|
||||
{
|
||||
pDivU = (p*fvc::div(rhoPhi/fvc::interpolate(rho)));
|
||||
}
|
||||
|
||||
const surfaceScalarField rhoCpPhi(fvc::interpolate(cp)*rhoPhi);
|
||||
|
||||
Pair<tmp<volScalarField>> vDotAlphal = mixture->mDot();
|
||||
@ -23,13 +17,13 @@
|
||||
fvScalarMatrix TEqn
|
||||
(
|
||||
fvm::ddt(rhoCp, T)
|
||||
+ fvm::div(rhoCpPhi, T, "div(rhoCpPhi,T)")
|
||||
+ fvm::div(rhoCpPhi, T)
|
||||
- fvm::Sp(fvc::ddt(rhoCp) + fvc::div(rhoCpPhi), T)
|
||||
- fvm::laplacian(kappaEff, T)
|
||||
+ thermo->hc()*vDotvmcAlphal
|
||||
+ pDivU
|
||||
);
|
||||
|
||||
|
||||
TEqn.relax();
|
||||
TEqn.solve();
|
||||
|
||||
@ -57,8 +57,7 @@ volScalarField rho
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
alpha1*rho1 + alpha2*rho2,
|
||||
alpha1.boundaryField().types()
|
||||
alpha1*rho1 + alpha2*rho2
|
||||
);
|
||||
rho.oldTime();
|
||||
|
||||
@ -123,19 +122,6 @@ volScalarField kappaEff
|
||||
thermo->kappa()
|
||||
);
|
||||
|
||||
Info<< "Creating field pDivU\n" << endl;
|
||||
volScalarField pDivU
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"pDivU",
|
||||
runTime.timeName(),
|
||||
mesh
|
||||
),
|
||||
mesh,
|
||||
dimensionedScalar(p.dimensions()/dimTime, Zero)
|
||||
);
|
||||
|
||||
// Need to store rho for ddt(rhoCp, U)
|
||||
volScalarField rhoCp
|
||||
(
|
||||
@ -149,4 +135,5 @@ volScalarField rhoCp
|
||||
),
|
||||
rho*thermo->Cp()
|
||||
);
|
||||
|
||||
rhoCp.oldTime();
|
||||
|
||||
@ -118,9 +118,8 @@ int main(int argc, char *argv[])
|
||||
#include "alphaEqnSubCycle.H"
|
||||
|
||||
solve(fvm::ddt(rho) + fvc::div(rhoPhi));
|
||||
|
||||
#include "UEqn.H"
|
||||
#include "eEqn.H"
|
||||
#include "TEqn.H"
|
||||
|
||||
// --- Pressure corrector loop
|
||||
while (pimple.correct())
|
||||
|
||||
@ -490,6 +490,22 @@ Foam::tmp<Foam::scalarField> Foam::twoPhaseMixtureEThermo::kappa
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::volScalarField> Foam::twoPhaseMixtureEThermo::alphahe() const
|
||||
{
|
||||
NotImplemented;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::scalarField> Foam::twoPhaseMixtureEThermo::alphahe
|
||||
(
|
||||
const label patchi
|
||||
) const
|
||||
{
|
||||
NotImplemented;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Foam::tmp<Foam::volScalarField> Foam::twoPhaseMixtureEThermo::kappaEff
|
||||
(
|
||||
const volScalarField& kappat
|
||||
|
||||
@ -246,6 +246,12 @@ public:
|
||||
const label patchi
|
||||
) const;
|
||||
|
||||
//- Thermal diffusivity for energy of mixture [kg/m/s]
|
||||
virtual tmp<volScalarField> alphahe() const;
|
||||
|
||||
//- Thermal diffusivity for energy of mixture for patch [kg/m/s]
|
||||
virtual tmp<scalarField> alphahe(const label patchi) const;
|
||||
|
||||
//- Effective thermal diffusivity for temperature
|
||||
//- of mixture [J/m/s/K]
|
||||
virtual tmp<volScalarField> kappaEff
|
||||
|
||||
@ -87,8 +87,8 @@
|
||||
alphaPhi1,
|
||||
zeroField(),
|
||||
zeroField(),
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
else
|
||||
@ -103,8 +103,8 @@
|
||||
alphaPhi1,
|
||||
zeroField(),
|
||||
zeroField(),
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
|
||||
@ -155,8 +155,8 @@
|
||||
alphaPhi2,
|
||||
zeroField(),
|
||||
zeroField(),
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
else
|
||||
@ -171,8 +171,8 @@
|
||||
alphaPhi2,
|
||||
zeroField(),
|
||||
zeroField(),
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -78,8 +78,8 @@
|
||||
divU*(alpha10 - alpha100)
|
||||
- vDotvmcAlphal*alpha10
|
||||
)(),
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
// Under-relax the correction for all but the 1st corrector
|
||||
@ -103,8 +103,8 @@
|
||||
talphaPhiCorr.ref(),
|
||||
vDotvmcAlphal,
|
||||
(divU*alpha1 + vDotcAlphal)(),
|
||||
1,
|
||||
0
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
talphaPhi = talphaPhiCorr;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd |
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
| Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -37,7 +37,12 @@ License
|
||||
#include "fvcDiv.H"
|
||||
#include "fvcFlux.H"
|
||||
#include "fvcAverage.H"
|
||||
#include "unitConversion.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * //
|
||||
|
||||
const Foam::scalar Foam::multiphaseSystem::convertToRad =
|
||||
Foam::constant::mathematical::pi/180.0;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
@ -124,8 +129,8 @@ void Foam::multiphaseSystem::solveAlphas()
|
||||
alphaPhiCorr,
|
||||
zeroField(),
|
||||
zeroField(),
|
||||
1,
|
||||
0,
|
||||
oneField(),
|
||||
zeroField(),
|
||||
true
|
||||
);
|
||||
|
||||
@ -143,7 +148,7 @@ void Foam::multiphaseSystem::solveAlphas()
|
||||
mesh_
|
||||
),
|
||||
mesh_,
|
||||
dimensionedScalar(dimless, Zero)
|
||||
dimensionedScalar("sumAlpha", dimless, 0)
|
||||
);
|
||||
|
||||
phasei = 0;
|
||||
@ -158,9 +163,7 @@ void Foam::multiphaseSystem::solveAlphas()
|
||||
(
|
||||
geometricOneField(),
|
||||
phase,
|
||||
alphaPhi,
|
||||
zeroField(),
|
||||
zeroField()
|
||||
alphaPhi
|
||||
);
|
||||
|
||||
phase.alphaPhi() = alphaPhi;
|
||||
@ -278,7 +281,7 @@ void Foam::multiphaseSystem::correctContactAngle
|
||||
|
||||
bool matched = (tp.key().first() == phase1.name());
|
||||
|
||||
const scalar theta0 = degToRad(tp().theta0(matched));
|
||||
scalar theta0 = convertToRad*tp().theta0(matched);
|
||||
scalarField theta(boundary[patchi].size(), theta0);
|
||||
|
||||
scalar uTheta = tp().uTheta();
|
||||
@ -286,8 +289,8 @@ void Foam::multiphaseSystem::correctContactAngle
|
||||
// Calculate the dynamic contact angle if required
|
||||
if (uTheta > SMALL)
|
||||
{
|
||||
const scalar thetaA = degToRad(tp().thetaA(matched));
|
||||
const scalar thetaR = degToRad(tp().thetaR(matched));
|
||||
scalar thetaA = convertToRad*tp().thetaA(matched);
|
||||
scalar thetaR = convertToRad*tp().thetaR(matched);
|
||||
|
||||
// Calculated the component of the velocity parallel to the wall
|
||||
vectorField Uwall
|
||||
@ -391,7 +394,7 @@ Foam::multiphaseSystem::multiphaseSystem
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
mesh_,
|
||||
dimensionedScalar(dimless, Zero)
|
||||
dimensionedScalar("alphas", dimless, 0.0)
|
||||
),
|
||||
|
||||
sigmas_(lookup("sigmas")),
|
||||
@ -411,7 +414,7 @@ Foam::multiphaseSystem::multiphaseSystem
|
||||
|
||||
forAllConstIters(dragModelsDict, iter)
|
||||
{
|
||||
dragModels_.insert
|
||||
dragModels_.set
|
||||
(
|
||||
iter.key(),
|
||||
dragModel::New
|
||||
@ -419,7 +422,7 @@ Foam::multiphaseSystem::multiphaseSystem
|
||||
iter(),
|
||||
*phases_.lookup(iter.key().first()),
|
||||
*phases_.lookup(iter.key().second())
|
||||
)
|
||||
).ptr()
|
||||
);
|
||||
}
|
||||
|
||||
@ -583,7 +586,12 @@ Foam::tmp<Foam::volVectorField> Foam::multiphaseSystem::Svm
|
||||
mesh_
|
||||
),
|
||||
mesh_,
|
||||
dimensionedVector(dimensionSet(1, -2, -2, 0, 0), Zero)
|
||||
dimensionedVector
|
||||
(
|
||||
"Svm",
|
||||
dimensionSet(1, -2, -2, 0, 0),
|
||||
Zero
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
@ -636,7 +644,7 @@ Foam::tmp<Foam::volVectorField> Foam::multiphaseSystem::Svm
|
||||
Foam::autoPtr<Foam::multiphaseSystem::dragCoeffFields>
|
||||
Foam::multiphaseSystem::dragCoeffs() const
|
||||
{
|
||||
auto dragCoeffsPtr = autoPtr<dragCoeffFields>::New();
|
||||
autoPtr<dragCoeffFields> dragCoeffsPtr(new dragCoeffFields);
|
||||
|
||||
forAllConstIters(dragModels_, iter)
|
||||
{
|
||||
@ -646,8 +654,8 @@ Foam::multiphaseSystem::dragCoeffs() const
|
||||
(
|
||||
max
|
||||
(
|
||||
//fvc::average(dm.phase1()*dm.phase2()),
|
||||
//fvc::average(dm.phase1())*fvc::average(dm.phase2()),
|
||||
// fvc::average(dm.phase1()*dm.phase2()),
|
||||
// fvc::average(dm.phase1())*fvc::average(dm.phase2()),
|
||||
dm.phase1()*dm.phase2(),
|
||||
dm.residualPhaseFraction()
|
||||
)
|
||||
@ -702,7 +710,12 @@ Foam::tmp<Foam::volScalarField> Foam::multiphaseSystem::dragCoeff
|
||||
mesh_
|
||||
),
|
||||
mesh_,
|
||||
dimensionedScalar(dimensionSet(1, -3, -1, 0, 0), Zero)
|
||||
dimensionedScalar
|
||||
(
|
||||
"dragCoeff",
|
||||
dimensionSet(1, -3, -1, 0, 0),
|
||||
0
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
@ -745,7 +758,12 @@ Foam::tmp<Foam::surfaceScalarField> Foam::multiphaseSystem::surfaceTension
|
||||
mesh_
|
||||
),
|
||||
mesh_,
|
||||
dimensionedScalar(dimensionSet(1, -2, -2, 0, 0), Zero)
|
||||
dimensionedScalar
|
||||
(
|
||||
"surfaceTension",
|
||||
dimensionSet(1, -2, -2, 0, 0),
|
||||
0
|
||||
)
|
||||
)
|
||||
);
|
||||
tSurfaceTension.ref().setOriented();
|
||||
@ -789,7 +807,7 @@ Foam::multiphaseSystem::nearInterface() const
|
||||
mesh_
|
||||
),
|
||||
mesh_,
|
||||
dimensionedScalar(dimless, Zero)
|
||||
dimensionedScalar("nearInterface", dimless, 0.0)
|
||||
)
|
||||
);
|
||||
|
||||
@ -813,7 +831,7 @@ void Foam::multiphaseSystem::solve()
|
||||
const Time& runTime = mesh_.time();
|
||||
|
||||
const dictionary& alphaControls = mesh_.solverDict("alpha");
|
||||
label nAlphaSubCycles(alphaControls.get<label>("nAlphaSubCycles"));
|
||||
label nAlphaSubCycles(readLabel(alphaControls.lookup("nAlphaSubCycles")));
|
||||
|
||||
if (nAlphaSubCycles > 1)
|
||||
{
|
||||
@ -845,7 +863,7 @@ void Foam::multiphaseSystem::solve()
|
||||
mesh_
|
||||
),
|
||||
mesh_,
|
||||
dimensionedScalar(dimensionSet(0, 3, -1, 0, 0), Zero)
|
||||
dimensionedScalar("0", dimensionSet(0, 3, -1, 0, 0), 0)
|
||||
)
|
||||
);
|
||||
|
||||
@ -912,14 +930,16 @@ bool Foam::multiphaseSystem::read()
|
||||
readOK &= phase.read(phaseData[phasei++].dict());
|
||||
}
|
||||
|
||||
readEntry("sigmas", sigmas_);
|
||||
readEntry("interfaceCompression", cAlphas_);
|
||||
readEntry("virtualMass", Cvms_);
|
||||
lookup("sigmas") >> sigmas_;
|
||||
lookup("interfaceCompression") >> cAlphas_;
|
||||
lookup("virtualMass") >> Cvms_;
|
||||
|
||||
return readOK;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -76,16 +76,30 @@ public:
|
||||
{
|
||||
public:
|
||||
|
||||
struct symmHash
|
||||
class symmHash
|
||||
:
|
||||
public Hash<interfacePair>
|
||||
{
|
||||
public:
|
||||
|
||||
symmHash()
|
||||
{}
|
||||
|
||||
label operator()(const interfacePair& key) const
|
||||
{
|
||||
return word::hash()(key.first()) + word::hash()(key.second());
|
||||
}
|
||||
};
|
||||
|
||||
struct hash
|
||||
class hash
|
||||
:
|
||||
public Hash<interfacePair>
|
||||
{
|
||||
public:
|
||||
|
||||
hash()
|
||||
{}
|
||||
|
||||
label operator()(const interfacePair& key) const
|
||||
{
|
||||
return word::hash()(key.first(), word::hash()(key.second()));
|
||||
@ -95,7 +109,8 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
interfacePair() {} // = default
|
||||
interfacePair()
|
||||
{}
|
||||
|
||||
interfacePair(const word& alpha1Name, const word& alpha2Name)
|
||||
:
|
||||
@ -174,6 +189,9 @@ private:
|
||||
//- Stabilisation for normalisation of the interface normal
|
||||
const dimensionedScalar deltaN_;
|
||||
|
||||
//- Conversion factor for degrees into radians
|
||||
static const scalar convertToRad;
|
||||
|
||||
|
||||
// Private member functions
|
||||
|
||||
@ -220,7 +238,8 @@ public:
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~multiphaseSystem() = default;
|
||||
virtual ~multiphaseSystem()
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
@ -613,8 +613,8 @@ void Foam::multiphaseMixture::solveAlphas
|
||||
alphaPhiCorr,
|
||||
zeroField(),
|
||||
zeroField(),
|
||||
1,
|
||||
0,
|
||||
oneField(),
|
||||
zeroField(),
|
||||
true
|
||||
);
|
||||
|
||||
@ -648,9 +648,7 @@ void Foam::multiphaseMixture::solveAlphas
|
||||
(
|
||||
geometricOneField(),
|
||||
alpha,
|
||||
alphaPhi,
|
||||
zeroField(),
|
||||
zeroField()
|
||||
alphaPhi
|
||||
);
|
||||
|
||||
rhoPhi_ += alphaPhi*alpha.rho();
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
#!/bin/sh
|
||||
cd ${0%/*} || exit 1 # Run from this directory
|
||||
|
||||
wclean libso phaseSystems
|
||||
wclean libso interfacialModels
|
||||
wclean libso interfacialCompositionModels
|
||||
reactingTwoPhaseEulerFoam/Allwclean
|
||||
reactingMultiphaseEulerFoam/Allwclean
|
||||
wclean reactingTwoPhaseEulerFoam
|
||||
wclean reactingMultiphaseEulerFoam
|
||||
wclean libso functionObjects
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -4,12 +4,8 @@ cd ${0%/*} || exit 1 # Run from this directory
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
wmakeLnInclude interfacialModels
|
||||
wmakeLnInclude interfacialCompositionModels
|
||||
wmake $targetType phaseSystems
|
||||
wmake $targetType interfacialModels
|
||||
wmake $targetType interfacialCompositionModels
|
||||
reactingTwoPhaseEulerFoam/Allwmake $targetType $*
|
||||
reactingMultiphaseEulerFoam/Allwmake $targetType $*
|
||||
wmake $targetType functionObjects
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
sizeDistribution/sizeDistribution.C
|
||||
phaseForces/phaseForces.C
|
||||
|
||||
LIB = $(FOAM_LIBBIN)/libreactingEulerFoamFunctionObjects
|
||||
@ -0,0 +1,11 @@
|
||||
EXE_INC = \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
|
||||
-I$(LIB_SRC)/transportModels/compressible/lnInclude \
|
||||
-I$(LIB_SRC)/functionObjects/field/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/interfacialModels/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/phaseSystems/lnInclude
|
||||
|
||||
LIB_LIBS = \
|
||||
-lfieldFunctionObjects \
|
||||
-lfiniteVolume
|
||||
@ -0,0 +1,306 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2018-2019 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "phaseForces.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "BlendedInterfacialModel.H"
|
||||
#include "dragModel.H"
|
||||
#include "virtualMassModel.H"
|
||||
#include "liftModel.H"
|
||||
#include "wallLubricationModel.H"
|
||||
#include "turbulentDispersionModel.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace functionObjects
|
||||
{
|
||||
defineTypeNameAndDebug(phaseForces, 0);
|
||||
addToRunTimeSelectionTable(functionObject, phaseForces, dictionary);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class modelType>
|
||||
Foam::tmp<Foam::volVectorField>
|
||||
Foam::functionObjects::phaseForces::nonDragForce(const phasePair& pair) const
|
||||
{
|
||||
const BlendedInterfacialModel<modelType>& model =
|
||||
fluid_.lookupBlendedSubModel<modelType>(pair);
|
||||
|
||||
if (&pair.phase1() == &phase_)
|
||||
{
|
||||
return model.template F<vector>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return -model.template F<vector>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::functionObjects::phaseForces::phaseForces
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
fvMeshFunctionObject(name, runTime, dict),
|
||||
phase_
|
||||
(
|
||||
mesh_.lookupObject<phaseModel>
|
||||
(
|
||||
IOobject::groupName("alpha", dict.get<word>("phase"))
|
||||
)
|
||||
),
|
||||
fluid_(mesh_.lookupObject<phaseSystem>("phaseProperties"))
|
||||
{
|
||||
read(dict);
|
||||
|
||||
forAllConstIter
|
||||
(
|
||||
phaseSystem::phasePairTable,
|
||||
fluid_.phasePairs(),
|
||||
iter
|
||||
)
|
||||
{
|
||||
const phasePair& pair = iter();
|
||||
|
||||
if (pair.contains(phase_) && !pair.ordered())
|
||||
{
|
||||
if (fluid_.foundBlendedSubModel<dragModel>(pair))
|
||||
{
|
||||
forceFields_.set
|
||||
(
|
||||
dragModel::typeName,
|
||||
new volVectorField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName("dragForce", phase_.name()),
|
||||
mesh_.time().timeName(),
|
||||
mesh_
|
||||
),
|
||||
mesh_,
|
||||
dimensionedVector(dimForce/dimVolume)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (fluid_.foundBlendedSubModel<virtualMassModel>(pair))
|
||||
{
|
||||
forceFields_.set
|
||||
(
|
||||
virtualMassModel::typeName,
|
||||
new volVectorField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName
|
||||
(
|
||||
"virtualMassForce",
|
||||
phase_.name()
|
||||
),
|
||||
mesh_.time().timeName(),
|
||||
mesh_
|
||||
),
|
||||
mesh_,
|
||||
dimensionedVector(dimForce/dimVolume)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (fluid_.foundBlendedSubModel<liftModel>(pair))
|
||||
{
|
||||
forceFields_.set
|
||||
(
|
||||
liftModel::typeName,
|
||||
new volVectorField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName("liftForce", phase_.name()),
|
||||
mesh_.time().timeName(),
|
||||
mesh_
|
||||
),
|
||||
mesh_,
|
||||
dimensionedVector(dimForce/dimVolume)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (fluid_.foundBlendedSubModel<wallLubricationModel>(pair))
|
||||
{
|
||||
forceFields_.set
|
||||
(
|
||||
wallLubricationModel::typeName,
|
||||
new volVectorField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName
|
||||
(
|
||||
"wallLubricationForce",
|
||||
phase_.name()
|
||||
),
|
||||
mesh_.time().timeName(),
|
||||
mesh_
|
||||
),
|
||||
mesh_,
|
||||
dimensionedVector(dimForce/dimVolume)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (fluid_.foundBlendedSubModel<turbulentDispersionModel>(pair))
|
||||
{
|
||||
forceFields_.set
|
||||
(
|
||||
turbulentDispersionModel::typeName,
|
||||
new volVectorField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName
|
||||
(
|
||||
"turbulentDispersionForce",
|
||||
phase_.name()
|
||||
),
|
||||
mesh_.time().timeName(),
|
||||
mesh_
|
||||
),
|
||||
mesh_,
|
||||
dimensionedVector(dimForce/dimVolume)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::functionObjects::phaseForces::~phaseForces()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::functionObjects::phaseForces::read(const dictionary& dict)
|
||||
{
|
||||
fvMeshFunctionObject::read(dict);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::phaseForces::execute()
|
||||
{
|
||||
forAllIter
|
||||
(
|
||||
HashPtrTable<volVectorField>,
|
||||
forceFields_,
|
||||
iter
|
||||
)
|
||||
{
|
||||
const word& type = iter.key();
|
||||
volVectorField& force = *iter();
|
||||
|
||||
force *= 0.0;
|
||||
|
||||
forAllConstIter
|
||||
(
|
||||
phaseSystem::phasePairTable,
|
||||
fluid_.phasePairs(),
|
||||
iter2
|
||||
)
|
||||
{
|
||||
const phasePair& pair = iter2();
|
||||
|
||||
if (pair.contains(phase_) && !pair.ordered())
|
||||
{
|
||||
if (type == "dragModel")
|
||||
{
|
||||
force +=
|
||||
fluid_.lookupBlendedSubModel<dragModel>(pair).K()
|
||||
*(pair.otherPhase(phase_).U() - phase_.U());
|
||||
}
|
||||
|
||||
if (type == "virtualMassModel")
|
||||
{
|
||||
force +=
|
||||
fluid_.lookupBlendedSubModel<virtualMassModel>(pair).K()
|
||||
*(
|
||||
pair.otherPhase(phase_).DUDt()
|
||||
- phase_.DUDt()
|
||||
);
|
||||
}
|
||||
|
||||
if (type == "liftModel")
|
||||
{
|
||||
force = nonDragForce<liftModel>(pair);
|
||||
}
|
||||
|
||||
if (type == "wallLubricationModel")
|
||||
{
|
||||
force = nonDragForce<wallLubricationModel>(pair);
|
||||
}
|
||||
|
||||
if (type == "turbulentDispersionModel")
|
||||
{
|
||||
force = nonDragForce<turbulentDispersionModel>(pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::phaseForces::write()
|
||||
{
|
||||
forAllIter
|
||||
(
|
||||
HashPtrTable<volVectorField>,
|
||||
forceFields_,
|
||||
iter
|
||||
)
|
||||
{
|
||||
writeObject(iter()->name());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,163 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::functionObjects::phaseForces
|
||||
|
||||
Description
|
||||
This function object calculates and outputs the blended interfacial forces
|
||||
acting on a given phase, i.e. drag, virtual mass, lift, wall-lubrication and
|
||||
turbulent dispersion. Note that it works only in run-time processing mode
|
||||
and in combination with the reactingEulerFoam solvers.
|
||||
|
||||
For a simulation involving more than two phases, the accumulated force is
|
||||
calculated by looping over all phasePairs involving that phase. The fields
|
||||
are stored in the database so that they can be processed further, e.g. with
|
||||
the fieldAveraging functionObject.
|
||||
|
||||
Example of function object specification:
|
||||
\verbatim
|
||||
phaseForces.water
|
||||
{
|
||||
type phaseForces;
|
||||
libs ("libreactingEulerFoamFunctionObjects.so");
|
||||
writeControl writeTime;
|
||||
writeInterval 1;
|
||||
|
||||
...
|
||||
|
||||
phaseName water;
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Usage
|
||||
\table
|
||||
Property | Description | Required | Default value
|
||||
type | type name: phaseForces | yes |
|
||||
phaseName | Name of evaluated phase | yes |
|
||||
\endtable
|
||||
|
||||
See also
|
||||
Foam::BlendedInterfacialModel
|
||||
Foam::functionObjects::fvMeshFunctionObject
|
||||
Foam::functionObject
|
||||
|
||||
SourceFiles
|
||||
phaseForces.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef functionObjects_phaseForces_H
|
||||
#define functionObjects_phaseForces_H
|
||||
|
||||
#include "fvMeshFunctionObject.H"
|
||||
#include "phaseSystem.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace functionObjects
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class phaseForces Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class phaseForces
|
||||
:
|
||||
public fvMeshFunctionObject
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
phaseForces(const phaseForces&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const phaseForces&);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
HashPtrTable<volVectorField> forceFields_;
|
||||
|
||||
//- Phase for which forces are evaluated
|
||||
const phaseModel& phase_;
|
||||
|
||||
//- Constant access to phaseSystem
|
||||
const phaseSystem& fluid_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Evaluate and return non-drag force
|
||||
template<class modelType>
|
||||
tmp<volVectorField> nonDragForce(const phasePair& key) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("phaseForces");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from Time and dictionary
|
||||
phaseForces
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary&
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~phaseForces();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Read the input data
|
||||
virtual bool read(const dictionary& dict);
|
||||
|
||||
//- Calculate the force fields
|
||||
virtual bool execute();
|
||||
|
||||
//- Write the force fields
|
||||
virtual bool write();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace functionObjects
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,585 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2017-2019 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "sizeDistribution.H"
|
||||
#include "sizeGroup.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace functionObjects
|
||||
{
|
||||
defineTypeNameAndDebug(sizeDistribution, 0);
|
||||
addToRunTimeSelectionTable(functionObject, sizeDistribution, dictionary);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const Foam::Enum
|
||||
<
|
||||
Foam::functionObjects::sizeDistribution::selectionModeTypes
|
||||
>
|
||||
Foam::functionObjects::sizeDistribution::selectionModeTypeNames_
|
||||
({
|
||||
{selectionModeTypes::rtCellZone, "cellZone"},
|
||||
{selectionModeTypes::rtAll, "all"},
|
||||
});
|
||||
|
||||
|
||||
const Foam::Enum
|
||||
<
|
||||
Foam::functionObjects::sizeDistribution::functionTypes
|
||||
>
|
||||
Foam::functionObjects::sizeDistribution::functionTypeNames_
|
||||
({
|
||||
{functionTypes::ftNdf, "numberDensity"},
|
||||
{functionTypes::ftVdf, "volumeDensity"},
|
||||
{functionTypes::ftNc, "numberConcentration"},
|
||||
{functionTypes::ftMom, "moments"},
|
||||
});
|
||||
|
||||
|
||||
const Foam::Enum
|
||||
<
|
||||
Foam::functionObjects::sizeDistribution::abszissaTypes
|
||||
>
|
||||
Foam::functionObjects::sizeDistribution::abszissaTypeNames_
|
||||
({
|
||||
|
||||
{abszissaTypes::atDiameter, "diameter"},
|
||||
{abszissaTypes::atVolume, "volume"},
|
||||
});
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::functionObjects::sizeDistribution::initialise
|
||||
(
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
switch (functionType_)
|
||||
{
|
||||
case ftNdf:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case ftVdf:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case ftNc:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case ftMom:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< "Unknown functionType. Valid types are:"
|
||||
<< functionTypeNames_ << nl << exit(FatalIOError);
|
||||
}
|
||||
}
|
||||
|
||||
switch (abszissaType_)
|
||||
{
|
||||
case atDiameter:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case atVolume:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< "Unknown abszissaType. Valid types are:"
|
||||
<< abszissaTypeNames_ << nl << exit(FatalIOError);
|
||||
}
|
||||
}
|
||||
|
||||
setCellZoneCells();
|
||||
|
||||
if (nCells_ == 0)
|
||||
{
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< type() << " " << name() << ": "
|
||||
<< selectionModeTypeNames_[selectionModeType_]
|
||||
<< "(" << selectionModeTypeName_ << "):" << nl
|
||||
<< " Selection has no cells" << exit(FatalIOError);
|
||||
}
|
||||
|
||||
volume_ = volume();
|
||||
|
||||
Info<< type() << " " << name() << ":"
|
||||
<< selectionModeTypeNames_[selectionModeType_]
|
||||
<< "(" << selectionModeTypeName_ << "):" << nl
|
||||
<< " total cells = " << nCells_ << nl
|
||||
<< " total volume = " << volume_
|
||||
<< nl << endl;
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::sizeDistribution::setCellZoneCells()
|
||||
{
|
||||
switch (selectionModeType_)
|
||||
{
|
||||
case rtCellZone:
|
||||
{
|
||||
dict().lookup("cellZone") >> selectionModeTypeName_;
|
||||
|
||||
label zoneId =
|
||||
mesh().cellZones().findZoneID(selectionModeTypeName_);
|
||||
|
||||
if (zoneId < 0)
|
||||
{
|
||||
FatalIOErrorInFunction(dict_)
|
||||
<< "Unknown cellZone name: " << selectionModeTypeName_
|
||||
<< ". Valid cellZone names are: "
|
||||
<< mesh().cellZones().names()
|
||||
<< nl << exit(FatalIOError);
|
||||
}
|
||||
|
||||
cellId_ = mesh().cellZones()[zoneId];
|
||||
nCells_ = returnReduce(cellId_.size(), sumOp<label>());
|
||||
break;
|
||||
}
|
||||
|
||||
case rtAll:
|
||||
{
|
||||
cellId_ = identity(mesh().nCells());
|
||||
nCells_ = returnReduce(cellId_.size(), sumOp<label>());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
FatalIOErrorInFunction(dict_)
|
||||
<< "Unknown selectionMode type. Valid selectionMode types are:"
|
||||
<< selectionModeTypeNames_ << nl << exit(FatalIOError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::scalar Foam::functionObjects::sizeDistribution::volume() const
|
||||
{
|
||||
return gSum(filterField(mesh().V()));
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::sizeDistribution::combineFields(scalarField& field)
|
||||
{
|
||||
List<scalarField> allValues(Pstream::nProcs());
|
||||
|
||||
allValues[Pstream::myProcNo()] = field;
|
||||
|
||||
Pstream::gatherList(allValues);
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
field =
|
||||
ListListOps::combine<scalarField>
|
||||
(
|
||||
allValues,
|
||||
accessOp<scalarField>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::scalarField>
|
||||
Foam::functionObjects::sizeDistribution::filterField
|
||||
(
|
||||
const scalarField& field
|
||||
) const
|
||||
{
|
||||
return tmp<scalarField>(new scalarField(field, cellId_));
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::sizeDistribution::writeFileHeader
|
||||
(
|
||||
const label i
|
||||
)
|
||||
{
|
||||
OFstream& file = this->file();
|
||||
|
||||
switch (functionType_)
|
||||
{
|
||||
case ftNdf:
|
||||
{
|
||||
writeHeader(file, "Number density function");
|
||||
break;
|
||||
}
|
||||
|
||||
case ftVdf:
|
||||
{
|
||||
writeHeader(file, "Volume density function");
|
||||
break;
|
||||
}
|
||||
|
||||
case ftNc:
|
||||
{
|
||||
writeHeader(file, "Number concentration");
|
||||
break;
|
||||
}
|
||||
|
||||
case ftMom:
|
||||
{
|
||||
writeHeader(file, "Moments");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (abszissaType_)
|
||||
{
|
||||
case atVolume:
|
||||
{
|
||||
writeCommented(file, "Time/volume");
|
||||
break;
|
||||
}
|
||||
|
||||
case atDiameter:
|
||||
{
|
||||
writeCommented(file, "Time/diameter");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (functionType_)
|
||||
{
|
||||
case ftMom:
|
||||
{
|
||||
for (label i = 0; i <= momentOrder_; i++)
|
||||
{
|
||||
file() << tab << i;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
forAll(popBal_.sizeGroups(), sizeGroupi)
|
||||
{
|
||||
const diameterModels::sizeGroup& fi =
|
||||
popBal_.sizeGroups()[sizeGroupi];
|
||||
|
||||
switch (abszissaType_)
|
||||
{
|
||||
case atDiameter:
|
||||
{
|
||||
file() << tab << fi.d().value();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case atVolume:
|
||||
{
|
||||
file() << tab << fi.x().value();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
file << endl;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::functionObjects::sizeDistribution::sizeDistribution
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
fvMeshFunctionObject(name, runTime, dict),
|
||||
writeFile(obr_, name),
|
||||
dict_(dict),
|
||||
selectionModeType_
|
||||
(
|
||||
selectionModeTypeNames_.get("selectionMode", dict)
|
||||
),
|
||||
selectionModeTypeName_(word::null),
|
||||
functionType_(functionTypeNames_.get("functionType", dict)),
|
||||
abszissaType_(abszissaTypeNames_.get("abszissaType", dict)),
|
||||
nCells_(0),
|
||||
cellId_(),
|
||||
volume_(0.0),
|
||||
writeVolume_(dict.lookupOrDefault("writeVolume", false)),
|
||||
popBal_
|
||||
(
|
||||
obr_.lookupObject<Foam::diameterModels::populationBalanceModel>
|
||||
(
|
||||
dict.get<word>("populationBalance")
|
||||
)
|
||||
),
|
||||
N_(popBal_.sizeGroups().size()),
|
||||
momentOrder_(dict.lookupOrDefault<label>("momentOrder", 0)),
|
||||
normalize_(dict.lookupOrDefault("normalize", false)),
|
||||
sumN_(0.0),
|
||||
sumV_(0.0)
|
||||
{
|
||||
read(dict);
|
||||
resetFile(name);
|
||||
createFile(name);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::functionObjects::sizeDistribution::~sizeDistribution()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::functionObjects::sizeDistribution::read(const dictionary& dict)
|
||||
{
|
||||
if (dict != dict_)
|
||||
{
|
||||
dict_ = dict;
|
||||
}
|
||||
|
||||
fvMeshFunctionObject::read(dict);
|
||||
writeFile::read(dict);
|
||||
|
||||
initialise(dict);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::sizeDistribution::execute()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::sizeDistribution::write()
|
||||
{
|
||||
writeFileHeader();
|
||||
writeTime(file());
|
||||
|
||||
Log << type() << " " << name() << " write" << nl;
|
||||
|
||||
scalarField V(filterField(mesh().V()));
|
||||
combineFields(V);
|
||||
|
||||
sumN_ = 0;
|
||||
sumV_ = 0;
|
||||
|
||||
forAll(N_, i)
|
||||
{
|
||||
const Foam::diameterModels::sizeGroup& fi = popBal_.sizeGroups()[i];
|
||||
|
||||
const volScalarField& alpha = fi.VelocityGroup().phase();
|
||||
|
||||
scalarField Ni(fi*alpha/fi.x());
|
||||
scalarField values(filterField(Ni));
|
||||
scalarField V(filterField(mesh().V()));
|
||||
|
||||
// Combine onto master
|
||||
combineFields(values);
|
||||
combineFields(V);
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
// Calculate volume-averaged number concentration
|
||||
N_[i] = sum(V*values)/sum(V);
|
||||
}
|
||||
|
||||
sumN_ += N_[i];
|
||||
|
||||
sumV_ += N_[i]*fi.x().value();
|
||||
}
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
switch (functionType_)
|
||||
{
|
||||
case ftMom:
|
||||
{
|
||||
for (label m = 0; m <= momentOrder_; m++)
|
||||
{
|
||||
scalar result(0.0);
|
||||
|
||||
forAll(N_, i)
|
||||
{
|
||||
const Foam::diameterModels::sizeGroup& fi =
|
||||
popBal_.sizeGroups()[i];
|
||||
|
||||
switch (abszissaType_)
|
||||
{
|
||||
case atVolume:
|
||||
{
|
||||
result += pow(fi.x().value(), m)*N_[i];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case atDiameter:
|
||||
{
|
||||
result += pow(fi.d().value(), m)*N_[i];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file() << tab << result;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
forAll(popBal_.sizeGroups(), i)
|
||||
{
|
||||
const Foam::diameterModels::sizeGroup& fi =
|
||||
popBal_.sizeGroups()[i];
|
||||
|
||||
scalar result(0.0);
|
||||
scalar delta(0.0);
|
||||
|
||||
switch (abszissaType_)
|
||||
{
|
||||
case atVolume:
|
||||
{
|
||||
delta = popBal_.v()[i+1].value()
|
||||
- popBal_.v()[i].value();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case atDiameter:
|
||||
{
|
||||
const scalar& formFactor =
|
||||
fi.VelocityGroup().formFactor().value();
|
||||
|
||||
delta =
|
||||
pow
|
||||
(
|
||||
popBal_.v()[i+1].value()
|
||||
/formFactor,
|
||||
1.0/3.0
|
||||
)
|
||||
- pow
|
||||
(
|
||||
popBal_.v()[i].value()
|
||||
/formFactor,
|
||||
1.0/3.0
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (functionType_)
|
||||
{
|
||||
case ftNdf:
|
||||
{
|
||||
if (normalize_ == true)
|
||||
{
|
||||
result = N_[i]/delta/sumN_;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = N_[i]/delta;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ftVdf:
|
||||
{
|
||||
if (normalize_ == true)
|
||||
{
|
||||
result = N_[i]*fi.x().value()/delta/sumV_;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = N_[i]*fi.x().value()/delta;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ftNc:
|
||||
{
|
||||
if (normalize_ == true)
|
||||
{
|
||||
result = N_[i]/sumN_;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = N_[i];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
file()<< tab << result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
file()<< endl;
|
||||
}
|
||||
|
||||
Log << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,277 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2017-2019 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::functionObjects::sizeDistribution
|
||||
|
||||
Description
|
||||
This function object calculates and outputs information about the size
|
||||
distribution of the dispersed phase, such as the number density function or
|
||||
its moments. It is designed to be used exclusively with the population
|
||||
balance modeling functionality of the reactingEulerFoam solvers. It can be
|
||||
applied to a specific cellZone or the entire domain.
|
||||
|
||||
Example of function object specification:
|
||||
\verbatim
|
||||
box.all.numberDensity.volume.bubbles
|
||||
{
|
||||
type sizeDistribution;
|
||||
libs ("libreactingEulerFoamFunctionObjects.so");
|
||||
writeControl outputTime;
|
||||
writeInterval 1;
|
||||
log true;
|
||||
...
|
||||
functionType numberDensity;
|
||||
abszissaType volume;
|
||||
selectionMode all;
|
||||
populationBalanceModel bubbles;
|
||||
normalize true;
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Usage
|
||||
\table
|
||||
Property | Description | Required | Default value
|
||||
type | type name: sizeDistribution | yes |
|
||||
functionType | numberDensity, volumeDensity, numberConcentration,
|
||||
moments | yes |
|
||||
abszissaType | volume, diameter | yes |
|
||||
momentOrder | Write moment up to given order | no | 0
|
||||
selectionMode | Evaluate for cellZone or entire mesh | yes |
|
||||
cellZone | Required if selectionMode is cellZone | |
|
||||
populationBalanceModel | Respective populationBalanceModel | yes |
|
||||
normalize | Normalization | no |
|
||||
\endtable
|
||||
|
||||
See also
|
||||
Foam::diameterModels::populationBalanceModel
|
||||
Foam::functionObject
|
||||
Foam::functionObjects::fvMeshFunctionObject
|
||||
Foam::functionObjects::writeFile
|
||||
|
||||
SourceFiles
|
||||
sizeDistribution.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef functionObjects_sizeDistribution_H
|
||||
#define functionObjects_sizeDistribution_H
|
||||
|
||||
#include "fvMeshFunctionObject.H"
|
||||
#include "writeFile.H"
|
||||
#include "populationBalanceModel.H"
|
||||
#include "Enum.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
class fvMesh;
|
||||
|
||||
namespace functionObjects
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class sizeDistribution Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class sizeDistribution
|
||||
:
|
||||
public fvMeshFunctionObject,
|
||||
public writeFile
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Public data types
|
||||
|
||||
//- Selection mode type enumeration
|
||||
enum selectionModeTypes
|
||||
{
|
||||
rtCellZone,
|
||||
rtAll
|
||||
};
|
||||
|
||||
//- Selection mode type names
|
||||
static const Enum<selectionModeTypes> selectionModeTypeNames_;
|
||||
|
||||
|
||||
//- Function type enumeration
|
||||
enum functionTypes
|
||||
{
|
||||
ftNdf,
|
||||
ftVdf,
|
||||
ftNc,
|
||||
ftMom
|
||||
};
|
||||
|
||||
//- Function type names
|
||||
static const Enum<functionTypes> functionTypeNames_;
|
||||
|
||||
|
||||
//- abszissa type enumeration
|
||||
enum abszissaTypes
|
||||
{
|
||||
atDiameter,
|
||||
atVolume,
|
||||
};
|
||||
|
||||
//- Abszissa type names
|
||||
static const Enum<abszissaTypes> abszissaTypeNames_;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Construction dictionary
|
||||
dictionary dict_;
|
||||
|
||||
//- Selection mode type
|
||||
selectionModeTypes selectionModeType_;
|
||||
|
||||
//- Name of selection
|
||||
word selectionModeTypeName_;
|
||||
|
||||
//- Function type
|
||||
functionTypes functionType_;
|
||||
|
||||
//- Abszissa type
|
||||
abszissaTypes abszissaType_;
|
||||
|
||||
//- Global number of cells
|
||||
label nCells_;
|
||||
|
||||
//- Local list of cell IDs
|
||||
labelList cellId_;
|
||||
|
||||
//- Total volume of the evaluated selection
|
||||
scalar volume_;
|
||||
|
||||
//- Optionally write the volume of the sizeDistribution
|
||||
bool writeVolume_;
|
||||
|
||||
//- PopulationBalance
|
||||
const Foam::diameterModels::populationBalanceModel& popBal_;
|
||||
|
||||
//- Number concentrations
|
||||
List<scalar> N_;
|
||||
|
||||
//- Write moments up to specified order with respect to abszissaType
|
||||
label momentOrder_;
|
||||
|
||||
//- Normalization switch
|
||||
const Switch normalize_;
|
||||
|
||||
//- Sum of number concentrations
|
||||
scalar sumN_;
|
||||
|
||||
//- Volumertic sum
|
||||
scalar sumV_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Initialise, e.g. cell addressing
|
||||
void initialise(const dictionary& dict);
|
||||
|
||||
//- Set cells to evaluate based on a cell zone
|
||||
void setCellZoneCells();
|
||||
|
||||
//- Calculate and return volume of the evaluated cell zone
|
||||
scalar volume() const;
|
||||
|
||||
//- Combine fields from all processor domains into single field
|
||||
void combineFields(scalarField& field);
|
||||
|
||||
//- Filter field according to cellIds
|
||||
tmp<scalarField> filterField(const scalarField& field) const;
|
||||
|
||||
//- Output file header information
|
||||
void writeFileHeader(const label i = 0);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("sizeDistribution");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from Time and dictionary
|
||||
sizeDistribution
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~sizeDistribution();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return the reference to the construction dictionary
|
||||
const dictionary& dict() const
|
||||
{
|
||||
return dict_;
|
||||
}
|
||||
|
||||
//- Return the local list of cell IDs
|
||||
const labelList& cellId() const
|
||||
{
|
||||
return cellId_;
|
||||
}
|
||||
|
||||
//- Helper function to return the reference to the mesh
|
||||
const fvMesh& mesh() const
|
||||
{
|
||||
return refCast<const fvMesh>(obr_);
|
||||
}
|
||||
|
||||
//- Read from dictionary
|
||||
virtual bool read(const dictionary& dict);
|
||||
|
||||
//- Execute
|
||||
virtual bool execute();
|
||||
|
||||
//- Write
|
||||
virtual bool write();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace functionObjects
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,120 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd |
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2015-2017 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "interfaceCompositionModel.H"
|
||||
#include "InterfaceCompositionModel.H"
|
||||
#include "Henry.H"
|
||||
#include "NonRandomTwoLiquid.H"
|
||||
#include "Raoult.H"
|
||||
#include "Saturated.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "makeReactionThermo.H"
|
||||
|
||||
#include "thermoPhysicsTypes.H"
|
||||
|
||||
#include "rhoConst.H"
|
||||
#include "perfectFluid.H"
|
||||
|
||||
#include "pureMixture.H"
|
||||
#include "multiComponentMixture.H"
|
||||
#include "reactingMixture.H"
|
||||
#include "SpecieMixture.H"
|
||||
|
||||
#include "rhoThermo.H"
|
||||
#include "rhoReactionThermo.H"
|
||||
#include "heRhoThermo.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
using namespace interfaceCompositionModels;
|
||||
|
||||
// multi-component gas in the presence of a pure liquid
|
||||
makeInterfaceCompositionType
|
||||
(
|
||||
Saturated,
|
||||
heRhoThermo,
|
||||
rhoReactionThermo,
|
||||
multiComponentMixture,
|
||||
gasEThermoPhysics,
|
||||
heRhoThermo,
|
||||
rhoThermo,
|
||||
pureMixture,
|
||||
constFluidEThermoPhysics
|
||||
);
|
||||
|
||||
// reacting gas in the presence of a pure liquid
|
||||
makeInterfaceCompositionType
|
||||
(
|
||||
Saturated,
|
||||
heRhoThermo,
|
||||
rhoReactionThermo,
|
||||
reactingMixture,
|
||||
gasEThermoPhysics,
|
||||
heRhoThermo,
|
||||
rhoThermo,
|
||||
pureMixture,
|
||||
constFluidEThermoPhysics
|
||||
);
|
||||
|
||||
// multi-component gas in the presence of a multi-component liquid
|
||||
makeSpecieInterfaceCompositionType
|
||||
(
|
||||
Saturated,
|
||||
heRhoThermo,
|
||||
rhoReactionThermo,
|
||||
multiComponentMixture,
|
||||
constGasEThermoPhysics,
|
||||
heRhoThermo,
|
||||
rhoReactionThermo,
|
||||
multiComponentMixture,
|
||||
constFluidEThermoPhysics
|
||||
);
|
||||
|
||||
// multi-component liquid in the presence of a multi-component gas
|
||||
makeSpecieInterfaceCompositionType
|
||||
(
|
||||
Henry,
|
||||
heRhoThermo,
|
||||
rhoReactionThermo,
|
||||
multiComponentMixture,
|
||||
constFluidEThermoPhysics,
|
||||
heRhoThermo,
|
||||
rhoReactionThermo,
|
||||
multiComponentMixture,
|
||||
constGasEThermoPhysics
|
||||
);
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,550 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd |
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2014-2016 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "BlendedInterfacialModel.H"
|
||||
#include "fixedValueFvsPatchFields.H"
|
||||
#include "surfaceInterpolate.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class ModelType>
|
||||
template<class GeometricField>
|
||||
void Foam::BlendedInterfacialModel<ModelType>::correctFixedFluxBCs
|
||||
(
|
||||
GeometricField& field
|
||||
) const
|
||||
{
|
||||
typename GeometricField::Boundary& fieldBf =
|
||||
field.boundaryFieldRef();
|
||||
|
||||
forAll(phase1_.phi()().boundaryField(), patchi)
|
||||
{
|
||||
if
|
||||
(
|
||||
isA<fixedValueFvsPatchScalarField>
|
||||
(
|
||||
phase1_.phi()().boundaryField()[patchi]
|
||||
)
|
||||
)
|
||||
{
|
||||
fieldBf[patchi] = Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class ModelType>
|
||||
Foam::BlendedInterfacialModel<ModelType>::BlendedInterfacialModel
|
||||
(
|
||||
const phaseModel& phase1,
|
||||
const phaseModel& phase2,
|
||||
const blendingMethod& blending,
|
||||
autoPtr<ModelType> model,
|
||||
autoPtr<ModelType> model1In2,
|
||||
autoPtr<ModelType> model2In1,
|
||||
const bool correctFixedFluxBCs
|
||||
)
|
||||
:
|
||||
phase1_(phase1),
|
||||
phase2_(phase2),
|
||||
blending_(blending),
|
||||
model_(model),
|
||||
model1In2_(model1In2),
|
||||
model2In1_(model2In1),
|
||||
correctFixedFluxBCs_(correctFixedFluxBCs)
|
||||
{}
|
||||
|
||||
|
||||
template<class ModelType>
|
||||
Foam::BlendedInterfacialModel<ModelType>::BlendedInterfacialModel
|
||||
(
|
||||
const phasePair::dictTable& modelTable,
|
||||
const blendingMethod& blending,
|
||||
const phasePair& pair,
|
||||
const orderedPhasePair& pair1In2,
|
||||
const orderedPhasePair& pair2In1,
|
||||
const bool correctFixedFluxBCs
|
||||
)
|
||||
:
|
||||
phase1_(pair.phase1()),
|
||||
phase2_(pair.phase2()),
|
||||
blending_(blending),
|
||||
correctFixedFluxBCs_(correctFixedFluxBCs)
|
||||
{
|
||||
if (modelTable.found(pair))
|
||||
{
|
||||
model_.set
|
||||
(
|
||||
ModelType::New
|
||||
(
|
||||
modelTable[pair],
|
||||
pair
|
||||
).ptr()
|
||||
);
|
||||
}
|
||||
|
||||
if (modelTable.found(pair1In2))
|
||||
{
|
||||
model1In2_.set
|
||||
(
|
||||
ModelType::New
|
||||
(
|
||||
modelTable[pair1In2],
|
||||
pair1In2
|
||||
).ptr()
|
||||
);
|
||||
}
|
||||
|
||||
if (modelTable.found(pair2In1))
|
||||
{
|
||||
model2In1_.set
|
||||
(
|
||||
ModelType::New
|
||||
(
|
||||
modelTable[pair2In1],
|
||||
pair2In1
|
||||
).ptr()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class ModelType>
|
||||
Foam::BlendedInterfacialModel<ModelType>::~BlendedInterfacialModel()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
template<class ModelType>
|
||||
bool Foam::BlendedInterfacialModel<ModelType>::hasModel
|
||||
(
|
||||
const class phaseModel& phase
|
||||
) const
|
||||
{
|
||||
return
|
||||
&phase == &(phase1_)
|
||||
? model1In2_.valid()
|
||||
: model2In1_.valid();
|
||||
}
|
||||
|
||||
|
||||
template<class ModelType>
|
||||
const ModelType& Foam::BlendedInterfacialModel<ModelType>::model
|
||||
(
|
||||
const class phaseModel& phase
|
||||
) const
|
||||
{
|
||||
return &phase == &(phase1_) ? model1In2_ : model2In1_;
|
||||
}
|
||||
|
||||
|
||||
template<class ModelType>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::BlendedInterfacialModel<ModelType>::K() const
|
||||
{
|
||||
tmp<volScalarField> f1, f2;
|
||||
|
||||
if (model_.valid() || model1In2_.valid())
|
||||
{
|
||||
f1 = blending_.f1(phase1_, phase2_);
|
||||
}
|
||||
|
||||
if (model_.valid() || model2In1_.valid())
|
||||
{
|
||||
f2 = blending_.f2(phase1_, phase2_);
|
||||
}
|
||||
|
||||
tmp<volScalarField> x
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
ModelType::typeName + ":K",
|
||||
phase1_.mesh().time().timeName(),
|
||||
phase1_.mesh(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
phase1_.mesh(),
|
||||
dimensionedScalar(ModelType::dimK, Zero)
|
||||
)
|
||||
);
|
||||
|
||||
if (model_.valid())
|
||||
{
|
||||
x.ref() += model_->K()*(scalar(1) - f1() - f2());
|
||||
}
|
||||
if (model1In2_.valid())
|
||||
{
|
||||
x.ref() += model1In2_->K()*f1;
|
||||
}
|
||||
if (model2In1_.valid())
|
||||
{
|
||||
x.ref() += model2In1_->K()*f2;
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
correctFixedFluxBCs_
|
||||
&& (model_.valid() || model1In2_.valid() || model2In1_.valid())
|
||||
)
|
||||
{
|
||||
correctFixedFluxBCs(x.ref());
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
template<class ModelType>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::BlendedInterfacialModel<ModelType>::K(const scalar residualAlpha) const
|
||||
{
|
||||
tmp<volScalarField> f1, f2;
|
||||
|
||||
if (model_.valid() || model1In2_.valid())
|
||||
{
|
||||
f1 = blending_.f1(phase1_, phase2_);
|
||||
}
|
||||
|
||||
if (model_.valid() || model2In1_.valid())
|
||||
{
|
||||
f2 = blending_.f2(phase1_, phase2_);
|
||||
}
|
||||
|
||||
tmp<volScalarField> x
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
ModelType::typeName + ":K",
|
||||
phase1_.mesh().time().timeName(),
|
||||
phase1_.mesh(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
phase1_.mesh(),
|
||||
dimensionedScalar(ModelType::dimK, Zero)
|
||||
)
|
||||
);
|
||||
|
||||
if (model_.valid())
|
||||
{
|
||||
x.ref() += model_->K(residualAlpha)*(scalar(1) - f1() - f2());
|
||||
}
|
||||
if (model1In2_.valid())
|
||||
{
|
||||
x.ref() += model1In2_->K(residualAlpha)*f1;
|
||||
}
|
||||
if (model2In1_.valid())
|
||||
{
|
||||
x.ref() += model2In1_->K(residualAlpha)*f2;
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
correctFixedFluxBCs_
|
||||
&& (model_.valid() || model1In2_.valid() || model2In1_.valid())
|
||||
)
|
||||
{
|
||||
correctFixedFluxBCs(x.ref());
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
template<class ModelType>
|
||||
Foam::tmp<Foam::surfaceScalarField>
|
||||
Foam::BlendedInterfacialModel<ModelType>::Kf() const
|
||||
{
|
||||
tmp<surfaceScalarField> f1, f2;
|
||||
|
||||
if (model_.valid() || model1In2_.valid())
|
||||
{
|
||||
f1 = fvc::interpolate
|
||||
(
|
||||
blending_.f1(phase1_, phase2_)
|
||||
);
|
||||
}
|
||||
|
||||
if (model_.valid() || model2In1_.valid())
|
||||
{
|
||||
f2 = fvc::interpolate
|
||||
(
|
||||
blending_.f2(phase1_, phase2_)
|
||||
);
|
||||
}
|
||||
|
||||
tmp<surfaceScalarField> x
|
||||
(
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
ModelType::typeName + ":Kf",
|
||||
phase1_.mesh().time().timeName(),
|
||||
phase1_.mesh(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
phase1_.mesh(),
|
||||
dimensionedScalar(ModelType::dimK, Zero)
|
||||
)
|
||||
);
|
||||
|
||||
if (model_.valid())
|
||||
{
|
||||
x.ref() += model_->Kf()*(scalar(1) - f1() - f2());
|
||||
}
|
||||
|
||||
if (model1In2_.valid())
|
||||
{
|
||||
x.ref() += model1In2_->Kf()*f1;
|
||||
}
|
||||
|
||||
if (model2In1_.valid())
|
||||
{
|
||||
x.ref() += model2In1_->Kf()*f2;
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
correctFixedFluxBCs_
|
||||
&& (model_.valid() || model1In2_.valid() || model2In1_.valid())
|
||||
)
|
||||
{
|
||||
correctFixedFluxBCs(x.ref());
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
template<class ModelType>
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
|
||||
Foam::BlendedInterfacialModel<ModelType>::F() const
|
||||
{
|
||||
tmp<volScalarField> f1, f2;
|
||||
|
||||
if (model_.valid() || model1In2_.valid())
|
||||
{
|
||||
f1 = blending_.f1(phase1_, phase2_);
|
||||
}
|
||||
|
||||
if (model_.valid() || model2In1_.valid())
|
||||
{
|
||||
f2 = blending_.f2(phase1_, phase2_);
|
||||
}
|
||||
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh>> x
|
||||
(
|
||||
new GeometricField<Type, fvPatchField, volMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
ModelType::typeName + ":F",
|
||||
phase1_.mesh().time().timeName(),
|
||||
phase1_.mesh(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
phase1_.mesh(),
|
||||
dimensioned<Type>(ModelType::dimF, Zero)
|
||||
)
|
||||
);
|
||||
|
||||
if (model_.valid())
|
||||
{
|
||||
x.ref() += model_->F()*(scalar(1) - f1() - f2());
|
||||
}
|
||||
|
||||
if (model1In2_.valid())
|
||||
{
|
||||
x.ref() += model1In2_->F()*f1;
|
||||
}
|
||||
|
||||
if (model2In1_.valid())
|
||||
{
|
||||
x.ref() -= model2In1_->F()*f2; // note : subtraction
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
correctFixedFluxBCs_
|
||||
&& (model_.valid() || model1In2_.valid() || model2In1_.valid())
|
||||
)
|
||||
{
|
||||
correctFixedFluxBCs(x.ref());
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
template<class ModelType>
|
||||
Foam::tmp<Foam::surfaceScalarField>
|
||||
Foam::BlendedInterfacialModel<ModelType>::Ff() const
|
||||
{
|
||||
tmp<surfaceScalarField> f1, f2;
|
||||
|
||||
if (model_.valid() || model1In2_.valid())
|
||||
{
|
||||
f1 = fvc::interpolate
|
||||
(
|
||||
blending_.f1(phase1_, phase2_)
|
||||
);
|
||||
}
|
||||
|
||||
if (model_.valid() || model2In1_.valid())
|
||||
{
|
||||
f2 = fvc::interpolate
|
||||
(
|
||||
blending_.f2(phase1_, phase2_)
|
||||
);
|
||||
}
|
||||
|
||||
tmp<surfaceScalarField> x
|
||||
(
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
ModelType::typeName + ":Ff",
|
||||
phase1_.mesh().time().timeName(),
|
||||
phase1_.mesh(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
phase1_.mesh(),
|
||||
dimensionedScalar(ModelType::dimF*dimArea, Zero)
|
||||
)
|
||||
);
|
||||
x.ref().setOriented();
|
||||
|
||||
if (model_.valid())
|
||||
{
|
||||
x.ref() += model_->Ff()*(scalar(1) - f1() - f2());
|
||||
}
|
||||
|
||||
if (model1In2_.valid())
|
||||
{
|
||||
x.ref() += model1In2_->Ff()*f1;
|
||||
}
|
||||
|
||||
if (model2In1_.valid())
|
||||
{
|
||||
x.ref() -= model2In1_->Ff()*f2; // note : subtraction
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
correctFixedFluxBCs_
|
||||
&& (model_.valid() || model1In2_.valid() || model2In1_.valid())
|
||||
)
|
||||
{
|
||||
correctFixedFluxBCs(x.ref());
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
template<class ModelType>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::BlendedInterfacialModel<ModelType>::D() const
|
||||
{
|
||||
tmp<volScalarField> f1, f2;
|
||||
|
||||
if (model_.valid() || model1In2_.valid())
|
||||
{
|
||||
f1 = blending_.f1(phase1_, phase2_);
|
||||
}
|
||||
|
||||
if (model_.valid() || model2In1_.valid())
|
||||
{
|
||||
f2 = blending_.f2(phase1_, phase2_);
|
||||
}
|
||||
|
||||
tmp<volScalarField> x
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
ModelType::typeName + ":D",
|
||||
phase1_.mesh().time().timeName(),
|
||||
phase1_.mesh(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
phase1_.mesh(),
|
||||
dimensionedScalar(ModelType::dimD, Zero)
|
||||
)
|
||||
);
|
||||
|
||||
if (model_.valid())
|
||||
{
|
||||
x.ref() += model_->D()*(scalar(1) - f1() - f2());
|
||||
}
|
||||
if (model1In2_.valid())
|
||||
{
|
||||
x.ref() += model1In2_->D()*f1;
|
||||
}
|
||||
if (model2In1_.valid())
|
||||
{
|
||||
x.ref() += model2In1_->D()*f2;
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
correctFixedFluxBCs_
|
||||
&& (model_.valid() || model1In2_.valid() || model2In1_.valid())
|
||||
)
|
||||
{
|
||||
correctFixedFluxBCs(x.ref());
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,24 +0,0 @@
|
||||
phaseModel/phaseModel/phaseModel.C
|
||||
phaseModel/phaseModel/newPhaseModel.C
|
||||
phaseModel/phaseModel/phaseModels.C
|
||||
|
||||
phasePair/phasePairKey/phasePairKey.C
|
||||
phasePair/phasePair/phasePair.C
|
||||
phasePair/orderedPhasePair/orderedPhasePair.C
|
||||
|
||||
phaseSystem/phaseSystem.C
|
||||
|
||||
diameterModels/diameterModel/diameterModel.C
|
||||
diameterModels/diameterModel/newDiameterModel.C
|
||||
diameterModels/constantDiameter/constantDiameter.C
|
||||
diameterModels/isothermalDiameter/isothermalDiameter.C
|
||||
|
||||
BlendedInterfacialModel/blendingMethods/blendingMethod/blendingMethod.C
|
||||
BlendedInterfacialModel/blendingMethods/blendingMethod/newBlendingMethod.C
|
||||
BlendedInterfacialModel/blendingMethods/noBlending/noBlending.C
|
||||
BlendedInterfacialModel/blendingMethods/linear/linear.C
|
||||
BlendedInterfacialModel/blendingMethods/hyperbolic/hyperbolic.C
|
||||
|
||||
reactionThermo/hRefConstThermos.C
|
||||
|
||||
LIB = $(FOAM_LIBBIN)/libreactingPhaseSystem
|
||||
@ -1,371 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2015-2016 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "HeatAndMassTransferPhaseSystem.H"
|
||||
|
||||
#include "BlendedInterfacialModel.H"
|
||||
#include "heatTransferModel.H"
|
||||
#include "massTransferModel.H"
|
||||
|
||||
#include "HashPtrTable.H"
|
||||
|
||||
#include "fvcDiv.H"
|
||||
#include "fvmSup.H"
|
||||
#include "fvMatrix.H"
|
||||
#include "zeroGradientFvPatchFields.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::HeatAndMassTransferPhaseSystem<BasePhaseSystem>::
|
||||
HeatAndMassTransferPhaseSystem
|
||||
(
|
||||
const fvMesh& mesh
|
||||
)
|
||||
:
|
||||
BasePhaseSystem(mesh)
|
||||
{
|
||||
this->generatePairsAndSubModels
|
||||
(
|
||||
"heatTransfer",
|
||||
heatTransferModels_
|
||||
);
|
||||
|
||||
this->generatePairsAndSubModels
|
||||
(
|
||||
"massTransfer",
|
||||
massTransferModels_
|
||||
);
|
||||
|
||||
forAllConstIters(this->phasePairs_, phasePairIter)
|
||||
{
|
||||
const phasePair& pair = *(phasePairIter.val());
|
||||
|
||||
if (pair.ordered())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Initially assume no mass transfer
|
||||
|
||||
dmdt_.set
|
||||
(
|
||||
pair,
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName("dmdt", pair.name()),
|
||||
this->mesh().time().timeName(),
|
||||
this->mesh(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
this->mesh(),
|
||||
dimensionedScalar(dimDensity/dimTime, Zero)
|
||||
)
|
||||
);
|
||||
|
||||
dmdtExplicit_.set
|
||||
(
|
||||
pair,
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName("dmdtExplicit", pair.name()),
|
||||
this->mesh().time().timeName(),
|
||||
this->mesh()
|
||||
),
|
||||
this->mesh(),
|
||||
dimensionedScalar(dimDensity/dimTime, Zero)
|
||||
)
|
||||
);
|
||||
|
||||
volScalarField H1(heatTransferModels_[pair][pair.first()]->K());
|
||||
volScalarField H2(heatTransferModels_[pair][pair.second()]->K());
|
||||
|
||||
Tf_.set
|
||||
(
|
||||
pair,
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName("Tf", pair.name()),
|
||||
this->mesh().time().timeName(),
|
||||
this->mesh(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
(
|
||||
H1*pair.phase1().thermo().T()
|
||||
+ H2*pair.phase2().thermo().T()
|
||||
)
|
||||
/max
|
||||
(
|
||||
H1 + H2,
|
||||
dimensionedScalar("small", heatTransferModel::dimK, SMALL)
|
||||
),
|
||||
zeroGradientFvPatchScalarField::typeName
|
||||
)
|
||||
);
|
||||
Tf_[pair]->correctBoundaryConditions();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::HeatAndMassTransferPhaseSystem<BasePhaseSystem>::
|
||||
~HeatAndMassTransferPhaseSystem()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
bool Foam::HeatAndMassTransferPhaseSystem<BasePhaseSystem>::transfersMass
|
||||
(
|
||||
const phaseModel& phase
|
||||
) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::HeatAndMassTransferPhaseSystem<BasePhaseSystem>::dmdt
|
||||
(
|
||||
const phasePairKey& key
|
||||
) const
|
||||
{
|
||||
const scalar dmdtSign(Pair<word>::compare(dmdt_.find(key).key(), key));
|
||||
|
||||
return dmdtSign**dmdt_[key];
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::HeatAndMassTransferPhaseSystem<BasePhaseSystem>::dmdt
|
||||
(
|
||||
const Foam::phaseModel& phase
|
||||
) const
|
||||
{
|
||||
tmp<volScalarField> tdmdt
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName("dmdt", phase.name()),
|
||||
this->mesh_.time().timeName(),
|
||||
this->mesh_
|
||||
),
|
||||
this->mesh_,
|
||||
dimensionedScalar(dimDensity/dimTime, Zero)
|
||||
)
|
||||
);
|
||||
|
||||
forAllConstIters(this->phasePairs_, phasePairIter)
|
||||
{
|
||||
const phasePair& pair = *(phasePairIter.val());
|
||||
|
||||
if (pair.ordered())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const phaseModel* phase1 = &pair.phase1();
|
||||
const phaseModel* phase2 = &pair.phase2();
|
||||
|
||||
forAllConstIters(pair, iter)
|
||||
{
|
||||
if (phase1 == &phase)
|
||||
{
|
||||
tdmdt.ref() += this->dmdt(pair);
|
||||
}
|
||||
|
||||
Swap(phase1, phase2);
|
||||
}
|
||||
}
|
||||
|
||||
return tdmdt;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::autoPtr<Foam::phaseSystem::momentumTransferTable>
|
||||
Foam::HeatAndMassTransferPhaseSystem<BasePhaseSystem>::momentumTransfer() const
|
||||
{
|
||||
autoPtr<phaseSystem::momentumTransferTable>
|
||||
eqnsPtr(BasePhaseSystem::momentumTransfer());
|
||||
|
||||
phaseSystem::momentumTransferTable& eqns = eqnsPtr();
|
||||
|
||||
// Source term due to mass transfer
|
||||
forAllConstIters(this->phasePairs_, phasePairIter)
|
||||
{
|
||||
const phasePair& pair = *(phasePairIter.val());
|
||||
|
||||
if (pair.ordered())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const volVectorField& U1(pair.phase1().U());
|
||||
const volVectorField& U2(pair.phase2().U());
|
||||
|
||||
const volScalarField dmdt(this->dmdt(pair));
|
||||
const volScalarField dmdt21(posPart(dmdt));
|
||||
const volScalarField dmdt12(negPart(dmdt));
|
||||
|
||||
*eqns[pair.phase1().name()] += dmdt21*U2 - fvm::Sp(dmdt21, U1);
|
||||
*eqns[pair.phase2().name()] -= dmdt12*U1 - fvm::Sp(dmdt12, U2);
|
||||
}
|
||||
|
||||
return eqnsPtr;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::autoPtr<Foam::phaseSystem::heatTransferTable>
|
||||
Foam::HeatAndMassTransferPhaseSystem<BasePhaseSystem>::heatTransfer() const
|
||||
{
|
||||
auto eqnsPtr = autoPtr<phaseSystem::heatTransferTable>::New();
|
||||
auto& eqns = *eqnsPtr;
|
||||
|
||||
for (const phaseModel& phase : this->phaseModels_)
|
||||
{
|
||||
eqns.set
|
||||
(
|
||||
phase.name(),
|
||||
new fvScalarMatrix(phase.thermo().he(), dimEnergy/dimTime)
|
||||
);
|
||||
}
|
||||
|
||||
// Heat transfer with the interface
|
||||
forAllConstIters(heatTransferModels_, heatTransferModelIter)
|
||||
{
|
||||
const phasePair& pair =
|
||||
*(this->phasePairs_[heatTransferModelIter.key()]);
|
||||
|
||||
const phaseModel* phase = &pair.phase1();
|
||||
const phaseModel* otherPhase = &pair.phase2();
|
||||
|
||||
const volScalarField& Tf(*Tf_[pair]);
|
||||
|
||||
const volScalarField K1
|
||||
(
|
||||
heatTransferModelIter()[pair.first()]->K()
|
||||
);
|
||||
const volScalarField K2
|
||||
(
|
||||
heatTransferModelIter()[pair.second()]->K()
|
||||
);
|
||||
const volScalarField KEff
|
||||
(
|
||||
K1*K2
|
||||
/max
|
||||
(
|
||||
K1 + K2,
|
||||
dimensionedScalar("small", heatTransferModel::dimK, SMALL)
|
||||
)
|
||||
);
|
||||
|
||||
const volScalarField* K = &K1;
|
||||
const volScalarField* otherK = &K2;
|
||||
|
||||
forAllConstIters(pair, iter)
|
||||
{
|
||||
const volScalarField& he(phase->thermo().he());
|
||||
volScalarField Cpv(phase->thermo().Cpv());
|
||||
|
||||
*eqns[phase->name()] +=
|
||||
(*K)*(Tf - phase->thermo().T())
|
||||
+ KEff/Cpv*he - fvm::Sp(KEff/Cpv, he);
|
||||
|
||||
Swap(phase, otherPhase);
|
||||
Swap(K, otherK);
|
||||
}
|
||||
}
|
||||
|
||||
// Source term due to mass transfer
|
||||
forAllConstIters(this->phasePairs_, phasePairIter)
|
||||
{
|
||||
const phasePair& pair = *(phasePairIter.val());
|
||||
|
||||
if (pair.ordered())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const phaseModel& phase1 = pair.phase1();
|
||||
const phaseModel& phase2 = pair.phase2();
|
||||
|
||||
const volScalarField& he1(phase1.thermo().he());
|
||||
const volScalarField& he2(phase2.thermo().he());
|
||||
|
||||
const volScalarField& K1(phase1.K());
|
||||
const volScalarField& K2(phase2.K());
|
||||
|
||||
const volScalarField dmdt(this->dmdt(pair));
|
||||
const volScalarField dmdt21(posPart(dmdt));
|
||||
const volScalarField dmdt12(negPart(dmdt));
|
||||
const volScalarField& Tf(*Tf_[pair]);
|
||||
|
||||
*eqns[phase1.name()] +=
|
||||
dmdt21*(phase1.thermo().he(phase1.thermo().p(), Tf))
|
||||
- fvm::Sp(dmdt21, he1)
|
||||
+ dmdt21*(K2 - K1);
|
||||
|
||||
*eqns[phase2.name()] -=
|
||||
dmdt12*(phase2.thermo().he(phase2.thermo().p(), Tf))
|
||||
- fvm::Sp(dmdt12, he2)
|
||||
+ dmdt12*(K1 - K2);
|
||||
}
|
||||
|
||||
return eqnsPtr;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
bool Foam::HeatAndMassTransferPhaseSystem<BasePhaseSystem>::read()
|
||||
{
|
||||
if (BasePhaseSystem::read())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,176 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2015-2016 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "HeatTransferPhaseSystem.H"
|
||||
|
||||
#include "BlendedInterfacialModel.H"
|
||||
#include "heatTransferModel.H"
|
||||
|
||||
#include "HashPtrTable.H"
|
||||
|
||||
#include "fvcDiv.H"
|
||||
#include "fvmSup.H"
|
||||
#include "fvMatrix.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::HeatTransferPhaseSystem<BasePhaseSystem>::HeatTransferPhaseSystem
|
||||
(
|
||||
const fvMesh& mesh
|
||||
)
|
||||
:
|
||||
BasePhaseSystem(mesh)
|
||||
{
|
||||
this->generatePairsAndSubModels("heatTransfer", heatTransferModels_);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::HeatTransferPhaseSystem<BasePhaseSystem>::~HeatTransferPhaseSystem()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
bool Foam::HeatTransferPhaseSystem<BasePhaseSystem>::transfersMass
|
||||
(
|
||||
const phaseModel& phase
|
||||
) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::HeatTransferPhaseSystem<BasePhaseSystem>::dmdt
|
||||
(
|
||||
const phasePairKey& key
|
||||
) const
|
||||
{
|
||||
return tmp<volScalarField>::New
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName
|
||||
(
|
||||
"dmdt",
|
||||
this->phasePairs_[key]->name()
|
||||
),
|
||||
this->mesh().time().timeName(),
|
||||
this->mesh().time()
|
||||
),
|
||||
this->mesh(),
|
||||
dimensionedScalar(dimDensity/dimTime, Zero)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::HeatTransferPhaseSystem<BasePhaseSystem>::dmdt
|
||||
(
|
||||
const Foam::phaseModel& phase
|
||||
) const
|
||||
{
|
||||
return tmp<volScalarField>(nullptr);
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::autoPtr<Foam::phaseSystem::heatTransferTable>
|
||||
Foam::HeatTransferPhaseSystem<BasePhaseSystem>::heatTransfer() const
|
||||
{
|
||||
auto eqnsPtr = autoPtr<phaseSystem::heatTransferTable>::New();
|
||||
auto& eqns = *eqnsPtr;
|
||||
|
||||
for (const phaseModel& phase : this->phaseModels_)
|
||||
{
|
||||
eqns.set
|
||||
(
|
||||
phase.name(),
|
||||
new fvScalarMatrix(phase.thermo().he(), dimEnergy/dimTime)
|
||||
);
|
||||
}
|
||||
|
||||
forAllConstIters(heatTransferModels_, heatTransferModelIter)
|
||||
{
|
||||
const phasePair& pair =
|
||||
*(this->phasePairs_[heatTransferModelIter.key()]);
|
||||
|
||||
const volScalarField K(heatTransferModelIter()->K());
|
||||
|
||||
const phaseModel* phase = &pair.phase1();
|
||||
const phaseModel* otherPhase = &pair.phase2();
|
||||
|
||||
forAllConstIters(pair, iter)
|
||||
{
|
||||
const volScalarField& he(phase->thermo().he());
|
||||
volScalarField Cpv(phase->thermo().Cpv());
|
||||
|
||||
*eqns[phase->name()] +=
|
||||
K*(otherPhase->thermo().T() - phase->thermo().T() + he/Cpv)
|
||||
- fvm::Sp(K/Cpv, he);
|
||||
|
||||
Swap(phase, otherPhase);
|
||||
}
|
||||
}
|
||||
|
||||
return eqnsPtr;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::autoPtr<Foam::phaseSystem::massTransferTable>
|
||||
Foam::HeatTransferPhaseSystem<BasePhaseSystem>::massTransfer() const
|
||||
{
|
||||
autoPtr<phaseSystem::massTransferTable> eqnsPtr
|
||||
(
|
||||
new phaseSystem::massTransferTable()
|
||||
);
|
||||
|
||||
return eqnsPtr;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
bool Foam::HeatTransferPhaseSystem<BasePhaseSystem>::read()
|
||||
{
|
||||
if (BasePhaseSystem::read())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,294 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd |
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2015-2016 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "InterfaceCompositionPhaseChangePhaseSystem.H"
|
||||
#include "interfaceCompositionModel.H"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::InterfaceCompositionPhaseChangePhaseSystem<BasePhaseSystem>::
|
||||
InterfaceCompositionPhaseChangePhaseSystem
|
||||
(
|
||||
const fvMesh& mesh
|
||||
)
|
||||
:
|
||||
HeatAndMassTransferPhaseSystem<BasePhaseSystem>(mesh)
|
||||
{
|
||||
this->generatePairsAndSubModels
|
||||
(
|
||||
"interfaceComposition",
|
||||
interfaceCompositionModels_
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::InterfaceCompositionPhaseChangePhaseSystem<BasePhaseSystem>::
|
||||
~InterfaceCompositionPhaseChangePhaseSystem()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::autoPtr<Foam::phaseSystem::massTransferTable>
|
||||
Foam::InterfaceCompositionPhaseChangePhaseSystem<BasePhaseSystem>::
|
||||
massTransfer() const
|
||||
{
|
||||
// Create a mass transfer matrix for each species of each phase
|
||||
auto eqnsPtr = autoPtr<phaseSystem::massTransferTable>::New();
|
||||
auto& eqns = *eqnsPtr;
|
||||
|
||||
for (const phaseModel& phase : this->phaseModels_)
|
||||
{
|
||||
const PtrList<volScalarField>& Yi = phase.Y();
|
||||
|
||||
forAll(Yi, i)
|
||||
{
|
||||
eqns.set
|
||||
(
|
||||
Yi[i].name(),
|
||||
new fvScalarMatrix(Yi[i], dimMass/dimTime)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the interfacial mass flow rates
|
||||
forAllConstIters(this->phasePairs_, phasePairIter)
|
||||
{
|
||||
const phasePair& pair = *(phasePairIter.val());
|
||||
|
||||
if (pair.ordered())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
*this->dmdt_[pair] =
|
||||
*this->dmdtExplicit_[pair];
|
||||
|
||||
*this->dmdtExplicit_[pair] =
|
||||
dimensionedScalar(dimDensity/dimTime, Zero);
|
||||
}
|
||||
|
||||
// Sum up the contribution from each interface composition model
|
||||
forAllConstIters(interfaceCompositionModels_, modelIter)
|
||||
{
|
||||
const phasePair& pair = *(this->phasePairs_[modelIter.key()]);
|
||||
|
||||
const interfaceCompositionModel& compositionModel = *(modelIter.val());
|
||||
|
||||
const phaseModel& phase = pair.phase1();
|
||||
const phaseModel& otherPhase = pair.phase2();
|
||||
const phasePairKey key(phase.name(), otherPhase.name());
|
||||
|
||||
const volScalarField& Tf(*this->Tf_[key]);
|
||||
|
||||
volScalarField& dmdtExplicit(*this->dmdtExplicit_[key]);
|
||||
volScalarField& dmdt(*this->dmdt_[key]);
|
||||
|
||||
scalar dmdtSign(Pair<word>::compare(this->dmdt_.find(key).key(), key));
|
||||
|
||||
const volScalarField K
|
||||
(
|
||||
this->massTransferModels_[key][phase.name()]->K()
|
||||
);
|
||||
|
||||
for (const word& member : compositionModel.species())
|
||||
{
|
||||
const word name
|
||||
(
|
||||
IOobject::groupName(member, phase.name())
|
||||
);
|
||||
|
||||
const word otherName
|
||||
(
|
||||
IOobject::groupName(member, otherPhase.name())
|
||||
);
|
||||
|
||||
const volScalarField KD
|
||||
(
|
||||
K*compositionModel.D(member)
|
||||
);
|
||||
|
||||
const volScalarField Yf
|
||||
(
|
||||
compositionModel.Yf(member, Tf)
|
||||
);
|
||||
|
||||
// Implicit transport through the phase
|
||||
*eqns[name] +=
|
||||
phase.rho()*KD*Yf
|
||||
- fvm::Sp(phase.rho()*KD, eqns[name]->psi());
|
||||
|
||||
// Sum the mass transfer rate
|
||||
dmdtExplicit += dmdtSign*phase.rho()*KD*Yf;
|
||||
dmdt -= dmdtSign*phase.rho()*KD*eqns[name]->psi();
|
||||
|
||||
// Explicit transport out of the other phase
|
||||
if (eqns.found(otherName))
|
||||
{
|
||||
*eqns[otherName] -=
|
||||
otherPhase.rho()*KD*compositionModel.dY(member, Tf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return eqnsPtr;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
void Foam::InterfaceCompositionPhaseChangePhaseSystem<BasePhaseSystem>::
|
||||
correctThermo()
|
||||
{
|
||||
BasePhaseSystem::correctThermo();
|
||||
|
||||
// This loop solves for the interface temperatures, Tf, and updates the
|
||||
// interface composition models.
|
||||
//
|
||||
// The rate of heat transfer to the interface must equal the latent heat
|
||||
// consumed at the interface, i.e.:
|
||||
//
|
||||
// H1*(T1 - Tf) + H2*(T2 - Tf) == mDotL
|
||||
// == K*rho*(Yfi - Yi)*Li
|
||||
//
|
||||
// Yfi is likely to be a strong non-linear (typically exponential) function
|
||||
// of Tf, so the solution for the temperature is newton-accelerated
|
||||
|
||||
forAllConstIters(this->phasePairs_, phasePairIter)
|
||||
{
|
||||
const phasePair& pair = *(phasePairIter.val());
|
||||
|
||||
if (pair.ordered())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const phasePairKey key12(pair.first(), pair.second(), true);
|
||||
const phasePairKey key21(pair.second(), pair.first(), true);
|
||||
|
||||
volScalarField H1(this->heatTransferModels_[pair][pair.first()]->K());
|
||||
volScalarField H2(this->heatTransferModels_[pair][pair.second()]->K());
|
||||
dimensionedScalar HSmall("small", heatTransferModel::dimK, SMALL);
|
||||
|
||||
volScalarField mDotL
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"mDotL",
|
||||
this->mesh().time().timeName(),
|
||||
this->mesh()
|
||||
),
|
||||
this->mesh(),
|
||||
dimensionedScalar(dimEnergy/dimVolume/dimTime, Zero)
|
||||
);
|
||||
volScalarField mDotLPrime
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"mDotLPrime",
|
||||
this->mesh().time().timeName(),
|
||||
this->mesh()
|
||||
),
|
||||
this->mesh(),
|
||||
dimensionedScalar(mDotL.dimensions()/dimTemperature, Zero)
|
||||
);
|
||||
|
||||
volScalarField& Tf = *this->Tf_[pair];
|
||||
|
||||
// Add latent heats from forward and backward models
|
||||
if (this->interfaceCompositionModels_.found(key12))
|
||||
{
|
||||
this->interfaceCompositionModels_[key12]->addMDotL
|
||||
(
|
||||
this->massTransferModels_[pair][pair.first()]->K(),
|
||||
Tf,
|
||||
mDotL,
|
||||
mDotLPrime
|
||||
);
|
||||
}
|
||||
if (this->interfaceCompositionModels_.found(key21))
|
||||
{
|
||||
this->interfaceCompositionModels_[key21]->addMDotL
|
||||
(
|
||||
this->massTransferModels_[pair][pair.second()]->K(),
|
||||
Tf,
|
||||
mDotL,
|
||||
mDotLPrime
|
||||
);
|
||||
}
|
||||
|
||||
// Update the interface temperature by applying one step of newton's
|
||||
// method to the interface relation
|
||||
Tf -=
|
||||
(
|
||||
H1*(Tf - pair.phase1().thermo().T())
|
||||
+ H2*(Tf - pair.phase2().thermo().T())
|
||||
+ mDotL
|
||||
)
|
||||
/(
|
||||
max(H1 + H2 + mDotLPrime, HSmall)
|
||||
);
|
||||
|
||||
Tf.correctBoundaryConditions();
|
||||
|
||||
Info<< "Tf." << pair.name()
|
||||
<< ": min = " << min(Tf.primitiveField())
|
||||
<< ", mean = " << average(Tf.primitiveField())
|
||||
<< ", max = " << max(Tf.primitiveField())
|
||||
<< endl;
|
||||
|
||||
// Update the interface compositions
|
||||
if (this->interfaceCompositionModels_.found(key12))
|
||||
{
|
||||
this->interfaceCompositionModels_[key12]->update(Tf);
|
||||
}
|
||||
if (this->interfaceCompositionModels_.found(key21))
|
||||
{
|
||||
this->interfaceCompositionModels_[key21]->update(Tf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
bool Foam::InterfaceCompositionPhaseChangePhaseSystem<BasePhaseSystem>::read()
|
||||
{
|
||||
if (BasePhaseSystem::read())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,604 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2015-2016 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "MomentumTransferPhaseSystem.H"
|
||||
|
||||
#include "BlendedInterfacialModel.H"
|
||||
#include "dragModel.H"
|
||||
#include "virtualMassModel.H"
|
||||
#include "liftModel.H"
|
||||
#include "wallLubricationModel.H"
|
||||
#include "turbulentDispersionModel.H"
|
||||
|
||||
#include "HashPtrTable.H"
|
||||
|
||||
#include "fvmDdt.H"
|
||||
#include "fvmDiv.H"
|
||||
#include "fvmSup.H"
|
||||
#include "fvcDiv.H"
|
||||
#include "fvcSnGrad.H"
|
||||
#include "fvMatrix.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::
|
||||
MomentumTransferPhaseSystem
|
||||
(
|
||||
const fvMesh& mesh
|
||||
)
|
||||
:
|
||||
BasePhaseSystem(mesh)
|
||||
{
|
||||
this->generatePairsAndSubModels
|
||||
(
|
||||
"drag",
|
||||
dragModels_
|
||||
);
|
||||
|
||||
this->generatePairsAndSubModels
|
||||
(
|
||||
"virtualMass",
|
||||
virtualMassModels_
|
||||
);
|
||||
|
||||
this->generatePairsAndSubModels
|
||||
(
|
||||
"lift",
|
||||
liftModels_
|
||||
);
|
||||
|
||||
this->generatePairsAndSubModels
|
||||
(
|
||||
"wallLubrication",
|
||||
wallLubricationModels_
|
||||
);
|
||||
|
||||
this->generatePairsAndSubModels
|
||||
(
|
||||
"turbulentDispersion",
|
||||
turbulentDispersionModels_
|
||||
);
|
||||
|
||||
forAllConstIters(dragModels_, dragModelIter)
|
||||
{
|
||||
const phasePair& pair =
|
||||
*(this->phasePairs_[dragModelIter.key()]);
|
||||
|
||||
Kds_.set
|
||||
(
|
||||
pair,
|
||||
new volScalarField
|
||||
(
|
||||
IOobject::groupName("Kd", pair.name()),
|
||||
dragModelIter()->K()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
forAllConstIters(virtualMassModels_, virtualMassModelIter)
|
||||
{
|
||||
const phasePair& pair =
|
||||
*(this->phasePairs_[virtualMassModelIter.key()]);
|
||||
|
||||
Vms_.set
|
||||
(
|
||||
pair,
|
||||
new volScalarField
|
||||
(
|
||||
IOobject::groupName("Vm", pair.name()),
|
||||
virtualMassModelIter()->K()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::
|
||||
~MomentumTransferPhaseSystem()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::Kd
|
||||
(
|
||||
const phasePairKey& key
|
||||
) const
|
||||
{
|
||||
return dragModels_[key]->K();
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::surfaceScalarField>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::Kdf
|
||||
(
|
||||
const phasePairKey& key
|
||||
) const
|
||||
{
|
||||
return dragModels_[key]->Kf();
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::Kd
|
||||
(
|
||||
const Foam::phaseModel& phase
|
||||
) const
|
||||
{
|
||||
tmp<volScalarField> tKd
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName("Kd", phase.name()),
|
||||
this->mesh_.time().timeName(),
|
||||
this->mesh_
|
||||
),
|
||||
this->mesh_,
|
||||
dimensionedScalar(dimensionSet(1, -3, -1, 0, 0), Zero)
|
||||
)
|
||||
);
|
||||
|
||||
forAllConstIters(Kds_, KdIter)
|
||||
{
|
||||
const phasePair& pair = *(this->phasePairs_[KdIter.key()]);
|
||||
|
||||
const volScalarField& K(*KdIter());
|
||||
|
||||
const phaseModel* phase1 = &pair.phase1();
|
||||
const phaseModel* phase2 = &pair.phase2();
|
||||
|
||||
forAllConstIters(pair, iter)
|
||||
{
|
||||
if (phase1 == &phase)
|
||||
{
|
||||
tKd.ref() += K;
|
||||
}
|
||||
|
||||
Swap(phase1, phase2);
|
||||
}
|
||||
}
|
||||
|
||||
return tKd;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::Vm
|
||||
(
|
||||
const phasePairKey& key
|
||||
) const
|
||||
{
|
||||
if (virtualMassModels_.found(key))
|
||||
{
|
||||
return virtualMassModels_[key]->K();
|
||||
}
|
||||
|
||||
return tmp<volScalarField>::New
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
virtualMassModel::typeName + ":K",
|
||||
this->mesh_.time().timeName(),
|
||||
this->mesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
this->mesh_,
|
||||
dimensionedScalar(virtualMassModel::dimK, Zero)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::surfaceScalarField>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::Vmf
|
||||
(
|
||||
const phasePairKey& key
|
||||
) const
|
||||
{
|
||||
if (virtualMassModels_.found(key))
|
||||
{
|
||||
return virtualMassModels_[key]->Kf();
|
||||
}
|
||||
|
||||
return tmp<surfaceScalarField>::New
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
virtualMassModel::typeName + ":Kf",
|
||||
this->mesh_.time().timeName(),
|
||||
this->mesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
this->mesh_,
|
||||
dimensionedScalar(virtualMassModel::dimK, Zero)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::volVectorField>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::F
|
||||
(
|
||||
const phasePairKey& key
|
||||
) const
|
||||
{
|
||||
if (liftModels_.found(key) && wallLubricationModels_.found(key))
|
||||
{
|
||||
return
|
||||
liftModels_[key]->template F<vector>()
|
||||
+ wallLubricationModels_[key]->template F<vector>();
|
||||
}
|
||||
else if (liftModels_.found(key))
|
||||
{
|
||||
return liftModels_[key]->template F<vector>();
|
||||
}
|
||||
else if (wallLubricationModels_.found(key))
|
||||
{
|
||||
return wallLubricationModels_[key]->template F<vector>();
|
||||
}
|
||||
|
||||
return tmp<volVectorField>::New
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
liftModel::typeName + ":F",
|
||||
this->mesh_.time().timeName(),
|
||||
this->mesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
this->mesh_,
|
||||
dimensionedVector(liftModel::dimF, Zero)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::surfaceScalarField>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::Ff
|
||||
(
|
||||
const phasePairKey& key
|
||||
) const
|
||||
{
|
||||
if (liftModels_.found(key) && wallLubricationModels_.found(key))
|
||||
{
|
||||
return
|
||||
liftModels_[key]->Ff()
|
||||
+ wallLubricationModels_[key]->Ff();
|
||||
}
|
||||
else if (liftModels_.found(key))
|
||||
{
|
||||
return liftModels_[key]->Ff();
|
||||
}
|
||||
else if (wallLubricationModels_.found(key))
|
||||
{
|
||||
return wallLubricationModels_[key]->Ff();
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp<surfaceScalarField> tFf
|
||||
(
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
liftModel::typeName + ":Ff",
|
||||
this->mesh_.time().timeName(),
|
||||
this->mesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
this->mesh_,
|
||||
dimensionedScalar(liftModel::dimF*dimArea, Zero)
|
||||
)
|
||||
);
|
||||
|
||||
tFf.ref().setOriented();
|
||||
|
||||
return tFf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::D
|
||||
(
|
||||
const phasePairKey& key
|
||||
) const
|
||||
{
|
||||
if (turbulentDispersionModels_.found(key))
|
||||
{
|
||||
return turbulentDispersionModels_[key]->D();
|
||||
}
|
||||
|
||||
return tmp<volScalarField>::New
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
turbulentDispersionModel::typeName + ":D",
|
||||
this->mesh_.time().timeName(),
|
||||
this->mesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
this->mesh_,
|
||||
dimensionedScalar(turbulentDispersionModel::dimD, Zero)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::autoPtr<Foam::phaseSystem::momentumTransferTable>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::momentumTransfer() const
|
||||
{
|
||||
// Create a momentum transfer matrix for each phase
|
||||
auto eqnsPtr = autoPtr<phaseSystem::momentumTransferTable>::New();
|
||||
auto& eqns = *eqnsPtr;
|
||||
|
||||
for (const phaseModel& phase : this->phaseModels_)
|
||||
{
|
||||
eqns.set
|
||||
(
|
||||
phase.name(),
|
||||
new fvVectorMatrix(phase.U(), dimMass*dimVelocity/dimTime)
|
||||
);
|
||||
}
|
||||
|
||||
// Update the drag coefficients
|
||||
forAllConstIters(dragModels_, dragModelIter)
|
||||
{
|
||||
*Kds_[dragModelIter.key()] = dragModelIter()->K();
|
||||
}
|
||||
|
||||
// Add the implicit part of the drag force
|
||||
forAllConstIters(Kds_, KdIter)
|
||||
{
|
||||
const phasePair& pair = *(this->phasePairs_[KdIter.key()]);
|
||||
|
||||
const volScalarField& K(*KdIter());
|
||||
|
||||
const phaseModel* phase = &pair.phase1();
|
||||
const phaseModel* otherPhase = &pair.phase2();
|
||||
|
||||
forAllConstIters(pair, iter)
|
||||
{
|
||||
const volVectorField& U = phase->U();
|
||||
|
||||
*eqns[phase->name()] -= fvm::Sp(K, U);
|
||||
|
||||
Swap(phase, otherPhase);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the virtual mass coefficients
|
||||
forAllConstIters(virtualMassModels_, virtualMassModelIter)
|
||||
{
|
||||
*Vms_[virtualMassModelIter.key()] = virtualMassModelIter()->K();
|
||||
}
|
||||
|
||||
// Add the virtual mass force
|
||||
forAllConstIters(Vms_, VmIter)
|
||||
{
|
||||
const phasePair& pair = *(this->phasePairs_[VmIter.key()]);
|
||||
|
||||
const volScalarField& Vm(*VmIter());
|
||||
|
||||
const phaseModel* phase = &pair.phase1();
|
||||
const phaseModel* otherPhase = &pair.phase2();
|
||||
|
||||
forAllConstIters(pair, iter)
|
||||
{
|
||||
const volVectorField& U = phase->U();
|
||||
const surfaceScalarField& phi = phase->phi();
|
||||
|
||||
*eqns[phase->name()] -=
|
||||
Vm
|
||||
*(
|
||||
fvm::ddt(U)
|
||||
+ fvm::div(phi, U)
|
||||
- fvm::Sp(fvc::div(phi), U)
|
||||
- otherPhase->DUDt()
|
||||
)
|
||||
+ this->MRF_.DDt(Vm, U - otherPhase->U());
|
||||
|
||||
Swap(phase, otherPhase);
|
||||
}
|
||||
}
|
||||
|
||||
return eqnsPtr;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::volVectorField& Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::setF
|
||||
(
|
||||
PtrList<volVectorField>& Fs, const label phasei
|
||||
) const
|
||||
{
|
||||
if (!Fs.set(phasei))
|
||||
{
|
||||
Fs.set
|
||||
(
|
||||
phasei,
|
||||
new volVectorField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
liftModel::typeName + ":F",
|
||||
this->mesh_.time().timeName(),
|
||||
this->mesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
this->mesh_,
|
||||
dimensionedVector(liftModel::dimF, Zero)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return Fs[phasei];
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::autoPtr<Foam::PtrList<Foam::volVectorField>>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::Fs() const
|
||||
{
|
||||
auto tFs = autoPtr<PtrList<volVectorField>>::New(this->phases().size());
|
||||
auto& Fs = *tFs;
|
||||
|
||||
// Add the lift force
|
||||
forAllConstIters(liftModels_, modelIter)
|
||||
{
|
||||
const phasePair& pair = *(this->phasePairs_[modelIter.key()]);
|
||||
|
||||
const volVectorField F(modelIter()->template F<vector>());
|
||||
|
||||
setF(Fs, pair.phase1().index()) += F;
|
||||
setF(Fs, pair.phase2().index()) -= F;
|
||||
}
|
||||
|
||||
// Add the wall lubrication force
|
||||
forAllConstIters(wallLubricationModels_, modelIter)
|
||||
{
|
||||
const phasePair& pair = *(this->phasePairs_[modelIter.key()]);
|
||||
|
||||
const volVectorField F(modelIter()->template F<vector>());
|
||||
|
||||
setF(Fs, pair.phase1().index()) += F;
|
||||
setF(Fs, pair.phase2().index()) -= F;
|
||||
}
|
||||
|
||||
return tFs;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::surfaceScalarField&
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::setPhiD
|
||||
(
|
||||
PtrList<surfaceScalarField>& phiDs, const label phasei
|
||||
) const
|
||||
{
|
||||
if (!phiDs.set(phasei))
|
||||
{
|
||||
phiDs.set
|
||||
(
|
||||
phasei,
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
turbulentDispersionModel::typeName + ":phiD",
|
||||
this->mesh_.time().timeName(),
|
||||
this->mesh_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
this->mesh_,
|
||||
dimensionedScalar
|
||||
(
|
||||
dimTime*dimArea*turbulentDispersionModel::dimF/dimDensity,
|
||||
Zero
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
phiDs[phasei].setOriented();
|
||||
}
|
||||
|
||||
return phiDs[phasei];
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::autoPtr<Foam::PtrList<Foam::surfaceScalarField>>
|
||||
Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::phiDs
|
||||
(
|
||||
const PtrList<volScalarField>& rAUs
|
||||
) const
|
||||
{
|
||||
auto tphiDs =
|
||||
autoPtr<PtrList<surfaceScalarField>>::New(this->phases().size());
|
||||
auto& phiDs = *tphiDs;
|
||||
|
||||
// Add the turbulent dispersion force
|
||||
forAllConstIters(turbulentDispersionModels_, turbulentDispersionModelIter)
|
||||
{
|
||||
const phasePair& pair =
|
||||
*(this->phasePairs_[turbulentDispersionModelIter.key()]);
|
||||
|
||||
const volScalarField D(turbulentDispersionModelIter()->D());
|
||||
const surfaceScalarField snGradAlpha1
|
||||
(
|
||||
fvc::snGrad(pair.phase1())*this->mesh_.magSf()
|
||||
);
|
||||
|
||||
setPhiD(phiDs, pair.phase1().index()) +=
|
||||
fvc::interpolate(rAUs[pair.phase1().index()]*D)*snGradAlpha1;
|
||||
setPhiD(phiDs, pair.phase2().index()) -=
|
||||
fvc::interpolate(rAUs[pair.phase2().index()]*D)*snGradAlpha1;
|
||||
}
|
||||
|
||||
return tphiDs;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
bool Foam::MomentumTransferPhaseSystem<BasePhaseSystem>::read()
|
||||
{
|
||||
if (BasePhaseSystem::read())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,497 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2015-2017 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "ThermalPhaseChangePhaseSystem.H"
|
||||
#include "alphatPhaseChangeWallFunctionFvPatchScalarField.H"
|
||||
#include "fvcVolumeIntegrate.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::ThermalPhaseChangePhaseSystem<BasePhaseSystem>::
|
||||
ThermalPhaseChangePhaseSystem
|
||||
(
|
||||
const fvMesh& mesh
|
||||
)
|
||||
:
|
||||
HeatAndMassTransferPhaseSystem<BasePhaseSystem>(mesh),
|
||||
volatile_(this->lookup("volatile")),
|
||||
saturationModel_(saturationModel::New(this->subDict("saturationModel"))),
|
||||
massTransfer_(this->template get<bool>("massTransfer"))
|
||||
{
|
||||
|
||||
forAllConstIters(this->phasePairs_, phasePairIter)
|
||||
{
|
||||
const phasePair& pair = *(phasePairIter.val());
|
||||
|
||||
if (pair.ordered())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Initially assume no mass transfer
|
||||
iDmdt_.set
|
||||
(
|
||||
pair,
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName("iDmdt", pair.name()),
|
||||
this->mesh().time().timeName(),
|
||||
this->mesh(),
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
this->mesh(),
|
||||
dimensionedScalar(dimDensity/dimTime, Zero)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::ThermalPhaseChangePhaseSystem<BasePhaseSystem>::
|
||||
~ThermalPhaseChangePhaseSystem()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
const Foam::saturationModel&
|
||||
Foam::ThermalPhaseChangePhaseSystem<BasePhaseSystem>::saturation() const
|
||||
{
|
||||
return *saturationModel_;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::autoPtr<Foam::phaseSystem::heatTransferTable>
|
||||
Foam::ThermalPhaseChangePhaseSystem<BasePhaseSystem>::heatTransfer() const
|
||||
{
|
||||
typedef compressible::alphatPhaseChangeWallFunctionFvPatchScalarField
|
||||
alphatPhaseChangeWallFunction;
|
||||
|
||||
autoPtr<phaseSystem::heatTransferTable> eqnsPtr =
|
||||
Foam::HeatAndMassTransferPhaseSystem<BasePhaseSystem>::heatTransfer();
|
||||
|
||||
phaseSystem::heatTransferTable& eqns = eqnsPtr();
|
||||
|
||||
// Accumulate mDotL contributions from boundaries
|
||||
forAllConstIters(this->phasePairs_, phasePairIter)
|
||||
{
|
||||
const phasePair& pair = *(phasePairIter.val());
|
||||
|
||||
if (pair.ordered())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const phaseModel& phase = pair.phase1();
|
||||
const phaseModel& otherPhase = pair.phase2();
|
||||
|
||||
volScalarField mDotL
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"mDotL",
|
||||
phase.mesh().time().timeName(),
|
||||
phase.mesh(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
phase.mesh(),
|
||||
dimensionedScalar(dimensionSet(1,-1,-3,0,0), Zero)
|
||||
);
|
||||
|
||||
const volScalarField* alphatPtr =
|
||||
otherPhase.mesh().findObject<volScalarField>
|
||||
(
|
||||
"alphat." + otherPhase.name()
|
||||
);
|
||||
|
||||
if (alphatPtr)
|
||||
{
|
||||
const volScalarField& alphat = *alphatPtr;
|
||||
|
||||
const fvPatchList& patches = this->mesh().boundary();
|
||||
forAll(patches, patchi)
|
||||
{
|
||||
const fvPatch& currPatch = patches[patchi];
|
||||
|
||||
if
|
||||
(
|
||||
isA<alphatPhaseChangeWallFunction>
|
||||
(
|
||||
alphat.boundaryField()[patchi]
|
||||
)
|
||||
)
|
||||
{
|
||||
const scalarField& patchMDotL =
|
||||
refCast<const alphatPhaseChangeWallFunction>
|
||||
(
|
||||
alphat.boundaryField()[patchi]
|
||||
).mDotL();
|
||||
|
||||
forAll(patchMDotL,facei)
|
||||
{
|
||||
label faceCelli = currPatch.faceCells()[facei];
|
||||
mDotL[faceCelli] = patchMDotL[facei];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*eqns[otherPhase.name()] -= mDotL;
|
||||
|
||||
}
|
||||
|
||||
return eqnsPtr;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::autoPtr<Foam::phaseSystem::massTransferTable>
|
||||
Foam::ThermalPhaseChangePhaseSystem<BasePhaseSystem>::massTransfer() const
|
||||
{
|
||||
// Create a mass transfer matrix for each species of each phase
|
||||
auto eqnsPtr = autoPtr<phaseSystem::massTransferTable>::New();
|
||||
auto& eqns = *eqnsPtr;
|
||||
|
||||
for (const phaseModel& phase : this->phaseModels_)
|
||||
{
|
||||
const PtrList<volScalarField>& Yi = phase.Y();
|
||||
|
||||
forAll(Yi, i)
|
||||
{
|
||||
eqns.set
|
||||
(
|
||||
Yi[i].name(),
|
||||
new fvScalarMatrix(Yi[i], dimMass/dimTime)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
forAllConstIters(this->phasePairs_, phasePairIter)
|
||||
{
|
||||
const phasePair& pair = *(phasePairIter.val());
|
||||
|
||||
if (pair.ordered())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const phaseModel& phase = pair.phase1();
|
||||
const phaseModel& otherPhase = pair.phase2();
|
||||
|
||||
const word thisName
|
||||
(
|
||||
IOobject::groupName(volatile_, phase.name())
|
||||
);
|
||||
|
||||
const word otherName
|
||||
(
|
||||
IOobject::groupName(volatile_, otherPhase.name())
|
||||
);
|
||||
|
||||
const volScalarField dmdt(this->dmdt(pair));
|
||||
const volScalarField dmdt12(posPart(dmdt));
|
||||
const volScalarField dmdt21(negPart(dmdt));
|
||||
|
||||
*eqns[thisName] += fvm::Sp(dmdt21, eqns[thisName]->psi()) - dmdt21;
|
||||
*eqns[otherName] += dmdt12 - fvm::Sp(dmdt12, eqns[otherName]->psi());
|
||||
}
|
||||
|
||||
return eqnsPtr;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::ThermalPhaseChangePhaseSystem<BasePhaseSystem>::iDmdt
|
||||
(
|
||||
const phasePairKey& key
|
||||
) const
|
||||
{
|
||||
const scalar dmdtSign(Pair<word>::compare(iDmdt_.find(key).key(), key));
|
||||
|
||||
return dmdtSign**iDmdt_[key];
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
Foam::tmp<Foam::volScalarField>
|
||||
Foam::ThermalPhaseChangePhaseSystem<BasePhaseSystem>::iDmdt
|
||||
(
|
||||
const Foam::phaseModel& phase
|
||||
) const
|
||||
{
|
||||
tmp<volScalarField> tiDmdt
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName("iDmdt", phase.name()),
|
||||
this->mesh_.time().timeName(),
|
||||
this->mesh_
|
||||
),
|
||||
this->mesh_,
|
||||
dimensionedScalar(dimDensity/dimTime, Zero)
|
||||
)
|
||||
);
|
||||
|
||||
forAllConstIters(this->phasePairs_, phasePairIter)
|
||||
{
|
||||
const phasePair& pair = *(phasePairIter.val());
|
||||
|
||||
if (pair.ordered())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const phaseModel* phase1 = &pair.phase1();
|
||||
const phaseModel* phase2 = &pair.phase2();
|
||||
|
||||
forAllConstIters(pair, iter)
|
||||
{
|
||||
if (phase1 == &phase)
|
||||
{
|
||||
tiDmdt.ref() += this->iDmdt(pair);
|
||||
}
|
||||
|
||||
Swap(phase1, phase2);
|
||||
}
|
||||
}
|
||||
|
||||
return tiDmdt;
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
void Foam::ThermalPhaseChangePhaseSystem<BasePhaseSystem>::correctThermo()
|
||||
{
|
||||
typedef compressible::alphatPhaseChangeWallFunctionFvPatchScalarField
|
||||
alphatPhaseChangeWallFunction;
|
||||
|
||||
BasePhaseSystem::correctThermo();
|
||||
|
||||
forAllConstIters(this->phasePairs_, phasePairIter)
|
||||
{
|
||||
const phasePair& pair = *(phasePairIter.val());
|
||||
|
||||
if (pair.ordered())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const phaseModel& phase1 = pair.phase1();
|
||||
const phaseModel& phase2 = pair.phase2();
|
||||
|
||||
Info<< phase1.name() << " min/max T "
|
||||
<< min(phase1.thermo().T()).value()
|
||||
<< " - "
|
||||
<< max(phase1.thermo().T()).value()
|
||||
<< endl;
|
||||
|
||||
Info<< phase2.name() << " min/max T "
|
||||
<< min(phase2.thermo().T()).value()
|
||||
<< " - "
|
||||
<< max(phase2.thermo().T()).value()
|
||||
<< endl;
|
||||
|
||||
const volScalarField& T1(phase1.thermo().T());
|
||||
const volScalarField& T2(phase2.thermo().T());
|
||||
|
||||
const volScalarField& he1(phase1.thermo().he());
|
||||
const volScalarField& he2(phase2.thermo().he());
|
||||
|
||||
volScalarField& dmdt(*this->dmdt_[pair]);
|
||||
volScalarField& iDmdt(*this->iDmdt_[pair]);
|
||||
|
||||
volScalarField& Tf = *this->Tf_[pair];
|
||||
|
||||
volScalarField hef1(phase1.thermo().he(phase1.thermo().p(), Tf));
|
||||
volScalarField hef2(phase2.thermo().he(phase2.thermo().p(), Tf));
|
||||
|
||||
volScalarField L
|
||||
(
|
||||
min
|
||||
(
|
||||
(pos0(iDmdt)*he2 + neg(iDmdt)*hef2)
|
||||
- (neg(iDmdt)*he1 + pos0(iDmdt)*hef1),
|
||||
0.3*mag(hef2 - hef1)
|
||||
)
|
||||
);
|
||||
|
||||
volScalarField iDmdtNew(iDmdt);
|
||||
|
||||
if (massTransfer_)
|
||||
{
|
||||
volScalarField H1
|
||||
(
|
||||
this->heatTransferModels_[pair][pair.first()]->K(0)
|
||||
);
|
||||
|
||||
volScalarField H2
|
||||
(
|
||||
this->heatTransferModels_[pair][pair.second()]->K(0)
|
||||
);
|
||||
|
||||
Tf = saturationModel_->Tsat(phase1.thermo().p());
|
||||
|
||||
iDmdtNew =
|
||||
(H1*(Tf - T1) + H2*(Tf - T2))/L;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
iDmdtNew == dimensionedScalar(dmdt.dimensions(), Zero);
|
||||
}
|
||||
|
||||
volScalarField H1(this->heatTransferModels_[pair][pair.first()]->K());
|
||||
volScalarField H2(this->heatTransferModels_[pair][pair.second()]->K());
|
||||
|
||||
// Limit the H[12] boundary field to avoid /0
|
||||
const scalar HLimit = 1e-4;
|
||||
H1.boundaryFieldRef() =
|
||||
max(H1.boundaryField(), phase1.boundaryField()*HLimit);
|
||||
H2.boundaryFieldRef() =
|
||||
max(H2.boundaryField(), phase2.boundaryField()*HLimit);
|
||||
|
||||
Tf = (H1*T1 + H2*T2 + iDmdtNew*L)/(H1 + H2);
|
||||
|
||||
Info<< "Tf." << pair.name()
|
||||
<< ": min = " << min(Tf.primitiveField())
|
||||
<< ", mean = " << average(Tf.primitiveField())
|
||||
<< ", max = " << max(Tf.primitiveField())
|
||||
<< endl;
|
||||
|
||||
scalar iDmdtRelax(this->mesh().fieldRelaxationFactor("iDmdt"));
|
||||
iDmdt = (1 - iDmdtRelax)*iDmdt + iDmdtRelax*iDmdtNew;
|
||||
|
||||
if (massTransfer_ )
|
||||
{
|
||||
Info<< "iDmdt." << pair.name()
|
||||
<< ": min = " << min(iDmdt.primitiveField())
|
||||
<< ", mean = " << average(iDmdt.primitiveField())
|
||||
<< ", max = " << max(iDmdt.primitiveField())
|
||||
<< ", integral = " << fvc::domainIntegrate(iDmdt).value()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Accumulate dmdt contributions from boundaries
|
||||
volScalarField wDmdt
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::groupName("wDmdt", pair.name()),
|
||||
this->mesh().time().timeName(),
|
||||
this->mesh(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE,
|
||||
false
|
||||
),
|
||||
this->mesh(),
|
||||
dimensionedScalar(dimDensity/dimTime, Zero)
|
||||
);
|
||||
|
||||
const volScalarField* alphatPtr =
|
||||
phase2.mesh().findObject<volScalarField>
|
||||
(
|
||||
"alphat." + phase2.name()
|
||||
);
|
||||
|
||||
if (alphatPtr)
|
||||
{
|
||||
const volScalarField& alphat = *alphatPtr;
|
||||
|
||||
const fvPatchList& patches = this->mesh().boundary();
|
||||
forAll(patches, patchi)
|
||||
{
|
||||
const fvPatch& currPatch = patches[patchi];
|
||||
|
||||
if
|
||||
(
|
||||
isA<alphatPhaseChangeWallFunction>
|
||||
(
|
||||
alphat.boundaryField()[patchi]
|
||||
)
|
||||
)
|
||||
{
|
||||
const scalarField& patchDmdt =
|
||||
refCast<const alphatPhaseChangeWallFunction>
|
||||
(
|
||||
alphat.boundaryField()[patchi]
|
||||
).dmdt();
|
||||
|
||||
forAll(patchDmdt,facei)
|
||||
{
|
||||
label faceCelli = currPatch.faceCells()[facei];
|
||||
wDmdt[faceCelli] += patchDmdt[facei];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "wDmdt." << pair.name()
|
||||
<< ": min = " << min(wDmdt.primitiveField())
|
||||
<< ", mean = " << average(wDmdt.primitiveField())
|
||||
<< ", max = " << max(wDmdt.primitiveField())
|
||||
<< ", integral = " << fvc::domainIntegrate(wDmdt).value()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
dmdt = wDmdt + iDmdt;
|
||||
|
||||
Info<< "dmdt." << pair.name()
|
||||
<< ": min = " << min(dmdt.primitiveField())
|
||||
<< ", mean = " << average(dmdt.primitiveField())
|
||||
<< ", max = " << max(dmdt.primitiveField())
|
||||
<< ", integral = " << fvc::domainIntegrate(dmdt).value()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class BasePhaseSystem>
|
||||
bool Foam::ThermalPhaseChangePhaseSystem<BasePhaseSystem>::read()
|
||||
{
|
||||
if (BasePhaseSystem::read())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,377 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd |
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2015-2016 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::phaseSystem
|
||||
|
||||
Description
|
||||
Class to represent a system of phases and model interfacial transfers
|
||||
between them.
|
||||
|
||||
SourceFiles
|
||||
phaseSystem.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef phaseSystem_H
|
||||
#define phaseSystem_H
|
||||
|
||||
#include "IOdictionary.H"
|
||||
|
||||
#include "phaseModel.H"
|
||||
#include "phasePair.H"
|
||||
#include "orderedPhasePair.H"
|
||||
#include "HashPtrTable.H"
|
||||
#include "PtrListDictionary.H"
|
||||
|
||||
#include "IOMRFZoneList.H"
|
||||
#include "fvOptions.H"
|
||||
|
||||
#include "volFields.H"
|
||||
#include "surfaceFields.H"
|
||||
#include "fvMatricesFwd.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
class blendingMethod;
|
||||
template<class modelType> class BlendedInterfacialModel;
|
||||
class surfaceTensionModel;
|
||||
class aspectRatioModel;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class phaseSystem Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class phaseSystem
|
||||
:
|
||||
public IOdictionary
|
||||
{
|
||||
public:
|
||||
|
||||
// Public typedefs
|
||||
|
||||
typedef
|
||||
HashPtrTable
|
||||
<
|
||||
volScalarField,
|
||||
phasePairKey,
|
||||
phasePairKey::hash
|
||||
>
|
||||
KdTable;
|
||||
|
||||
typedef
|
||||
HashPtrTable
|
||||
<
|
||||
volScalarField,
|
||||
phasePairKey,
|
||||
phasePairKey::hash
|
||||
>
|
||||
VmTable;
|
||||
|
||||
typedef
|
||||
HashPtrTable
|
||||
<
|
||||
fvVectorMatrix,
|
||||
word,
|
||||
string::hash
|
||||
>
|
||||
momentumTransferTable;
|
||||
|
||||
typedef
|
||||
HashPtrTable
|
||||
<
|
||||
fvScalarMatrix,
|
||||
word,
|
||||
string::hash
|
||||
>
|
||||
heatTransferTable;
|
||||
|
||||
typedef
|
||||
HashPtrTable
|
||||
<
|
||||
fvScalarMatrix,
|
||||
word,
|
||||
string::hash
|
||||
>
|
||||
massTransferTable;
|
||||
|
||||
typedef PtrListDictionary<phaseModel> phaseModelList;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected typedefs
|
||||
|
||||
typedef
|
||||
HashTable<dictionary, phasePairKey, phasePairKey::hash>
|
||||
dictTable;
|
||||
|
||||
typedef
|
||||
HashTable<autoPtr<phasePair>, phasePairKey, phasePairKey::hash>
|
||||
phasePairTable;
|
||||
|
||||
typedef
|
||||
HashTable<autoPtr<blendingMethod>>
|
||||
blendingMethodTable;
|
||||
|
||||
typedef
|
||||
HashTable
|
||||
<
|
||||
autoPtr<surfaceTensionModel>,
|
||||
phasePairKey,
|
||||
phasePairKey::hash
|
||||
>
|
||||
surfaceTensionModelTable;
|
||||
|
||||
typedef
|
||||
HashTable
|
||||
<
|
||||
autoPtr<aspectRatioModel>,
|
||||
phasePairKey,
|
||||
phasePairKey::hash
|
||||
>
|
||||
aspectRatioModelTable;
|
||||
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Reference to the mesh
|
||||
const fvMesh& mesh_;
|
||||
|
||||
//- Phase models
|
||||
phaseModelList phaseModels_;
|
||||
|
||||
//- Phase pairs
|
||||
phasePairTable phasePairs_;
|
||||
|
||||
//- Total volumetric flux
|
||||
surfaceScalarField phi_;
|
||||
|
||||
//- Rate of change of pressure
|
||||
volScalarField dpdt_;
|
||||
|
||||
//- Optional MRF zones
|
||||
IOMRFZoneList MRF_;
|
||||
|
||||
//- Blending methods
|
||||
blendingMethodTable blendingMethods_;
|
||||
|
||||
|
||||
// Sub Models
|
||||
|
||||
//- Surface tension models
|
||||
surfaceTensionModelTable surfaceTensionModels_;
|
||||
|
||||
//- Aspect ratio models
|
||||
aspectRatioModelTable aspectRatioModels_;
|
||||
|
||||
|
||||
// Protected member functions
|
||||
|
||||
//- Calculate and return the mixture flux
|
||||
tmp<surfaceScalarField> calcPhi
|
||||
(
|
||||
const phaseModelList& phaseModels
|
||||
) const;
|
||||
|
||||
//- Generate pairs
|
||||
void generatePairs
|
||||
(
|
||||
const dictTable& modelDicts
|
||||
);
|
||||
|
||||
//- Generate pairs and sub-model tables
|
||||
template<class modelType>
|
||||
void createSubModels
|
||||
(
|
||||
const dictTable& modelDicts,
|
||||
HashTable
|
||||
<
|
||||
autoPtr<modelType>,
|
||||
phasePairKey,
|
||||
phasePairKey::hash
|
||||
>& models
|
||||
);
|
||||
|
||||
//- Generate pairs and sub-model tables
|
||||
template<class modelType>
|
||||
void generatePairsAndSubModels
|
||||
(
|
||||
const word& modelName,
|
||||
HashTable
|
||||
<
|
||||
autoPtr<modelType>,
|
||||
phasePairKey,
|
||||
phasePairKey::hash
|
||||
>& models
|
||||
);
|
||||
|
||||
//- Generate pairs and blended sub-model tables
|
||||
template<class modelType>
|
||||
void generatePairsAndSubModels
|
||||
(
|
||||
const word& modelName,
|
||||
HashTable
|
||||
<
|
||||
autoPtr<BlendedInterfacialModel<modelType>>,
|
||||
phasePairKey,
|
||||
phasePairKey::hash
|
||||
>& models
|
||||
);
|
||||
|
||||
//- Generate pairs and per-phase sub-model tables
|
||||
template<class modelType>
|
||||
void generatePairsAndSubModels
|
||||
(
|
||||
const word& modelName,
|
||||
HashTable
|
||||
<
|
||||
HashTable<autoPtr<modelType>>,
|
||||
phasePairKey,
|
||||
phasePairKey::hash
|
||||
>& models
|
||||
);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("phaseSystem");
|
||||
|
||||
//- Default name of the phase properties dictionary
|
||||
static const word propertiesName;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from fvMesh
|
||||
phaseSystem(const fvMesh& mesh);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~phaseSystem();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Constant access the mesh
|
||||
inline const fvMesh& mesh() const;
|
||||
|
||||
//- Constant access the phase models
|
||||
inline const phaseModelList& phases() const;
|
||||
|
||||
//- Access the phase models
|
||||
inline phaseModelList& phases();
|
||||
|
||||
//- Constant access the phase pairs
|
||||
inline const phasePairTable& phasePairs() const;
|
||||
|
||||
//- Return the mixture density
|
||||
tmp<volScalarField> rho() const;
|
||||
|
||||
//- Return the mixture velocity
|
||||
tmp<volVectorField> U() const;
|
||||
|
||||
//- Constant access the mixture flux
|
||||
inline const surfaceScalarField& phi() const;
|
||||
|
||||
//- Access the mixture flux
|
||||
inline surfaceScalarField& phi();
|
||||
|
||||
//- Constant access the rate of change of the pressure
|
||||
inline const volScalarField& dpdt() const;
|
||||
|
||||
//- Access the rate of change of the pressure
|
||||
inline volScalarField& dpdt();
|
||||
|
||||
//- Return the aspect-ratio
|
||||
tmp<volScalarField> E(const phasePairKey& key) const;
|
||||
|
||||
//- Return the surface tension coefficient
|
||||
tmp<volScalarField> sigma(const phasePairKey& key) const;
|
||||
|
||||
//- Return MRF zones
|
||||
inline const IOMRFZoneList& MRF() const;
|
||||
|
||||
//- Optional FV-options
|
||||
inline fv::options& fvOptions() const;
|
||||
|
||||
//- Access a sub model between a phase pair
|
||||
template<class modelType>
|
||||
const modelType& lookupSubModel(const phasePair& key) const;
|
||||
|
||||
//- Access a sub model between two phases
|
||||
template<class modelType>
|
||||
const modelType& lookupSubModel
|
||||
(
|
||||
const phaseModel& dispersed,
|
||||
const phaseModel& continuous
|
||||
) const;
|
||||
|
||||
//- Solve for the phase fractions
|
||||
virtual void solve();
|
||||
|
||||
//- Correct the fluid properties other than the thermo and turbulence
|
||||
virtual void correct();
|
||||
|
||||
//- Correct the kinematics
|
||||
virtual void correctKinematics();
|
||||
|
||||
//- Correct the thermodynamics
|
||||
virtual void correctThermo();
|
||||
|
||||
//- Correct the turbulence
|
||||
virtual void correctTurbulence();
|
||||
|
||||
//- Correct the energy transport e.g. alphat
|
||||
virtual void correctEnergyTransport();
|
||||
|
||||
//- Read base phaseProperties dictionary
|
||||
virtual bool read();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "phaseSystemI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "phaseSystemTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,225 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd |
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2015-2017 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "BlendedInterfacialModel.H"
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class modelType>
|
||||
void Foam::phaseSystem::createSubModels
|
||||
(
|
||||
const dictTable& modelDicts,
|
||||
HashTable
|
||||
<
|
||||
autoPtr<modelType>,
|
||||
phasePairKey,
|
||||
phasePairKey::hash
|
||||
>& models
|
||||
)
|
||||
{
|
||||
forAllConstIters(modelDicts, iter)
|
||||
{
|
||||
const phasePairKey& key = iter.key();
|
||||
|
||||
models.insert
|
||||
(
|
||||
key,
|
||||
modelType::New
|
||||
(
|
||||
iter.val(),
|
||||
phasePairs_[key]()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class modelType>
|
||||
void Foam::phaseSystem::generatePairsAndSubModels
|
||||
(
|
||||
const word& modelName,
|
||||
HashTable
|
||||
<
|
||||
autoPtr<modelType>,
|
||||
phasePairKey,
|
||||
phasePairKey::hash
|
||||
>& models
|
||||
)
|
||||
{
|
||||
dictTable modelDicts(lookup(modelName));
|
||||
|
||||
generatePairs(modelDicts);
|
||||
|
||||
createSubModels(modelDicts, models);
|
||||
}
|
||||
|
||||
|
||||
template<class modelType>
|
||||
void Foam::phaseSystem::generatePairsAndSubModels
|
||||
(
|
||||
const word& modelName,
|
||||
HashTable
|
||||
<
|
||||
autoPtr<BlendedInterfacialModel<modelType>>,
|
||||
phasePairKey,
|
||||
phasePairKey::hash
|
||||
>& models
|
||||
)
|
||||
{
|
||||
typedef
|
||||
HashTable<autoPtr<modelType>, phasePairKey, phasePairKey::hash>
|
||||
modelTypeTable;
|
||||
|
||||
modelTypeTable tempModels;
|
||||
generatePairsAndSubModels(modelName, tempModels);
|
||||
|
||||
const blendingMethod& blending
|
||||
(
|
||||
blendingMethods_.found(modelName)
|
||||
? *(blendingMethods_[modelName])
|
||||
: *(blendingMethods_["default"])
|
||||
);
|
||||
|
||||
autoPtr<modelType> noModel;
|
||||
|
||||
forAllConstIters(tempModels, iter)
|
||||
{
|
||||
if (!iter().valid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const phasePairKey key(iter.key().first(), iter.key().second());
|
||||
const phasePairKey key1In2(key.first(), key.second(), true);
|
||||
const phasePairKey key2In1(key.second(), key.first(), true);
|
||||
|
||||
models.insert
|
||||
(
|
||||
key,
|
||||
autoPtr<BlendedInterfacialModel<modelType>>
|
||||
(
|
||||
new BlendedInterfacialModel<modelType>
|
||||
(
|
||||
phaseModels_[key.first()],
|
||||
phaseModels_[key.second()],
|
||||
blending,
|
||||
tempModels.found(key ) ? tempModels[key ] : noModel,
|
||||
tempModels.found(key1In2) ? tempModels[key1In2] : noModel,
|
||||
tempModels.found(key2In1) ? tempModels[key2In1] : noModel
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if (!phasePairs_.found(key))
|
||||
{
|
||||
phasePairs_.insert
|
||||
(
|
||||
key,
|
||||
autoPtr<phasePair>
|
||||
(
|
||||
new phasePair
|
||||
(
|
||||
phaseModels_[key.first()],
|
||||
phaseModels_[key.second()]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class modelType>
|
||||
void Foam::phaseSystem::generatePairsAndSubModels
|
||||
(
|
||||
const word& modelName,
|
||||
HashTable
|
||||
<
|
||||
HashTable<autoPtr<modelType>>,
|
||||
phasePairKey,
|
||||
phasePairKey::hash
|
||||
>& models
|
||||
)
|
||||
{
|
||||
typedef
|
||||
HashTable<autoPtr<modelType>, phasePairKey, phasePairKey::hash>
|
||||
modelTypeTable;
|
||||
|
||||
for (const phaseModel& phase : phaseModels_)
|
||||
{
|
||||
modelTypeTable tempModels;
|
||||
generatePairsAndSubModels
|
||||
(
|
||||
IOobject::groupName(modelName, phase.name()),
|
||||
tempModels
|
||||
);
|
||||
|
||||
forAllConstIters(tempModels, tempModelIter)
|
||||
{
|
||||
const phasePairKey& key = tempModelIter.key();
|
||||
|
||||
if (!models.found(key))
|
||||
{
|
||||
models.insert
|
||||
(
|
||||
key,
|
||||
HashTable<autoPtr<modelType>>()
|
||||
);
|
||||
}
|
||||
|
||||
models[tempModelIter.key()].insert
|
||||
(
|
||||
phase.name(),
|
||||
*tempModelIter
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class modelType>
|
||||
const modelType& Foam::phaseSystem::lookupSubModel(const phasePair& key) const
|
||||
{
|
||||
return
|
||||
mesh().lookupObject<modelType>
|
||||
(
|
||||
IOobject::groupName(modelType::typeName, key.name())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class modelType>
|
||||
const modelType& Foam::phaseSystem::lookupSubModel
|
||||
(
|
||||
const phaseModel& dispersed,
|
||||
const phaseModel& continuous
|
||||
) const
|
||||
{
|
||||
return lookupSubModel<modelType>(orderedPhasePair(dispersed, continuous));
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -1,11 +1,9 @@
|
||||
#!/bin/sh
|
||||
cd ${0%/*} || exit 1 # Run from this directory
|
||||
|
||||
# Parse arguments for library compilation
|
||||
. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
wmake $targetType multiphaseSystem
|
||||
wmake $targetType multiphaseCompressibleTurbulenceModels
|
||||
wmake $targetType
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd |
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
| Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
@ -7,32 +7,27 @@ for (int Ecorr=0; Ecorr<nEnergyCorrectors; Ecorr++)
|
||||
|
||||
phaseSystem::heatTransferTable& heatTransfer = heatTransferPtr();
|
||||
|
||||
forAll(phases, phasei)
|
||||
forAll(fluid.anisothermalPhases(), anisothermalPhasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
phaseModel& phase = fluid.anisothermalPhases()[anisothermalPhasei];
|
||||
|
||||
const volScalarField& alpha = phase;
|
||||
const volScalarField& rho = phase.rho();
|
||||
const volVectorField& U = phase.U();
|
||||
|
||||
tmp<fvScalarMatrix> EEqn(phase.heEqn());
|
||||
|
||||
if (EEqn.valid())
|
||||
{
|
||||
EEqn =
|
||||
fvScalarMatrix EEqn
|
||||
(
|
||||
EEqn
|
||||
phase.heEqn()
|
||||
==
|
||||
*heatTransfer[phase.name()]
|
||||
+ alpha*rho*(U&g)
|
||||
+ fvOptions(alpha, rho, phase.thermo().he())
|
||||
+ fvOptions(alpha, rho, phase.thermoRef().he())
|
||||
);
|
||||
|
||||
EEqn->relax();
|
||||
fvOptions.constrain(EEqn.ref());
|
||||
EEqn->solve();
|
||||
fvOptions.correct(phase.thermo().he());
|
||||
}
|
||||
EEqn.relax();
|
||||
fvOptions.constrain(EEqn);
|
||||
EEqn.solve();
|
||||
fvOptions.correct(phase.thermoRef().he());
|
||||
}
|
||||
|
||||
fluid.correctThermo();
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
EXE_INC = \
|
||||
-ImultiphaseSystem/lnInclude \
|
||||
-I../phaseSystems/lnInclude \
|
||||
-I../interfacialModels/lnInclude \
|
||||
-I../interfacialCompositionModels/lnInclude \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/sampling/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/reactingMultiphaseEulerFoam/multiphaseSystem/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/phaseSystems/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/interfacialModels/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/interfacialCompositionModels/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/reactingMultiphaseEulerFoam/multiphaseCompressibleTurbulenceModels/lnInclude \
|
||||
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
|
||||
-I$(LIB_SRC)/transportModels/compressible/lnInclude \
|
||||
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
|
||||
-I$(LIB_SRC)/TurbulenceModels/compressible/lnInclude \
|
||||
-I$(LIB_SRC)/TurbulenceModels/compressible/turbulentFluidThermoModels/turbulentFluidFvPatchFields/lnInclude \
|
||||
-I$(LIB_SRC)/TurbulenceModels/phaseCompressible/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
|
||||
@ -5,33 +5,26 @@
|
||||
phaseSystem::massTransferTable&
|
||||
massTransfer(massTransferPtr());
|
||||
|
||||
forAll(phases, phasei)
|
||||
forAll(fluid.multiComponentPhases(), multiComponentPhasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
phaseModel& phase = fluid.multiComponentPhases()[multiComponentPhasei];
|
||||
|
||||
PtrList<volScalarField>& Y = phase.Y();
|
||||
UPtrList<volScalarField>& Y = phase.YActiveRef();
|
||||
const volScalarField& alpha = phase;
|
||||
const volScalarField& rho = phase.rho();
|
||||
|
||||
forAll(Y, i)
|
||||
{
|
||||
tmp<fvScalarMatrix> YiEqn(phase.YiEqn(Y[i]));
|
||||
|
||||
if (YiEqn.valid())
|
||||
{
|
||||
YiEqn =
|
||||
fvScalarMatrix YiEqn
|
||||
(
|
||||
YiEqn
|
||||
phase.YiEqn(Y[i])
|
||||
==
|
||||
*massTransfer[Y[i].name()]
|
||||
+ fvOptions(alpha, rho, Y[i])
|
||||
);
|
||||
|
||||
YiEqn->relax();
|
||||
YiEqn->solve(mesh.solver("Yi"));
|
||||
YiEqn.relax();
|
||||
YiEqn.solve(mesh.solver("Yi"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fluid.massTransfer(); // updates interfacial mass flow rates
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ dimensionedScalar pMin
|
||||
|
||||
#include "gh.H"
|
||||
|
||||
volScalarField& p = phases[0].thermo().p();
|
||||
volScalarField& p = phases[0].thermoRef().p();
|
||||
|
||||
Info<< "Reading field p_rgh\n" << endl;
|
||||
volScalarField p_rgh
|
||||
|
||||
@ -9,17 +9,17 @@ PtrList<fvVectorMatrix> UEqns(phases.size());
|
||||
phaseSystem::momentumTransferTable&
|
||||
momentumTransfer(momentumTransferPtr());
|
||||
|
||||
forAll(phases, phasei)
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
|
||||
const volScalarField& alpha = phase;
|
||||
const volScalarField& rho = phase.rho();
|
||||
volVectorField& U = phase.U();
|
||||
volVectorField& U = phase.URef();
|
||||
|
||||
UEqns.set
|
||||
(
|
||||
phasei,
|
||||
phase.index(),
|
||||
new fvVectorMatrix
|
||||
(
|
||||
phase.UEqn()
|
||||
@ -29,8 +29,8 @@ PtrList<fvVectorMatrix> UEqns(phases.size());
|
||||
)
|
||||
);
|
||||
|
||||
UEqns[phasei].relax();
|
||||
fvOptions.constrain(UEqns[phasei]);
|
||||
UEqns[phase.index()].relax();
|
||||
fvOptions.constrain(UEqns[phase.index()]);
|
||||
fvOptions.correct(U);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
// Face volume fractions
|
||||
PtrList<surfaceScalarField> alphafs(phases.size());
|
||||
PtrList<volScalarField> rAUs(phases.size());
|
||||
PtrList<surfaceScalarField> alpharAUfs(phases.size());
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
@ -9,21 +7,37 @@ forAll(phases, phasei)
|
||||
|
||||
alphafs.set(phasei, fvc::interpolate(alpha).ptr());
|
||||
alphafs[phasei].rename("pEqn" + alphafs[phasei].name());
|
||||
}
|
||||
|
||||
// Diagonal coefficients
|
||||
PtrList<volScalarField> rAUs(phases.size());
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
const volScalarField& alpha = phase;
|
||||
|
||||
rAUs.set
|
||||
(
|
||||
phasei,
|
||||
phase.index(),
|
||||
new volScalarField
|
||||
(
|
||||
IOobject::groupName("rAU", phase.name()),
|
||||
1.0
|
||||
/(
|
||||
UEqns[phasei].A()
|
||||
+ max(phase.residualAlpha() - alpha, scalar(0))
|
||||
*phase.rho()/runTime.deltaT()
|
||||
UEqns[phase.index()].A()
|
||||
+ byDt(max(phase.residualAlpha() - alpha, scalar(0))*phase.rho())
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
fluid.fillFields("rAU", dimTime/dimDensity, rAUs);
|
||||
|
||||
// Phase diagonal coefficients
|
||||
PtrList<surfaceScalarField> alpharAUfs(phases.size());
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
const volScalarField& alpha = phase;
|
||||
|
||||
alpharAUfs.set
|
||||
(
|
||||
@ -34,57 +48,8 @@ forAll(phases, phasei)
|
||||
);
|
||||
}
|
||||
|
||||
// Lift, wall-lubrication and turbulent diffusion fluxes
|
||||
PtrList<surfaceScalarField> phiFs(phases.size());
|
||||
{
|
||||
autoPtr<PtrList<volVectorField>> Fs = fluid.Fs();
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
|
||||
if (Fs().set(phasei))
|
||||
{
|
||||
phiFs.set
|
||||
(
|
||||
phasei,
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject::groupName("phiF", phase.name()),
|
||||
fvc::flux(rAUs[phasei]*Fs()[phasei])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
autoPtr<PtrList<surfaceScalarField>> phiDs = fluid.phiDs(rAUs);
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
|
||||
if (phiDs().set(phasei))
|
||||
{
|
||||
if (phiFs.set(phasei))
|
||||
{
|
||||
phiFs[phasei] += phiDs()[phasei];
|
||||
}
|
||||
else
|
||||
{
|
||||
phiFs.set
|
||||
(
|
||||
phasei,
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject::groupName("phiF", phase.name()),
|
||||
phiDs()[phasei]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Explicit force fluxes
|
||||
PtrList<surfaceScalarField> phiFs(fluid.phiFs(rAUs));
|
||||
|
||||
// --- Pressure corrector loop
|
||||
while (pimple.correct())
|
||||
@ -94,42 +59,22 @@ while (pimple.correct())
|
||||
// Correct p_rgh for consistency with p and the updated densities
|
||||
p_rgh = p - rho*gh;
|
||||
|
||||
PtrList<volVectorField> HbyAs(phases.size());
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
const volScalarField& alpha = phase;
|
||||
|
||||
// Correct fixed-flux BCs to be consistent with the velocity BCs
|
||||
MRF.correctBoundaryFlux(phase.U(), phase.phi());
|
||||
|
||||
HbyAs.set
|
||||
(
|
||||
phasei,
|
||||
new volVectorField
|
||||
(
|
||||
IOobject::groupName("HbyA", phase.name()),
|
||||
phase.U()
|
||||
)
|
||||
);
|
||||
|
||||
HbyAs[phasei] =
|
||||
rAUs[phasei]
|
||||
*(
|
||||
UEqns[phasei].H()
|
||||
+ max(phase.residualAlpha() - alpha, scalar(0))
|
||||
*phase.rho()*phase.U().oldTime()/runTime.deltaT()
|
||||
);
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
MRF.correctBoundaryFlux(phase.U(), phase.phiRef());
|
||||
}
|
||||
|
||||
surfaceScalarField ghSnGradRho
|
||||
// Combined buoyancy and force fluxes
|
||||
PtrList<surfaceScalarField> phigFs(phases.size());
|
||||
{
|
||||
const surfaceScalarField ghSnGradRho
|
||||
(
|
||||
"ghSnGradRho",
|
||||
ghf*fvc::snGrad(rho)*mesh.magSf()
|
||||
);
|
||||
|
||||
PtrList<surfaceScalarField> phigFs(phases.size());
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
@ -152,9 +97,78 @@ while (pimple.correct())
|
||||
phigFs[phasei] += phiFs[phasei];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Predicted velocities and fluxes for each phase
|
||||
PtrList<volVectorField> HbyAs(phases.size());
|
||||
PtrList<surfaceScalarField> phiHbyAs(phases.size());
|
||||
{
|
||||
// Correction force fluxes
|
||||
PtrList<surfaceScalarField> ddtCorrByAs(fluid.ddtCorrByAs(rAUs));
|
||||
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
const volScalarField& alpha = phase;
|
||||
|
||||
HbyAs.set
|
||||
(
|
||||
phase.index(),
|
||||
new volVectorField
|
||||
(
|
||||
IOobject::groupName("HbyA", phase.name()),
|
||||
phase.U()
|
||||
)
|
||||
);
|
||||
|
||||
HbyAs[phase.index()] =
|
||||
rAUs[phase.index()]
|
||||
*(
|
||||
UEqns[phase.index()].H()
|
||||
+ byDt
|
||||
(
|
||||
max(phase.residualAlpha() - alpha, scalar(0))
|
||||
*phase.rho()
|
||||
)
|
||||
*phase.U()().oldTime()
|
||||
);
|
||||
|
||||
phiHbyAs.set
|
||||
(
|
||||
phase.index(),
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject::groupName("phiHbyA", phase.name()),
|
||||
fvc::flux(HbyAs[phase.index()])
|
||||
- phigFs[phase.index()]
|
||||
- ddtCorrByAs[phase.index()]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
fluid.fillFields("HbyA", dimVelocity, HbyAs);
|
||||
fluid.fillFields("phiHbyA", dimForce/dimDensity/dimVelocity, phiHbyAs);
|
||||
|
||||
// Add explicit drag forces and fluxes if not doing partial elimination
|
||||
if (!partialElimination)
|
||||
{
|
||||
PtrList<volVectorField> KdUByAs(fluid.KdUByAs(rAUs));
|
||||
PtrList<surfaceScalarField> phiKdPhis(fluid.phiKdPhis(rAUs));
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
if (KdUByAs.set(phasei))
|
||||
{
|
||||
HbyAs[phasei] -= KdUByAs[phasei];
|
||||
}
|
||||
if (phiKdPhis.set(phasei))
|
||||
{
|
||||
phiHbyAs[phasei] -= phiKdPhis[phasei];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Total predicted flux
|
||||
surfaceScalarField phiHbyA
|
||||
(
|
||||
IOobject
|
||||
@ -166,84 +180,28 @@ while (pimple.correct())
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
mesh,
|
||||
dimensionedScalar(dimArea*dimVelocity, Zero)
|
||||
dimensionedScalar("phiHbyA", dimArea*dimVelocity, 0)
|
||||
);
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
const volScalarField& alpha = phase;
|
||||
|
||||
// ddtPhiCorr filter -- only apply in pure(ish) phases
|
||||
surfaceScalarField alphafBar
|
||||
(
|
||||
fvc::interpolate(fvc::average(alphafs[phasei]))
|
||||
);
|
||||
surfaceScalarField phiCorrCoeff(pos0(alphafBar - 0.99));
|
||||
|
||||
surfaceScalarField::Boundary& phiCorrCoeffBf =
|
||||
phiCorrCoeff.boundaryFieldRef();
|
||||
|
||||
forAll(mesh.boundary(), patchi)
|
||||
{
|
||||
// Set ddtPhiCorr to 0 on non-coupled boundaries
|
||||
if
|
||||
(
|
||||
!mesh.boundary()[patchi].coupled()
|
||||
|| isA<cyclicAMIFvPatch>(mesh.boundary()[patchi])
|
||||
)
|
||||
{
|
||||
phiCorrCoeffBf[patchi] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
phiHbyAs.set
|
||||
(
|
||||
phasei,
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject::groupName("phiHbyA", phase.name()),
|
||||
fvc::flux(HbyAs[phasei])
|
||||
+ phiCorrCoeff
|
||||
*fvc::interpolate
|
||||
(
|
||||
alpha.oldTime()*phase.rho()().oldTime()*rAUs[phasei]
|
||||
)
|
||||
*(
|
||||
MRF.absolute(phase.phi().oldTime())
|
||||
- fvc::flux(phase.U().oldTime())
|
||||
)/runTime.deltaT()
|
||||
- phigFs[phasei]
|
||||
)
|
||||
);
|
||||
|
||||
forAllConstIters(fluid.Kds(), KdIter)
|
||||
{
|
||||
const volScalarField& K(*KdIter());
|
||||
|
||||
const phasePair& pair = *(fluid.phasePairs()[KdIter.key()]);
|
||||
|
||||
const phaseModel* phase1 = &pair.phase1();
|
||||
const phaseModel* phase2 = &pair.phase2();
|
||||
|
||||
forAllConstIters(pair, iter)
|
||||
{
|
||||
if (phase1 == &phase)
|
||||
{
|
||||
phiHbyAs[phasei] +=
|
||||
fvc::interpolate(rAUs[phasei]*K)
|
||||
*MRF.absolute(phase2->phi());
|
||||
|
||||
HbyAs[phasei] += rAUs[phasei]*K*phase2->U();
|
||||
}
|
||||
|
||||
Swap(phase1, phase2);
|
||||
}
|
||||
}
|
||||
|
||||
phiHbyA += alphafs[phasei]*phiHbyAs[phasei];
|
||||
}
|
||||
|
||||
// Add explicit drag fluxes if doing partial elimination
|
||||
if (partialElimination)
|
||||
{
|
||||
PtrList<surfaceScalarField> phiKdPhis(fluid.phiKdPhis(rAUs));
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
if (phiKdPhis.set(phasei))
|
||||
{
|
||||
phiHbyA -= alphafs[phasei]*phiKdPhis[phasei];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MRF.makeRelative(phiHbyA);
|
||||
|
||||
// Construct pressure "diffusivity"
|
||||
@ -256,15 +214,15 @@ while (pimple.correct())
|
||||
mesh
|
||||
),
|
||||
mesh,
|
||||
dimensionedScalar(dimensionSet(-1, 3, 1, 0, 0), Zero)
|
||||
dimensionedScalar("rAUf", dimensionSet(-1, 3, 1, 0, 0), 0)
|
||||
);
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
rAUf += alphafs[phasei]*alpharAUfs[phasei];
|
||||
}
|
||||
rAUf = mag(rAUf);
|
||||
|
||||
rAUf = mag(rAUf);
|
||||
|
||||
// Update the fixedFluxPressure BCs to ensure flux consistency
|
||||
{
|
||||
@ -273,7 +231,8 @@ while (pimple.correct())
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
phib += alphafs[phasei].boundaryField()*phase.phi().boundaryField();
|
||||
phib +=
|
||||
alphafs[phasei].boundaryField()*phase.phi()().boundaryField();
|
||||
}
|
||||
|
||||
setSnGrad<fixedFluxPressureFvPatchScalarField>
|
||||
@ -285,12 +244,14 @@ while (pimple.correct())
|
||||
);
|
||||
}
|
||||
|
||||
// Compressible pressure equations
|
||||
PtrList<fvScalarMatrix> pEqnComps(phases.size());
|
||||
PtrList<volScalarField> dmdts(fluid.dmdts());
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
const volScalarField& alpha = phase;
|
||||
volScalarField& rho = phase.thermo().rho();
|
||||
volScalarField& rho = phase.thermoRef().rho();
|
||||
|
||||
if (phase.compressible())
|
||||
{
|
||||
@ -307,7 +268,7 @@ while (pimple.correct())
|
||||
phasei,
|
||||
(
|
||||
(
|
||||
phase.continuityError()
|
||||
fvc::ddt(alpha, rho) + fvc::div(phase.alphaRhoPhi())
|
||||
- fvc::Sp
|
||||
(
|
||||
fvc::ddt(alpha) + fvc::div(phase.alphaPhi()),
|
||||
@ -335,7 +296,7 @@ while (pimple.correct())
|
||||
phasei,
|
||||
(
|
||||
(
|
||||
phase.continuityError()
|
||||
fvc::ddt(alpha, rho) + fvc::div(phase.alphaRhoPhi())
|
||||
- fvc::Sp
|
||||
(
|
||||
(fvc::ddt(alpha) + fvc::div(phase.alphaPhi())),
|
||||
@ -348,27 +309,38 @@ while (pimple.correct())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add option sources
|
||||
if (fvOptions.appliesToField(rho.name()))
|
||||
{
|
||||
tmp<fvScalarMatrix> optEqn = fvOptions(alpha, rho);
|
||||
if (pEqnComps.set(phasei))
|
||||
{
|
||||
pEqnComps[phasei] -= (optEqn&rho)/rho;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComps.set
|
||||
(
|
||||
phasei,
|
||||
fvm::Su(-(fvOptions(alpha, rho)&rho)/rho, p_rgh).ptr()
|
||||
fvm::Su(- (optEqn&rho)/rho, p_rgh).ptr()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (fluid.transfersMass(phase))
|
||||
// Add mass transfer
|
||||
if (dmdts.set(phasei))
|
||||
{
|
||||
if (pEqnComps.set(phasei))
|
||||
{
|
||||
pEqnComps[phasei] -= fluid.dmdt(phase)/rho;
|
||||
pEqnComps[phasei] -= dmdts[phasei]/rho;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComps.set
|
||||
(
|
||||
phasei,
|
||||
fvm::Su(-fluid.dmdt(phase)/rho, p_rgh)
|
||||
fvm::Su(- dmdts[phasei]/rho, p_rgh)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -412,16 +384,18 @@ while (pimple.correct())
|
||||
|
||||
surfaceScalarField mSfGradp("mSfGradp", pEqnIncomp.flux()/rAUf);
|
||||
|
||||
forAll(phases, phasei)
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
|
||||
phase.phi() = phiHbyAs[phasei] + alpharAUfs[phasei]*mSfGradp;
|
||||
phase.phiRef() =
|
||||
phiHbyAs[phase.index()]
|
||||
+ alpharAUfs[phase.index()]*mSfGradp;
|
||||
|
||||
// Set the phase dilatation rates
|
||||
if (pEqnComps.set(phasei))
|
||||
if (pEqnComps.set(phase.index()))
|
||||
{
|
||||
phase.divU(-pEqnComps[phasei] & p_rgh);
|
||||
phase.divU(-pEqnComps[phase.index()] & p_rgh);
|
||||
}
|
||||
}
|
||||
|
||||
@ -430,19 +404,30 @@ while (pimple.correct())
|
||||
|
||||
mSfGradp = pEqnIncomp.flux()/rAUf;
|
||||
|
||||
forAll(phases, phasei)
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
|
||||
phase.U() =
|
||||
HbyAs[phasei]
|
||||
phase.URef() =
|
||||
HbyAs[phase.index()]
|
||||
+ fvc::reconstruct
|
||||
(
|
||||
alpharAUfs[phasei]*mSfGradp
|
||||
- phigFs[phasei]
|
||||
alpharAUfs[phase.index()]*mSfGradp
|
||||
- phigFs[phase.index()]
|
||||
);
|
||||
phase.U().correctBoundaryConditions();
|
||||
fvOptions.correct(phase.U());
|
||||
}
|
||||
|
||||
if (partialElimination)
|
||||
{
|
||||
fluid.partialElimination(rAUs);
|
||||
}
|
||||
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
|
||||
phase.URef().correctBoundaryConditions();
|
||||
fvOptions.correct(phase.URef());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -457,7 +442,7 @@ while (pimple.correct())
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
phase.thermo().rho() += phase.thermo().psi()*(p_rgh - p_rgh_0);
|
||||
phase.thermoRef().rho() += phase.thermo().psi()*(p_rgh - p_rgh_0);
|
||||
}
|
||||
|
||||
// Correct p_rgh for consistency with p and the updated densities
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
Info<< "Constructing face momentum equations" << endl;
|
||||
|
||||
PtrList<fvVectorMatrix> UEqns(phases.size());
|
||||
|
||||
{
|
||||
fluid.momentumTransfer(); // !!! Update coefficients shouldn't be necessary
|
||||
// This should be done on demand
|
||||
|
||||
autoPtr<phaseSystem::momentumTransferTable>
|
||||
momentumTransferPtr(fluid.momentumTransferf());
|
||||
|
||||
phaseSystem::momentumTransferTable&
|
||||
momentumTransfer(momentumTransferPtr());
|
||||
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
|
||||
const volScalarField& alpha = phase;
|
||||
const volScalarField& rho = phase.rho();
|
||||
volVectorField& U = phase.URef();
|
||||
|
||||
UEqns.set
|
||||
(
|
||||
phase.index(),
|
||||
new fvVectorMatrix
|
||||
(
|
||||
phase.UfEqn()
|
||||
==
|
||||
*momentumTransfer[phase.name()]
|
||||
+ fvOptions(alpha, rho, U)
|
||||
)
|
||||
);
|
||||
|
||||
UEqns[phase.index()].relax();
|
||||
fvOptions.constrain(UEqns[phase.index()]);
|
||||
U.correctBoundaryConditions();
|
||||
fvOptions.correct(U);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,428 @@
|
||||
// Face volume fractions
|
||||
PtrList<surfaceScalarField> alphafs(phases.size());
|
||||
PtrList<surfaceScalarField> alphaRho0fs(phases.size());
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
const volScalarField& alpha = phase;
|
||||
|
||||
alphafs.set(phasei, fvc::interpolate(alpha).ptr());
|
||||
alphafs[phasei].rename("pEqn" + alphafs[phasei].name());
|
||||
|
||||
alphaRho0fs.set
|
||||
(
|
||||
phasei,
|
||||
(
|
||||
fvc::interpolate
|
||||
(
|
||||
max(alpha.oldTime(), phase.residualAlpha())
|
||||
*phase.rho()().oldTime()
|
||||
)
|
||||
).ptr()
|
||||
);
|
||||
}
|
||||
|
||||
// Diagonal coefficients
|
||||
PtrList<surfaceScalarField> rAUfs(phases.size());
|
||||
{
|
||||
PtrList<surfaceScalarField> AFfs(fluid.AFfs());
|
||||
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
|
||||
rAUfs.set
|
||||
(
|
||||
phase.index(),
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject::groupName("rAUf", phase.name()),
|
||||
1.0
|
||||
/(
|
||||
byDt(alphaRho0fs[phase.index()])
|
||||
+ fvc::interpolate(UEqns[phase.index()].A())
|
||||
+ AFfs[phase.index()]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
fluid.fillFields("rAUf", dimTime/dimDensity, rAUfs);
|
||||
|
||||
// Phase diagonal coefficients
|
||||
PtrList<surfaceScalarField> alpharAUfs(phases.size());
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
alpharAUfs.set
|
||||
(
|
||||
phase.index(),
|
||||
(
|
||||
max(alphafs[phase.index()], phase.residualAlpha())
|
||||
*rAUfs[phase.index()]
|
||||
).ptr()
|
||||
);
|
||||
}
|
||||
|
||||
// Explicit force fluxes
|
||||
PtrList<surfaceScalarField> phiFfs(fluid.phiFfs(rAUfs));
|
||||
|
||||
// --- Pressure corrector loop
|
||||
while (pimple.correct())
|
||||
{
|
||||
volScalarField rho("rho", fluid.rho());
|
||||
|
||||
// Correct p_rgh for consistency with p and the updated densities
|
||||
p_rgh = p - rho*gh;
|
||||
|
||||
// Correct fixed-flux BCs to be consistent with the velocity BCs
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
MRF.correctBoundaryFlux(phase.U(), phase.phiRef());
|
||||
}
|
||||
|
||||
// Combined buoyancy and force fluxes
|
||||
PtrList<surfaceScalarField> phigFs(phases.size());
|
||||
{
|
||||
const surfaceScalarField ghSnGradRho
|
||||
(
|
||||
"ghSnGradRho",
|
||||
ghf*fvc::snGrad(rho)*mesh.magSf()
|
||||
);
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
|
||||
phigFs.set
|
||||
(
|
||||
phasei,
|
||||
(
|
||||
alpharAUfs[phasei]
|
||||
*(
|
||||
ghSnGradRho
|
||||
- (fvc::interpolate(phase.rho() - rho))*(g & mesh.Sf())
|
||||
- fluid.surfaceTension(phase)*mesh.magSf()
|
||||
)
|
||||
).ptr()
|
||||
);
|
||||
|
||||
if (phiFfs.set(phasei))
|
||||
{
|
||||
phigFs[phasei] += phiFfs[phasei];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Predicted fluxes for each phase
|
||||
PtrList<surfaceScalarField> phiHbyAs(phases.size());
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
|
||||
phiHbyAs.set
|
||||
(
|
||||
phase.index(),
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject::groupName("phiHbyA", phase.name()),
|
||||
rAUfs[phase.index()]
|
||||
*(
|
||||
fvc::flux(UEqns[phase.index()].H())
|
||||
+ alphaRho0fs[phase.index()]
|
||||
*byDt(MRF.absolute(phase.phi()().oldTime()))
|
||||
)
|
||||
- phigFs[phase.index()]
|
||||
)
|
||||
);
|
||||
}
|
||||
fluid.fillFields("phiHbyA", dimForce/dimDensity/dimVelocity, phiHbyAs);
|
||||
|
||||
// Add explicit drag forces and fluxes if not doing partial elimination
|
||||
if (!partialElimination)
|
||||
{
|
||||
PtrList<surfaceScalarField> phiKdPhifs(fluid.phiKdPhifs(rAUfs));
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
if (phiKdPhifs.set(phasei))
|
||||
{
|
||||
phiHbyAs[phasei] -= phiKdPhifs[phasei];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Total predicted flux
|
||||
surfaceScalarField phiHbyA
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"phiHbyA",
|
||||
runTime.timeName(),
|
||||
mesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
mesh,
|
||||
dimensionedScalar("phiHbyA", dimArea*dimVelocity, 0)
|
||||
);
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phiHbyA += alphafs[phasei]*phiHbyAs[phasei];
|
||||
}
|
||||
|
||||
// Add explicit drag fluxes if doing partial elimination
|
||||
if (partialElimination)
|
||||
{
|
||||
PtrList<surfaceScalarField> phiKdPhifs(fluid.phiKdPhifs(rAUfs));
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
if (phiKdPhifs.set(phasei))
|
||||
{
|
||||
phiHbyA -= alphafs[phasei]*phiKdPhifs[phasei];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MRF.makeRelative(phiHbyA);
|
||||
|
||||
// Construct pressure "diffusivity"
|
||||
surfaceScalarField rAUf
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"rAUf",
|
||||
runTime.timeName(),
|
||||
mesh
|
||||
),
|
||||
mesh,
|
||||
dimensionedScalar("rAUf", dimensionSet(-1, 3, 1, 0, 0), 0)
|
||||
);
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
rAUf += alphafs[phasei]*alpharAUfs[phasei];
|
||||
}
|
||||
|
||||
rAUf = mag(rAUf);
|
||||
|
||||
// Update the fixedFluxPressure BCs to ensure flux consistency
|
||||
{
|
||||
surfaceScalarField::Boundary phib(phi.boundaryField());
|
||||
phib = 0;
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
phib +=
|
||||
alphafs[phasei].boundaryField()*phase.phi()().boundaryField();
|
||||
}
|
||||
|
||||
setSnGrad<fixedFluxPressureFvPatchScalarField>
|
||||
(
|
||||
p_rgh.boundaryFieldRef(),
|
||||
(
|
||||
phiHbyA.boundaryField() - phib
|
||||
)/(mesh.magSf().boundaryField()*rAUf.boundaryField())
|
||||
);
|
||||
}
|
||||
|
||||
// Compressible pressure equations
|
||||
PtrList<fvScalarMatrix> pEqnComps(phases.size());
|
||||
PtrList<volScalarField> dmdts(fluid.dmdts());
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
const volScalarField& alpha = phase;
|
||||
volScalarField& rho = phase.thermoRef().rho();
|
||||
|
||||
if (phase.compressible())
|
||||
{
|
||||
if (pimple.transonic())
|
||||
{
|
||||
surfaceScalarField phid
|
||||
(
|
||||
IOobject::groupName("phid", phase.name()),
|
||||
fvc::interpolate(phase.thermo().psi())*phase.phi()
|
||||
);
|
||||
|
||||
pEqnComps.set
|
||||
(
|
||||
phasei,
|
||||
(
|
||||
(
|
||||
fvc::ddt(alpha, rho) + fvc::div(phase.alphaRhoPhi())
|
||||
- fvc::Sp
|
||||
(
|
||||
fvc::ddt(alpha) + fvc::div(phase.alphaPhi()),
|
||||
rho
|
||||
)
|
||||
)/rho
|
||||
+ correction
|
||||
(
|
||||
(alpha/rho)*
|
||||
(
|
||||
phase.thermo().psi()*fvm::ddt(p_rgh)
|
||||
+ fvm::div(phid, p_rgh)
|
||||
- fvm::Sp(fvc::div(phid), p_rgh)
|
||||
)
|
||||
)
|
||||
).ptr()
|
||||
);
|
||||
|
||||
deleteDemandDrivenData
|
||||
(
|
||||
pEqnComps[phasei].faceFluxCorrectionPtr()
|
||||
);
|
||||
|
||||
pEqnComps[phasei].relax();
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComps.set
|
||||
(
|
||||
phasei,
|
||||
(
|
||||
(
|
||||
fvc::ddt(alpha, rho) + fvc::div(phase.alphaRhoPhi())
|
||||
- fvc::Sp
|
||||
(
|
||||
(fvc::ddt(alpha) + fvc::div(phase.alphaPhi())),
|
||||
rho
|
||||
)
|
||||
)/rho
|
||||
+ (alpha*phase.thermo().psi()/rho)
|
||||
*correction(fvm::ddt(p_rgh))
|
||||
).ptr()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (fvOptions.appliesToField(rho.name()))
|
||||
{
|
||||
tmp<fvScalarMatrix> optEqn = fvOptions(alpha, rho);
|
||||
if (pEqnComps.set(phasei))
|
||||
{
|
||||
pEqnComps[phasei] -= (optEqn&rho)/rho;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComps.set
|
||||
(
|
||||
phasei,
|
||||
fvm::Su(- (optEqn&rho)/rho, p_rgh).ptr()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (dmdts.set(phasei))
|
||||
{
|
||||
if (pEqnComps.set(phasei))
|
||||
{
|
||||
pEqnComps[phasei] -= dmdts[phasei]/rho;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComps.set
|
||||
(
|
||||
phasei,
|
||||
fvm::Su(- dmdts[phasei]/rho, p_rgh)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cache p prior to solve for density update
|
||||
volScalarField p_rgh_0(p_rgh);
|
||||
|
||||
// Iterate over the pressure equation to correct for non-orthogonality
|
||||
while (pimple.correctNonOrthogonal())
|
||||
{
|
||||
// Construct the transport part of the pressure equation
|
||||
fvScalarMatrix pEqnIncomp
|
||||
(
|
||||
fvc::div(phiHbyA)
|
||||
- fvm::laplacian(rAUf, p_rgh)
|
||||
);
|
||||
|
||||
{
|
||||
fvScalarMatrix pEqn(pEqnIncomp);
|
||||
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
if (pEqnComps.set(phasei))
|
||||
{
|
||||
pEqn += pEqnComps[phasei];
|
||||
}
|
||||
}
|
||||
|
||||
solve
|
||||
(
|
||||
pEqn,
|
||||
mesh.solver(p_rgh.select(pimple.finalInnerIter()))
|
||||
);
|
||||
}
|
||||
|
||||
// Correct fluxes and velocities on last non-orthogonal iteration
|
||||
if (pimple.finalNonOrthogonalIter())
|
||||
{
|
||||
phi = phiHbyA + pEqnIncomp.flux();
|
||||
|
||||
surfaceScalarField mSfGradp("mSfGradp", pEqnIncomp.flux()/rAUf);
|
||||
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
|
||||
phase.phiRef() =
|
||||
phiHbyAs[phase.index()]
|
||||
+ alpharAUfs[phase.index()]*mSfGradp;
|
||||
|
||||
// Set the phase dilatation rates
|
||||
if (pEqnComps.set(phase.index()))
|
||||
{
|
||||
phase.divU(-pEqnComps[phase.index()] & p_rgh);
|
||||
}
|
||||
}
|
||||
|
||||
if (partialElimination)
|
||||
{
|
||||
fluid.partialEliminationf(rAUfs);
|
||||
}
|
||||
|
||||
// Optionally relax pressure for velocity correction
|
||||
p_rgh.relax();
|
||||
|
||||
mSfGradp = pEqnIncomp.flux()/rAUf;
|
||||
|
||||
forAll(fluid.movingPhases(), movingPhasei)
|
||||
{
|
||||
phaseModel& phase = fluid.movingPhases()[movingPhasei];
|
||||
|
||||
phase.URef() = fvc::reconstruct(MRF.absolute(phase.phi()));
|
||||
phase.URef().correctBoundaryConditions();
|
||||
fvOptions.correct(phase.URef());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update and limit the static pressure
|
||||
p = max(p_rgh + rho*gh, pMin);
|
||||
|
||||
// Limit p_rgh
|
||||
p_rgh = p - rho*gh;
|
||||
|
||||
// Update densities from change in p_rgh
|
||||
forAll(phases, phasei)
|
||||
{
|
||||
phaseModel& phase = phases[phasei];
|
||||
phase.thermoRef().rho() += phase.thermo().psi()*(p_rgh - p_rgh_0);
|
||||
}
|
||||
|
||||
// Correct p_rgh for consistency with p and the updated densities
|
||||
rho = fluid.rho();
|
||||
p_rgh = p - rho*gh;
|
||||
p_rgh.correctBoundaryConditions();
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd |
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
| Copyright (C) 2011-2018 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,9 +26,6 @@ License
|
||||
Application
|
||||
reactingMultiphaseEulerFoam
|
||||
|
||||
Group
|
||||
grpMultiphaseSolvers
|
||||
|
||||
Description
|
||||
Solver for a system of any number of compressible fluid phases with a
|
||||
common pressure, but otherwise separate properties. The type of phase model
|
||||
@ -40,6 +37,7 @@ Description
|
||||
|
||||
#include "fvCFD.H"
|
||||
#include "multiphaseSystem.H"
|
||||
#include "phaseCompressibleTurbulenceModel.H"
|
||||
#include "pimpleControl.H"
|
||||
#include "localEulerDdtScheme.H"
|
||||
#include "fvcSmooth.H"
|
||||
@ -48,16 +46,10 @@ Description
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::addNote
|
||||
(
|
||||
"Solver for a system of any number of compressible fluid phases with a"
|
||||
" common pressure, but otherwise separate properties."
|
||||
);
|
||||
|
||||
#include "postProcess.H"
|
||||
|
||||
#include "addCheckCaseOptions.H"
|
||||
#include "setRootCaseLists.H"
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
#include "createMesh.H"
|
||||
#include "createControl.H"
|
||||
@ -71,20 +63,14 @@ int main(int argc, char *argv[])
|
||||
#include "setInitialDeltaT.H"
|
||||
}
|
||||
|
||||
// bool faceMomentum
|
||||
// (
|
||||
// pimple.dict().lookupOrDefault("faceMomentum", false)
|
||||
// );
|
||||
|
||||
// bool implicitPhasePressure
|
||||
// (
|
||||
// mesh.solverDict(alpha1.name()).lookupOrDefault
|
||||
// (
|
||||
// "implicitPhasePressure", false
|
||||
// )
|
||||
// );
|
||||
|
||||
//#include "pUf/createDDtU.H"
|
||||
Switch faceMomentum
|
||||
(
|
||||
pimple.dict().lookupOrDefault<Switch>("faceMomentum", false)
|
||||
);
|
||||
Switch partialElimination
|
||||
(
|
||||
pimple.dict().lookupOrDefault<Switch>("partialElimination", false)
|
||||
);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -109,7 +95,7 @@ int main(int argc, char *argv[])
|
||||
#include "setDeltaT.H"
|
||||
}
|
||||
|
||||
++runTime;
|
||||
runTime++;
|
||||
Info<< "Time = " << runTime.timeName() << nl << endl;
|
||||
|
||||
// --- Pressure-velocity PIMPLE corrector loop
|
||||
@ -120,14 +106,13 @@ int main(int argc, char *argv[])
|
||||
|
||||
#include "YEqns.H"
|
||||
|
||||
// if (faceMomentum)
|
||||
// {
|
||||
// #include "pUf/UEqns.H"
|
||||
// #include "EEqns.H"
|
||||
// #include "pUf/pEqn.H"
|
||||
// #include "pUf/DDtU.H"
|
||||
// }
|
||||
// else
|
||||
if (faceMomentum)
|
||||
{
|
||||
#include "pUf/UEqns.H"
|
||||
#include "EEqns.H"
|
||||
#include "pUf/pEqn.H"
|
||||
}
|
||||
else
|
||||
{
|
||||
#include "pU/UEqns.H"
|
||||
#include "EEqns.H"
|
||||
@ -144,7 +129,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
runTime.write();
|
||||
|
||||
runTime.printExecutionTime(Info);
|
||||
Info<< "ExecutionTime = "
|
||||
<< runTime.elapsedCpuTime()
|
||||
<< " s\n\n" << endl;
|
||||
}
|
||||
|
||||
Info<< "End\n" << endl;
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
#!/bin/sh
|
||||
cd ${0%/*} || exit 1 # Run from this directory
|
||||
|
||||
wclean libso twoPhaseSystem
|
||||
wclean libso twoPhaseCompressibleTurbulenceModels
|
||||
wclean
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -4,8 +4,6 @@ cd ${0%/*} || exit 1 # Run from this directory
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
wmake $targetType twoPhaseSystem
|
||||
wmake $targetType twoPhaseCompressibleTurbulenceModels
|
||||
wmake $targetType
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -8,46 +8,38 @@ for (int Ecorr=0; Ecorr<nEnergyCorrectors; Ecorr++)
|
||||
phaseSystem::heatTransferTable&
|
||||
heatTransfer = heatTransferPtr();
|
||||
|
||||
if (!phase1.isothermal())
|
||||
{
|
||||
tmp<fvScalarMatrix> E1Eqn(phase1.heEqn());
|
||||
|
||||
if (E1Eqn.valid())
|
||||
{
|
||||
E1Eqn =
|
||||
fvScalarMatrix E1Eqn
|
||||
(
|
||||
E1Eqn
|
||||
phase1.heEqn()
|
||||
==
|
||||
*heatTransfer[phase1.name()]
|
||||
+ alpha1*rho1*(U1&g)
|
||||
+ fvOptions(alpha1, rho1, phase1.thermo().he())
|
||||
+ fvOptions(alpha1, rho1, thermo1.he())
|
||||
);
|
||||
|
||||
E1Eqn->relax();
|
||||
fvOptions.constrain(E1Eqn.ref());
|
||||
E1Eqn->solve();
|
||||
fvOptions.correct(phase1.thermo().he());
|
||||
}
|
||||
E1Eqn.relax();
|
||||
fvOptions.constrain(E1Eqn);
|
||||
E1Eqn.solve();
|
||||
fvOptions.correct(thermo1.he());
|
||||
}
|
||||
|
||||
if (!phase2.isothermal())
|
||||
{
|
||||
tmp<fvScalarMatrix> E2Eqn(phase2.heEqn());
|
||||
|
||||
if (E2Eqn.valid())
|
||||
{
|
||||
E2Eqn =
|
||||
fvScalarMatrix E2Eqn
|
||||
(
|
||||
E2Eqn
|
||||
phase2.heEqn()
|
||||
==
|
||||
*heatTransfer[phase2.name()]
|
||||
+ alpha2*rho2*(U2&g)
|
||||
+ fvOptions(alpha2, rho2, phase2.thermo().he())
|
||||
+ fvOptions(alpha2, rho2, phase2.thermoRef().he())
|
||||
);
|
||||
|
||||
E2Eqn->relax();
|
||||
fvOptions.constrain(E2Eqn.ref());
|
||||
E2Eqn->solve();
|
||||
fvOptions.correct(phase2.thermo().he());
|
||||
}
|
||||
E2Eqn.relax();
|
||||
fvOptions.constrain(E2Eqn);
|
||||
E2Eqn.solve();
|
||||
fvOptions.correct(thermo2.he());
|
||||
}
|
||||
|
||||
fluid.correctThermo();
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
EXE_INC = \
|
||||
-ItwoPhaseSystem/lnInclude \
|
||||
-I../phaseSystems/lnInclude \
|
||||
-I../interfacialModels/lnInclude \
|
||||
-I../interfacialCompositionModels/lnInclude \
|
||||
-ItwoPhaseCompressibleTurbulenceModels/lnInclude \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/sampling/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/reactingTwoPhaseEulerFoam/twoPhaseSystem/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/interfacialCompositionModels/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/phaseSystems/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/interfacialModels/lnInclude \
|
||||
-I$(LIB_SRC)/phaseSystemModels/reactingEulerFoam/reactingTwoPhaseEulerFoam/twoPhaseCompressibleTurbulenceModels/lnInclude \
|
||||
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
|
||||
-I$(LIB_SRC)/transportModels/compressible/lnInclude \
|
||||
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
|
||||
|
||||
@ -5,46 +5,41 @@
|
||||
phaseSystem::massTransferTable&
|
||||
massTransfer(massTransferPtr());
|
||||
|
||||
PtrList<volScalarField>& Y1 = phase1.Y();
|
||||
PtrList<volScalarField>& Y2 = phase2.Y();
|
||||
if (!phase1.pure())
|
||||
{
|
||||
UPtrList<volScalarField>& Y1 = phase1.YActiveRef();
|
||||
|
||||
forAll(Y1, i)
|
||||
{
|
||||
tmp<fvScalarMatrix> Y1iEqn(phase1.YiEqn(Y1[i]));
|
||||
|
||||
if (Y1iEqn.valid())
|
||||
{
|
||||
Y1iEqn =
|
||||
fvScalarMatrix Y1iEqn
|
||||
(
|
||||
Y1iEqn
|
||||
phase1.YiEqn(Y1[i])
|
||||
==
|
||||
*massTransfer[Y1[i].name()]
|
||||
+ fvOptions(alpha1, rho1, Y1[i])
|
||||
);
|
||||
|
||||
Y1iEqn->relax();
|
||||
Y1iEqn->solve(mesh.solver("Yi"));
|
||||
Y1iEqn.relax();
|
||||
Y1iEqn.solve(mesh.solver("Yi"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!phase2.pure())
|
||||
{
|
||||
UPtrList<volScalarField>& Y2 = phase2.YActiveRef();
|
||||
|
||||
forAll(Y2, i)
|
||||
{
|
||||
tmp<fvScalarMatrix> Y2iEqn(phase2.YiEqn(Y2[i]));
|
||||
|
||||
if (Y2iEqn.valid())
|
||||
{
|
||||
Y2iEqn =
|
||||
fvScalarMatrix Y2iEqn
|
||||
(
|
||||
Y2iEqn
|
||||
phase2.YiEqn(Y2[i])
|
||||
==
|
||||
*massTransfer[Y2[i].name()]
|
||||
+ fvOptions(alpha2, rho2, Y2[i])
|
||||
);
|
||||
|
||||
Y2iEqn->relax();
|
||||
Y2iEqn->solve(mesh.solver("Yi"));
|
||||
Y2iEqn.relax();
|
||||
Y2iEqn.solve(mesh.solver("Yi"));
|
||||
}
|
||||
}
|
||||
|
||||
fluid.massTransfer(); // updates interfacial mass flow rates
|
||||
}
|
||||
|
||||
@ -1,22 +1,21 @@
|
||||
phaseModel& phase1 = fluid.phase1();
|
||||
phaseModel& phase2 = fluid.phase2();
|
||||
|
||||
volScalarField& alpha1 = phase1;
|
||||
volScalarField& alpha2 = phase2;
|
||||
const volScalarField& alpha1 = phase1;
|
||||
const volScalarField& alpha2 = phase2;
|
||||
|
||||
volVectorField& U1 = phase1.U();
|
||||
surfaceScalarField& phi1 = phase1.phi();
|
||||
surfaceScalarField& alphaPhi1 = phase1.alphaPhi();
|
||||
surfaceScalarField& alphaRhoPhi1 = phase1.alphaRhoPhi();
|
||||
volVectorField& U1 = phase1.URef();
|
||||
surfaceScalarField& phi1 = phase1.phiRef();
|
||||
const surfaceScalarField& alphaPhi1 = phase1.alphaPhi();
|
||||
|
||||
volVectorField& U2 = phase2.URef();
|
||||
surfaceScalarField& phi2 = phase2.phiRef();
|
||||
const surfaceScalarField& alphaPhi2 = phase2.alphaPhi();
|
||||
|
||||
volVectorField& U2 = phase2.U();
|
||||
surfaceScalarField& phi2 = phase2.phi();
|
||||
surfaceScalarField& alphaPhi2 = phase2.alphaPhi();
|
||||
surfaceScalarField& alphaRhoPhi2 = phase2.alphaRhoPhi();
|
||||
surfaceScalarField& phi = fluid.phi();
|
||||
|
||||
rhoThermo& thermo1 = phase1.thermo();
|
||||
rhoThermo& thermo2 = phase2.thermo();
|
||||
rhoThermo& thermo1 = phase1.thermoRef();
|
||||
rhoThermo& thermo2 = phase2.thermoRef();
|
||||
|
||||
volScalarField& rho1 = thermo1.rho();
|
||||
const volScalarField& psi1 = thermo1.psi();
|
||||
|
||||
@ -19,7 +19,7 @@ dimensionedScalar pMin
|
||||
|
||||
#include "gh.H"
|
||||
|
||||
volScalarField& p = fluid.phase1().thermo().p();
|
||||
volScalarField& p = fluid.phase1().thermoRef().p();
|
||||
|
||||
Info<< "Reading field p_rgh\n" << endl;
|
||||
volScalarField p_rgh
|
||||
|
||||
@ -1,82 +1,54 @@
|
||||
surfaceScalarField alphaf1("alphaf1", fvc::interpolate(alpha1));
|
||||
surfaceScalarField alphaf2("alphaf2", scalar(1) - alphaf1);
|
||||
const surfaceScalarField alphaf1("alphaf1", fvc::interpolate(alpha1));
|
||||
const surfaceScalarField alphaf2("alphaf2", scalar(1) - alphaf1);
|
||||
|
||||
volScalarField rAU1
|
||||
PtrList<volScalarField> rAUs;
|
||||
rAUs.append
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
IOobject::groupName("rAU", phase1.name()),
|
||||
1.0
|
||||
/(
|
||||
U1Eqn.A()
|
||||
+ byDt(max(phase1.residualAlpha() - alpha1, scalar(0))*rho1)
|
||||
)
|
||||
)
|
||||
);
|
||||
volScalarField rAU2
|
||||
rAUs.append
|
||||
(
|
||||
new volScalarField
|
||||
(
|
||||
IOobject::groupName("rAU", phase2.name()),
|
||||
1.0
|
||||
/(
|
||||
U2Eqn.A()
|
||||
+ byDt(max(phase2.residualAlpha() - alpha2, scalar(0))*rho2)
|
||||
)
|
||||
)
|
||||
);
|
||||
const volScalarField& rAU1 = rAUs[0];
|
||||
const volScalarField& rAU2 = rAUs[1];
|
||||
|
||||
surfaceScalarField alpharAUf1
|
||||
const surfaceScalarField alpharAUf1
|
||||
(
|
||||
fvc::interpolate(max(alpha1, phase1.residualAlpha())*rAU1)
|
||||
);
|
||||
surfaceScalarField alpharAUf2
|
||||
const surfaceScalarField alpharAUf2
|
||||
(
|
||||
fvc::interpolate(max(alpha2, phase2.residualAlpha())*rAU2)
|
||||
);
|
||||
|
||||
volScalarField Kd(fluid.Kd());
|
||||
|
||||
// Turbulent diffusion, particle-pressure, lift and wall-lubrication fluxes
|
||||
tmp<surfaceScalarField> phiF1;
|
||||
tmp<surfaceScalarField> phiF2;
|
||||
{
|
||||
// Turbulent-dispersion diffusivity
|
||||
volScalarField D(fluid.D());
|
||||
|
||||
// Phase-1 turbulent dispersion and particle-pressure flux
|
||||
tmp<surfaceScalarField> DbyA1
|
||||
(
|
||||
fvc::interpolate
|
||||
(
|
||||
rAU1*(D + phase1.turbulence().pPrime())
|
||||
)
|
||||
);
|
||||
|
||||
// Phase-2 turbulent dispersion and particle-pressure flux
|
||||
tmp<surfaceScalarField> DbyA2
|
||||
(
|
||||
fvc::interpolate
|
||||
(
|
||||
rAU2*(D + phase2.turbulence().pPrime())
|
||||
)
|
||||
);
|
||||
|
||||
// Lift and wall-lubrication forces
|
||||
volVectorField F(fluid.F());
|
||||
|
||||
// Phase-fraction face-gradient
|
||||
surfaceScalarField snGradAlpha1(fvc::snGrad(alpha1)*mesh.magSf());
|
||||
|
||||
// Phase-1 dispersion, lift and wall-lubrication flux
|
||||
phiF1 = DbyA1()*snGradAlpha1 + fvc::flux(rAU1*F);
|
||||
|
||||
// Phase-2 dispersion, lift and wall-lubrication flux
|
||||
phiF2 = - DbyA2()*snGradAlpha1 - fvc::flux(rAU2*F);
|
||||
|
||||
// Cache the phase diffusivities for implicit treatment in the
|
||||
// phase-fraction equation
|
||||
if (implicitPhasePressure)
|
||||
{
|
||||
phase1.DbyA(DbyA1);
|
||||
phase2.DbyA(DbyA2);
|
||||
}
|
||||
}
|
||||
// Drag coefficients
|
||||
const volScalarField Kd(fluid.Kd());
|
||||
const volScalarField rAUKd1(rAU1*Kd);
|
||||
const volScalarField rAUKd2(rAU2*Kd);
|
||||
const surfaceScalarField phiKd1(fvc::interpolate(rAUKd1));
|
||||
const surfaceScalarField phiKd2(fvc::interpolate(rAUKd2));
|
||||
|
||||
// Explicit force fluxes
|
||||
PtrList<surfaceScalarField> phiFs(fluid.phiFs(rAUs));
|
||||
const surfaceScalarField& phiF1 = phiFs[0];
|
||||
const surfaceScalarField& phiF2 = phiFs[1];
|
||||
|
||||
// --- Pressure corrector loop
|
||||
while (pimple.correct())
|
||||
@ -90,6 +62,34 @@ while (pimple.correct())
|
||||
MRF.correctBoundaryFlux(U1, phi1);
|
||||
MRF.correctBoundaryFlux(U2, phi2);
|
||||
|
||||
// Combined buoyancy and force fluxes
|
||||
const surfaceScalarField ghSnGradRho
|
||||
(
|
||||
"ghSnGradRho",
|
||||
ghf*fvc::snGrad(rho)*mesh.magSf()
|
||||
);
|
||||
|
||||
const surfaceScalarField phigF1
|
||||
(
|
||||
alpharAUf1
|
||||
*(
|
||||
ghSnGradRho
|
||||
- alphaf2*fvc::interpolate(rho1 - rho2)*(g & mesh.Sf())
|
||||
)
|
||||
+ phiF1
|
||||
);
|
||||
|
||||
const surfaceScalarField phigF2
|
||||
(
|
||||
alpharAUf2
|
||||
*(
|
||||
ghSnGradRho
|
||||
- alphaf1*fvc::interpolate(rho2 - rho1)*(g & mesh.Sf())
|
||||
)
|
||||
+ phiF2
|
||||
);
|
||||
|
||||
// Predicted velocities
|
||||
volVectorField HbyA1
|
||||
(
|
||||
IOobject::groupName("HbyA", phase1.name()),
|
||||
@ -116,98 +116,42 @@ while (pimple.correct())
|
||||
*U2.oldTime()
|
||||
);
|
||||
|
||||
surfaceScalarField ghSnGradRho
|
||||
(
|
||||
"ghSnGradRho",
|
||||
ghf*fvc::snGrad(rho)*mesh.magSf()
|
||||
);
|
||||
// Correction force fluxes
|
||||
PtrList<surfaceScalarField> ddtCorrByAs(fluid.ddtCorrByAs(rAUs));
|
||||
|
||||
surfaceScalarField phig1
|
||||
(
|
||||
alpharAUf1
|
||||
*(
|
||||
ghSnGradRho
|
||||
- alphaf2*fvc::interpolate(rho1 - rho2)*(g & mesh.Sf())
|
||||
)
|
||||
);
|
||||
|
||||
surfaceScalarField phig2
|
||||
(
|
||||
alpharAUf2
|
||||
*(
|
||||
ghSnGradRho
|
||||
- alphaf1*fvc::interpolate(rho2 - rho1)*(g & mesh.Sf())
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// ddtPhiCorr filter -- only apply in pure(ish) phases
|
||||
surfaceScalarField alphaf1Bar(fvc::interpolate(fvc::average(alphaf1)));
|
||||
surfaceScalarField phiCorrCoeff1(pos0(alphaf1Bar - 0.99));
|
||||
surfaceScalarField phiCorrCoeff2(pos0(0.01 - alphaf1Bar));
|
||||
|
||||
{
|
||||
surfaceScalarField::Boundary& phiCorrCoeff1Bf =
|
||||
phiCorrCoeff1.boundaryFieldRef();
|
||||
|
||||
surfaceScalarField::Boundary& phiCorrCoeff2Bf =
|
||||
phiCorrCoeff2.boundaryFieldRef();
|
||||
|
||||
forAll(mesh.boundary(), patchi)
|
||||
{
|
||||
// Set ddtPhiCorr to 0 on non-coupled boundaries
|
||||
if
|
||||
(
|
||||
!mesh.boundary()[patchi].coupled()
|
||||
|| isA<cyclicAMIFvPatch>(mesh.boundary()[patchi])
|
||||
)
|
||||
{
|
||||
phiCorrCoeff1Bf[patchi] = 0;
|
||||
phiCorrCoeff2Bf[patchi] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Phase-1 predicted flux
|
||||
surfaceScalarField phiHbyA1
|
||||
// Predicted fluxes
|
||||
const surfaceScalarField phiHbyA1
|
||||
(
|
||||
IOobject::groupName("phiHbyA", phase1.name()),
|
||||
fvc::flux(HbyA1)
|
||||
+ phiCorrCoeff1
|
||||
*fvc::interpolate(byDt(alpha1.oldTime()*rho1.oldTime()*rAU1))
|
||||
*(MRF.absolute(phi1.oldTime()) - fvc::flux(U1.oldTime()))
|
||||
- phiF1()
|
||||
- phig1
|
||||
fvc::flux(HbyA1) - phigF1 - ddtCorrByAs[0]
|
||||
);
|
||||
|
||||
// Phase-2 predicted flux
|
||||
surfaceScalarField phiHbyA2
|
||||
const surfaceScalarField phiHbyA2
|
||||
(
|
||||
IOobject::groupName("phiHbyA", phase2.name()),
|
||||
fvc::flux(HbyA2)
|
||||
+ phiCorrCoeff2
|
||||
*fvc::interpolate(byDt(alpha2.oldTime()*rho2.oldTime()*rAU2))
|
||||
*(MRF.absolute(phi2.oldTime()) - fvc::flux(U2.oldTime()))
|
||||
- phiF2()
|
||||
- phig2
|
||||
fvc::flux(HbyA2) - phigF2 - ddtCorrByAs[1]
|
||||
);
|
||||
|
||||
// Face-drag coefficients
|
||||
surfaceScalarField rAUKd1(fvc::interpolate(rAU1*Kd));
|
||||
surfaceScalarField rAUKd2(fvc::interpolate(rAU2*Kd));
|
||||
ddtCorrByAs.clear();
|
||||
|
||||
// Construct the mean predicted flux
|
||||
// including explicit drag contributions based on absolute fluxes
|
||||
// Drag fluxes
|
||||
PtrList<surfaceScalarField> phiKdPhis(fluid.phiKdPhis(rAUs));
|
||||
const surfaceScalarField& phiKdPhi1 = phiKdPhis[0];
|
||||
const surfaceScalarField& phiKdPhi2 = phiKdPhis[1];
|
||||
|
||||
// Total predicted flux
|
||||
surfaceScalarField phiHbyA
|
||||
(
|
||||
"phiHbyA",
|
||||
alphaf1*(phiHbyA1 + rAUKd1*MRF.absolute(phi2))
|
||||
+ alphaf2*(phiHbyA2 + rAUKd2*MRF.absolute(phi1))
|
||||
alphaf1*(phiHbyA1 - phiKdPhi1) + alphaf2*(phiHbyA2 - phiKdPhi2)
|
||||
);
|
||||
|
||||
MRF.makeRelative(phiHbyA);
|
||||
|
||||
phiKdPhis.clear();
|
||||
|
||||
// Construct pressure "diffusivity"
|
||||
surfaceScalarField rAUf
|
||||
const surfaceScalarField rAUf
|
||||
(
|
||||
"rAUf",
|
||||
mag(alphaf1*alpharAUf1 + alphaf2*alpharAUf2)
|
||||
@ -226,16 +170,13 @@ while (pimple.correct())
|
||||
)/(mesh.magSf().boundaryField()*rAUf.boundaryField())
|
||||
);
|
||||
|
||||
tmp<fvScalarMatrix> pEqnComp1;
|
||||
tmp<fvScalarMatrix> pEqnComp2;
|
||||
|
||||
// Construct the compressibility parts of the pressure equation
|
||||
|
||||
tmp<fvScalarMatrix> pEqnComp1, pEqnComp2;
|
||||
if (phase1.compressible())
|
||||
{
|
||||
if (pimple.transonic())
|
||||
{
|
||||
surfaceScalarField phid1
|
||||
const surfaceScalarField phid1
|
||||
(
|
||||
IOobject::groupName("phid", phase1.name()),
|
||||
fvc::interpolate(psi1)*phi1
|
||||
@ -243,7 +184,7 @@ while (pimple.correct())
|
||||
|
||||
pEqnComp1 =
|
||||
(
|
||||
phase1.continuityError()
|
||||
fvc::ddt(alpha1, rho1) + fvc::div(phase1.alphaRhoPhi())
|
||||
- fvc::Sp(fvc::ddt(alpha1) + fvc::div(alphaPhi1), rho1)
|
||||
)/rho1
|
||||
+ correction
|
||||
@ -261,22 +202,17 @@ while (pimple.correct())
|
||||
{
|
||||
pEqnComp1 =
|
||||
(
|
||||
phase1.continuityError()
|
||||
fvc::ddt(alpha1, rho1) + fvc::div(phase1.alphaRhoPhi())
|
||||
- fvc::Sp(fvc::ddt(alpha1) + fvc::div(alphaPhi1), rho1)
|
||||
)/rho1
|
||||
+ (alpha1*psi1/rho1)*correction(fvm::ddt(p_rgh));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComp1 = fvm::Su(-(fvOptions(alpha1, rho1)&rho1)/rho1, p_rgh);
|
||||
}
|
||||
|
||||
if (phase2.compressible())
|
||||
{
|
||||
if (pimple.transonic())
|
||||
{
|
||||
surfaceScalarField phid2
|
||||
const surfaceScalarField phid2
|
||||
(
|
||||
IOobject::groupName("phid", phase2.name()),
|
||||
fvc::interpolate(psi2)*phi2
|
||||
@ -284,7 +220,7 @@ while (pimple.correct())
|
||||
|
||||
pEqnComp2 =
|
||||
(
|
||||
phase2.continuityError()
|
||||
fvc::ddt(alpha2, rho2) + fvc::div(phase2.alphaRhoPhi())
|
||||
- fvc::Sp(fvc::ddt(alpha2) + fvc::div(alphaPhi2), rho2)
|
||||
)/rho2
|
||||
+ correction
|
||||
@ -302,40 +238,70 @@ while (pimple.correct())
|
||||
{
|
||||
pEqnComp2 =
|
||||
(
|
||||
phase2.continuityError()
|
||||
fvc::ddt(alpha2, rho2) + fvc::div(phase2.alphaRhoPhi())
|
||||
- fvc::Sp(fvc::ddt(alpha2) + fvc::div(alphaPhi2), rho2)
|
||||
)/rho2
|
||||
+ (alpha2*psi2/rho2)*correction(fvm::ddt(p_rgh));
|
||||
}
|
||||
}
|
||||
|
||||
// Add option sources
|
||||
{
|
||||
if (fvOptions.appliesToField(rho1.name()))
|
||||
{
|
||||
tmp<fvScalarMatrix> optEqn1 = fvOptions(alpha1, rho1);
|
||||
if (pEqnComp1.valid())
|
||||
{
|
||||
pEqnComp1.ref() -= (optEqn1 & rho1)/rho1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComp2 = fvm::Su(-(fvOptions(alpha2, rho2)&rho2)/rho2, p_rgh);
|
||||
pEqnComp1 = fvm::Su(- (optEqn1 & rho1)/rho1, p_rgh);
|
||||
}
|
||||
}
|
||||
if (fvOptions.appliesToField(rho2.name()))
|
||||
{
|
||||
tmp<fvScalarMatrix> optEqn2 = fvOptions(alpha2, rho2);
|
||||
if (pEqnComp2.valid())
|
||||
{
|
||||
pEqnComp2.ref() -= (optEqn2 & rho2)/rho2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComp2 = fvm::Su(- (optEqn2 & rho2)/rho2, p_rgh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fluid.transfersMass())
|
||||
// Add mass transfer
|
||||
{
|
||||
PtrList<volScalarField> dmdts(fluid.dmdts());
|
||||
if (dmdts.set(0))
|
||||
{
|
||||
if (pEqnComp1.valid())
|
||||
{
|
||||
pEqnComp1.ref() -= fluid.dmdt()/rho1;
|
||||
pEqnComp1.ref() -= dmdts[0]/rho1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComp1 = fvm::Su(-fluid.dmdt()/rho1, p_rgh);
|
||||
pEqnComp1 = fvm::Su(- dmdts[0]/rho1, p_rgh);
|
||||
}
|
||||
|
||||
}
|
||||
if (dmdts.set(1))
|
||||
{
|
||||
if (pEqnComp2.valid())
|
||||
{
|
||||
pEqnComp2.ref() += fluid.dmdt()/rho2;
|
||||
pEqnComp2.ref() -= dmdts[1]/rho2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComp2 = fvm::Su(fluid.dmdt()/rho2, p_rgh);
|
||||
pEqnComp2 = fvm::Su(- dmdts[1]/rho2, p_rgh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cache p prior to solve for density update
|
||||
volScalarField p_rgh_0(p_rgh);
|
||||
const volScalarField p_rgh_0(p_rgh);
|
||||
|
||||
// Iterate over the pressure equation to correct for non-orthogonality
|
||||
while (pimple.correctNonOrthogonal())
|
||||
@ -360,11 +326,7 @@ while (pimple.correct())
|
||||
pEqn += pEqnComp2();
|
||||
}
|
||||
|
||||
solve
|
||||
(
|
||||
pEqn,
|
||||
mesh.solver(p_rgh.select(pimple.finalInnerIter()))
|
||||
);
|
||||
pEqn.solve();
|
||||
}
|
||||
|
||||
// Correct fluxes and velocities on last non-orthogonal iteration
|
||||
@ -372,24 +334,28 @@ while (pimple.correct())
|
||||
{
|
||||
phi = phiHbyA + pEqnIncomp.flux();
|
||||
|
||||
surfaceScalarField mSfGradp("mSfGradp", pEqnIncomp.flux()/rAUf);
|
||||
surfaceScalarField mSfGradp
|
||||
(
|
||||
"mSfGradp",
|
||||
pEqnIncomp.flux()/rAUf
|
||||
);
|
||||
|
||||
// Partial-elimination phase-flux corrector
|
||||
{
|
||||
surfaceScalarField phi1s
|
||||
const surfaceScalarField phi1s
|
||||
(
|
||||
phiHbyA1 + alpharAUf1*mSfGradp
|
||||
);
|
||||
|
||||
surfaceScalarField phi2s
|
||||
const surfaceScalarField phi2s
|
||||
(
|
||||
phiHbyA2 + alpharAUf2*mSfGradp
|
||||
);
|
||||
|
||||
surfaceScalarField phir
|
||||
(
|
||||
((phi1s + rAUKd1*phi2s) - (phi2s + rAUKd2*phi1s))
|
||||
/(1 - rAUKd1*rAUKd2)
|
||||
((phi1s + phiKd1*phi2s) - (phi2s + phiKd2*phi1s))
|
||||
/(1 - phiKd1*phiKd2)
|
||||
);
|
||||
|
||||
phi1 = phi + alphaf2*phir;
|
||||
@ -413,23 +379,27 @@ while (pimple.correct())
|
||||
|
||||
// Partial-elimination phase-velocity corrector
|
||||
{
|
||||
volVectorField Us1
|
||||
const volVectorField Us1
|
||||
(
|
||||
HbyA1
|
||||
+ fvc::reconstruct(alpharAUf1*mSfGradp - phiF1() - phig1)
|
||||
+ fvc::reconstruct(alpharAUf1*mSfGradp - phigF1)
|
||||
);
|
||||
|
||||
volVectorField Us2
|
||||
const volVectorField Us2
|
||||
(
|
||||
HbyA2
|
||||
+ fvc::reconstruct(alpharAUf2*mSfGradp - phiF2() - phig2)
|
||||
+ fvc::reconstruct(alpharAUf2*mSfGradp - phigF2)
|
||||
);
|
||||
|
||||
volScalarField D1(rAU1*Kd);
|
||||
volScalarField D2(rAU2*Kd);
|
||||
const volVectorField U
|
||||
(
|
||||
alpha1*(Us1 + rAUKd1*U2) + alpha2*(Us2 + rAUKd2*U1)
|
||||
);
|
||||
|
||||
volVectorField U(alpha1*(Us1 + D1*U2) + alpha2*(Us2 + D2*U1));
|
||||
volVectorField Ur(((1 - D2)*Us1 - (1 - D1)*Us2)/(1 - D1*D2));
|
||||
const volVectorField Ur
|
||||
(
|
||||
((1 - rAUKd2)*Us1 - (1 - rAUKd1)*Us2)/(1 - rAUKd1*rAUKd2)
|
||||
);
|
||||
|
||||
U1 = U + alpha2*Ur;
|
||||
U1.correctBoundaryConditions();
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
tddtPhi1 = fvc::ddt(phi1);
|
||||
tddtPhi2 = fvc::ddt(phi2);
|
||||
@ -4,33 +4,22 @@ fvVectorMatrix U1Eqn(U1, rho1.dimensions()*U1.dimensions()*dimVolume/dimTime);
|
||||
fvVectorMatrix U2Eqn(U2, rho2.dimensions()*U2.dimensions()*dimVolume/dimTime);
|
||||
|
||||
{
|
||||
volScalarField Vm(fluid.Vm());
|
||||
fluid.momentumTransfer(); // !!! Update coefficients shouldn't be necessary
|
||||
// This should be done on demand
|
||||
|
||||
fvVectorMatrix UgradU1
|
||||
(
|
||||
fvm::div(phi1, U1) - fvm::Sp(fvc::div(phi1), U1)
|
||||
+ MRF.DDt(U1)
|
||||
);
|
||||
autoPtr<phaseSystem::momentumTransferTable>
|
||||
momentumTransferPtr(fluid.momentumTransferf());
|
||||
|
||||
fvVectorMatrix UgradU2
|
||||
(
|
||||
fvm::div(phi2, U2) - fvm::Sp(fvc::div(phi2), U2)
|
||||
+ MRF.DDt(U2)
|
||||
);
|
||||
|
||||
const volScalarField dmdt21(posPart(fluid.dmdt()));
|
||||
const volScalarField dmdt12(negPart(fluid.dmdt()));
|
||||
phaseSystem::momentumTransferTable&
|
||||
momentumTransfer(momentumTransferPtr());
|
||||
|
||||
{
|
||||
U1Eqn =
|
||||
(
|
||||
fvm::div(alphaRhoPhi1, U1) - fvm::Sp(fvc::div(alphaRhoPhi1), U1)
|
||||
+ fvm::Sp(dmdt21, U1) - dmdt21*U2
|
||||
+ MRF.DDt(alpha1*rho1, U1)
|
||||
+ phase1.turbulence().divDevRhoReff(U1)
|
||||
+ Vm*(UgradU1 - (UgradU2 & U2))
|
||||
- fvOptions(alpha1, rho1, U1)
|
||||
+ fvm::SuSp(fvOptions(alpha1, rho1)&rho1,U1)
|
||||
phase1.UfEqn()
|
||||
==
|
||||
*momentumTransfer[phase1.name()]
|
||||
+ fvOptions(alpha1, rho1, U1)
|
||||
);
|
||||
U1Eqn.relax();
|
||||
fvOptions.constrain(U1Eqn);
|
||||
@ -41,13 +30,10 @@ fvVectorMatrix U2Eqn(U2, rho2.dimensions()*U2.dimensions()*dimVolume/dimTime);
|
||||
{
|
||||
U2Eqn =
|
||||
(
|
||||
fvm::div(alphaRhoPhi2, U2) - fvm::Sp(fvc::div(alphaRhoPhi2), U2)
|
||||
- fvm::Sp(dmdt12, U2) + dmdt12*U1
|
||||
+ MRF.DDt(alpha2*rho2, U2)
|
||||
+ phase2.turbulence().divDevRhoReff(U2)
|
||||
+ Vm*(UgradU2 - (UgradU1 & U1))
|
||||
- fvOptions(alpha2, rho2, U2)
|
||||
+ fvm::SuSp(fvOptions(alpha2, rho2)&rho2,U2)
|
||||
phase2.UfEqn()
|
||||
==
|
||||
*momentumTransfer[phase2.name()]
|
||||
+ fvOptions(alpha2, rho2, U2)
|
||||
);
|
||||
U2Eqn.relax();
|
||||
fvOptions.constrain(U2Eqn);
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
tmp<surfaceScalarField> tddtPhi1;
|
||||
tmp<surfaceScalarField> tddtPhi2;
|
||||
|
||||
if (faceMomentum)
|
||||
{
|
||||
#include "pUf/DDtU.H"
|
||||
}
|
||||
@ -22,73 +22,47 @@ surfaceScalarField alphaRhof20
|
||||
);
|
||||
|
||||
// Drag coefficient
|
||||
surfaceScalarField Kdf("Kdf", fluid.Kdf());
|
||||
const surfaceScalarField Kdf("Kdf", fluid.Kdf());
|
||||
|
||||
// Virtual-mass coefficient
|
||||
surfaceScalarField Vmf("Vmf", fluid.Vmf());
|
||||
// Diagonal coefficients
|
||||
PtrList<surfaceScalarField> AFfs(fluid.AFfs());
|
||||
|
||||
surfaceScalarField rAUf1
|
||||
PtrList<surfaceScalarField> rAUfs;
|
||||
rAUfs.append
|
||||
(
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject::groupName("rAUf", phase1.name()),
|
||||
1.0
|
||||
/(
|
||||
byDt(alphaRhof10 + Vmf)
|
||||
byDt(alphaRhof10)
|
||||
+ fvc::interpolate(U1Eqn.A())
|
||||
+ Kdf
|
||||
+ AFfs[0]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
surfaceScalarField rAUf2
|
||||
rAUfs.append
|
||||
(
|
||||
new surfaceScalarField
|
||||
(
|
||||
IOobject::groupName("rAUf", phase2.name()),
|
||||
1.0
|
||||
/(
|
||||
byDt(alphaRhof20 + Vmf)
|
||||
byDt(alphaRhof20)
|
||||
+ fvc::interpolate(U2Eqn.A())
|
||||
+ Kdf
|
||||
+ AFfs[0]
|
||||
)
|
||||
)
|
||||
);
|
||||
const surfaceScalarField& rAUf1 = rAUfs[0];
|
||||
const surfaceScalarField& rAUf2 = rAUfs[1];
|
||||
|
||||
AFfs.clear();
|
||||
|
||||
// Turbulent dispersion, particle-pressure, lift and wall-lubrication forces
|
||||
tmp<surfaceScalarField> Ff1;
|
||||
tmp<surfaceScalarField> Ff2;
|
||||
{
|
||||
// Turbulent-dispersion diffusivity
|
||||
volScalarField D(fluid.D());
|
||||
|
||||
// Phase-1 turbulent dispersion and particle-pressure diffusivity
|
||||
surfaceScalarField Df1
|
||||
(
|
||||
fvc::interpolate(D + phase1.turbulence().pPrime())
|
||||
);
|
||||
|
||||
// Phase-2 turbulent dispersion and particle-pressure diffusivity
|
||||
surfaceScalarField Df2
|
||||
(
|
||||
fvc::interpolate(D + phase2.turbulence().pPrime())
|
||||
);
|
||||
|
||||
// Cache the phase diffusivities for implicit treatment in the
|
||||
// phase-fraction equation
|
||||
if (implicitPhasePressure)
|
||||
{
|
||||
phase1.DbyA(rAUf1*Df1);
|
||||
phase2.DbyA(rAUf2*Df2);
|
||||
}
|
||||
|
||||
// Lift and wall-lubrication forces
|
||||
surfaceScalarField Ff(fluid.Ff());
|
||||
|
||||
// Phase-fraction face-gradient
|
||||
surfaceScalarField snGradAlpha1(fvc::snGrad(alpha1)*mesh.magSf());
|
||||
|
||||
// Phase-1 dispersion, lift and wall-lubrication force
|
||||
Ff1 = Df1*snGradAlpha1 + Ff;
|
||||
|
||||
// Phase-2 dispersion, lift and wall-lubrication force
|
||||
Ff2 = -Df2*snGradAlpha1 - Ff;
|
||||
}
|
||||
// Explicit force fluxes
|
||||
PtrList<surfaceScalarField> phiFfs(fluid.phiFfs(rAUfs));
|
||||
const surfaceScalarField& phiFf1 = phiFfs[0];
|
||||
const surfaceScalarField& phiFf2 = phiFfs[1];
|
||||
|
||||
|
||||
while (pimple.correct())
|
||||
@ -105,48 +79,47 @@ while (pimple.correct())
|
||||
MRF.correctBoundaryFlux(U1, phi1);
|
||||
MRF.correctBoundaryFlux(U2, phi2);
|
||||
|
||||
surfaceScalarField alpharAUf1
|
||||
const surfaceScalarField alpharAUf1
|
||||
(
|
||||
IOobject::groupName("alpharAUf", phase1.name()),
|
||||
max(alphaf1, phase1.residualAlpha())*rAUf1
|
||||
);
|
||||
|
||||
surfaceScalarField alpharAUf2
|
||||
const surfaceScalarField alpharAUf2
|
||||
(
|
||||
IOobject::groupName("alpharAUf", phase2.name()),
|
||||
max(alphaf2, phase2.residualAlpha())*rAUf2
|
||||
);
|
||||
|
||||
surfaceScalarField ghSnGradRho
|
||||
// Combined buoyancy and force fluxes
|
||||
const surfaceScalarField ghSnGradRho
|
||||
(
|
||||
"ghSnGradRho",
|
||||
ghf*fvc::snGrad(rho)*mesh.magSf()
|
||||
);
|
||||
|
||||
// Phase-1 buoyancy flux
|
||||
surfaceScalarField phig1
|
||||
const surfaceScalarField phigF1
|
||||
(
|
||||
IOobject::groupName("phig", phase1.name()),
|
||||
alpharAUf1
|
||||
*(
|
||||
ghSnGradRho
|
||||
- alphaf2*(rhof1 - rhof2)*(g & mesh.Sf())
|
||||
)
|
||||
+ phiFf1
|
||||
);
|
||||
|
||||
// Phase-2 buoyancy flux
|
||||
surfaceScalarField phig2
|
||||
const surfaceScalarField phigF2
|
||||
(
|
||||
IOobject::groupName("phig", phase2.name()),
|
||||
alpharAUf2
|
||||
*(
|
||||
ghSnGradRho
|
||||
- alphaf1*(rhof2 - rhof1)*(g & mesh.Sf())
|
||||
)
|
||||
+ phiFf2
|
||||
);
|
||||
|
||||
|
||||
// Phase-1 predicted flux
|
||||
// Predicted fluxes
|
||||
surfaceScalarField phiHbyA1
|
||||
(
|
||||
IOobject::groupName("phiHbyA", phase1.name()),
|
||||
@ -156,15 +129,11 @@ while (pimple.correct())
|
||||
phiHbyA1 =
|
||||
rAUf1
|
||||
*(
|
||||
(alphaRhof10 + Vmf)
|
||||
*byDt(MRF.absolute(phi1.oldTime()))
|
||||
alphaRhof10*byDt(MRF.absolute(phi1.oldTime()))
|
||||
+ fvc::flux(U1Eqn.H())
|
||||
+ Vmf*tddtPhi2()
|
||||
+ Kdf*MRF.absolute(phi2)
|
||||
- Ff1()
|
||||
);
|
||||
)
|
||||
- phigF1;
|
||||
|
||||
// Phase-2 predicted flux
|
||||
surfaceScalarField phiHbyA2
|
||||
(
|
||||
IOobject::groupName("phiHbyA", phase2.name()),
|
||||
@ -174,31 +143,34 @@ while (pimple.correct())
|
||||
phiHbyA2 =
|
||||
rAUf2
|
||||
*(
|
||||
(alphaRhof20 + Vmf)
|
||||
*byDt(MRF.absolute(phi2.oldTime()))
|
||||
alphaRhof20*byDt(MRF.absolute(phi2.oldTime()))
|
||||
+ fvc::flux(U2Eqn.H())
|
||||
+ Vmf*tddtPhi1()
|
||||
+ Kdf*MRF.absolute(phi1)
|
||||
- Ff2()
|
||||
);
|
||||
)
|
||||
- phigF2;
|
||||
|
||||
// Drag fluxes
|
||||
PtrList<surfaceScalarField> phiKdPhifs(fluid.phiKdPhifs(rAUfs));
|
||||
const surfaceScalarField& phiKdPhif1 = phiKdPhifs[0];
|
||||
const surfaceScalarField& phiKdPhif2 = phiKdPhifs[1];
|
||||
|
||||
// Total predicted flux
|
||||
surfaceScalarField phiHbyA
|
||||
(
|
||||
"phiHbyA",
|
||||
alphaf1*(phiHbyA1 - phig1) + alphaf2*(phiHbyA2 - phig2)
|
||||
alphaf1*(phiHbyA1 - phiKdPhif1) + alphaf2*(phiHbyA2 - phiKdPhif2)
|
||||
);
|
||||
MRF.makeRelative(phiHbyA);
|
||||
|
||||
phiHbyA1 -= phig1;
|
||||
phiHbyA2 -= phig2;
|
||||
phiKdPhifs.clear();
|
||||
|
||||
surfaceScalarField rAUf
|
||||
// Construct pressure "diffusivity"
|
||||
const surfaceScalarField rAUf
|
||||
(
|
||||
"rAUf",
|
||||
mag(alphaf1*alpharAUf1 + alphaf2*alpharAUf2)
|
||||
);
|
||||
|
||||
|
||||
// Update the fixedFluxPressure BCs to ensure flux consistency
|
||||
setSnGrad<fixedFluxPressureFvPatchScalarField>
|
||||
(
|
||||
@ -212,10 +184,8 @@ while (pimple.correct())
|
||||
)/(mesh.magSf().boundaryField()*rAUf.boundaryField())
|
||||
);
|
||||
|
||||
tmp<fvScalarMatrix> pEqnComp1;
|
||||
tmp<fvScalarMatrix> pEqnComp2;
|
||||
|
||||
// Construct the compressibility parts of the pressure equation
|
||||
tmp<fvScalarMatrix> pEqnComp1, pEqnComp2;
|
||||
|
||||
if (phase1.compressible())
|
||||
{
|
||||
@ -229,7 +199,7 @@ while (pimple.correct())
|
||||
|
||||
pEqnComp1 =
|
||||
(
|
||||
phase1.continuityError()
|
||||
fvc::ddt(alpha1, rho1) + fvc::div(phase1.alphaRhoPhi())
|
||||
- fvc::Sp(fvc::ddt(alpha1) + fvc::div(alphaPhi1), rho1)
|
||||
)/rho1
|
||||
+ correction
|
||||
@ -247,16 +217,12 @@ while (pimple.correct())
|
||||
{
|
||||
pEqnComp1 =
|
||||
(
|
||||
phase1.continuityError()
|
||||
fvc::ddt(alpha1, rho1) + fvc::div(phase1.alphaRhoPhi())
|
||||
- fvc::Sp(fvc::ddt(alpha1) + fvc::div(alphaPhi1), rho1)
|
||||
)/rho1
|
||||
+ (alpha1*psi1/rho1)*correction(fvm::ddt(p_rgh));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComp1 = fvm::Su(-(fvOptions(alpha1, rho1)&rho1)/rho1, p_rgh);
|
||||
}
|
||||
|
||||
if (phase2.compressible())
|
||||
{
|
||||
@ -270,7 +236,7 @@ while (pimple.correct())
|
||||
|
||||
pEqnComp2 =
|
||||
(
|
||||
phase2.continuityError()
|
||||
fvc::ddt(alpha2, rho2) + fvc::div(phase2.alphaRhoPhi())
|
||||
- fvc::Sp(fvc::ddt(alpha2) + fvc::div(alphaPhi2), rho2)
|
||||
)/rho2
|
||||
+ correction
|
||||
@ -288,35 +254,66 @@ while (pimple.correct())
|
||||
{
|
||||
pEqnComp2 =
|
||||
(
|
||||
phase2.continuityError()
|
||||
fvc::ddt(alpha2, rho2) + fvc::div(phase2.alphaRhoPhi())
|
||||
- fvc::Sp(fvc::ddt(alpha2) + fvc::div(alphaPhi2), rho2)
|
||||
)/rho2
|
||||
+ (alpha2*psi2/rho2)*correction(fvm::ddt(p_rgh));
|
||||
}
|
||||
}
|
||||
|
||||
// Add option sources
|
||||
{
|
||||
if (fvOptions.appliesToField(rho1.name()))
|
||||
{
|
||||
tmp<fvScalarMatrix> optEqn1 = fvOptions(alpha1, rho1);
|
||||
if (pEqnComp1.valid())
|
||||
{
|
||||
pEqnComp1.ref() -= (optEqn1 & rho1)/rho1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComp2 = fvm::Su(-(fvOptions(alpha2, rho2)&rho2)/rho2, p_rgh);
|
||||
pEqnComp1 = fvm::Su(- (optEqn1 & rho1)/rho1, p_rgh);
|
||||
}
|
||||
}
|
||||
if (fvOptions.appliesToField(rho2.name()))
|
||||
{
|
||||
tmp<fvScalarMatrix> optEqn2 = fvOptions(alpha2, rho2);
|
||||
if (pEqnComp2.valid())
|
||||
{
|
||||
pEqnComp2.ref() -= (optEqn2 & rho2)/rho2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComp2 = fvm::Su(- (optEqn2 & rho2)/rho2, p_rgh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fluid.transfersMass())
|
||||
|
||||
// Add mass transfer
|
||||
{
|
||||
PtrList<volScalarField> dmdts(fluid.dmdts());
|
||||
if (dmdts.set(0))
|
||||
{
|
||||
if (pEqnComp1.valid())
|
||||
{
|
||||
pEqnComp1.ref() -= fluid.dmdt()/rho1;
|
||||
pEqnComp1.ref() -= dmdts[0]/rho1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComp1 = fvm::Su(-fluid.dmdt()/rho1, p_rgh);
|
||||
pEqnComp1 = fvm::Su(- dmdts[0]/rho1, p_rgh);
|
||||
}
|
||||
|
||||
}
|
||||
if (dmdts.set(1))
|
||||
{
|
||||
if (pEqnComp2.valid())
|
||||
{
|
||||
pEqnComp2.ref() += fluid.dmdt()/rho2;
|
||||
pEqnComp2.ref() -= dmdts[1]/rho2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEqnComp2 = fvm::Su(fluid.dmdt()/rho2, p_rgh);
|
||||
pEqnComp2 = fvm::Su(- dmdts[1]/rho2, p_rgh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,18 +354,14 @@ while (pimple.correct())
|
||||
|
||||
phi = phiHbyA + pEqnIncomp.flux();
|
||||
|
||||
surfaceScalarField phi1s
|
||||
const surfaceScalarField phi1s
|
||||
(
|
||||
phiHbyA1
|
||||
+ alpharAUf1*mSfGradp
|
||||
- rAUf1*Kdf*MRF.absolute(phi2)
|
||||
phiHbyA1 + alpharAUf1*mSfGradp
|
||||
);
|
||||
|
||||
surfaceScalarField phi2s
|
||||
const surfaceScalarField phi2s
|
||||
(
|
||||
phiHbyA2
|
||||
+ alpharAUf2*mSfGradp
|
||||
- rAUf2*Kdf*MRF.absolute(phi1)
|
||||
phiHbyA2 + alpharAUf2*mSfGradp
|
||||
);
|
||||
|
||||
surfaceScalarField phir
|
||||
|
||||
@ -45,33 +45,6 @@ Description
|
||||
#include "localEulerDdtScheme.H"
|
||||
#include "fvcSmooth.H"
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
tmp<volScalarField> byDt(const volScalarField& vf)
|
||||
{
|
||||
if (fv::localEulerDdt::enabled(vf.mesh()))
|
||||
{
|
||||
return fv::localEulerDdt::localRDeltaT(vf.mesh())*vf;
|
||||
}
|
||||
else
|
||||
{
|
||||
return vf/vf.mesh().time().deltaT();
|
||||
}
|
||||
}
|
||||
|
||||
tmp<surfaceScalarField> byDt(const surfaceScalarField& sf)
|
||||
{
|
||||
if (fv::localEulerDdt::enabled(sf.mesh()))
|
||||
{
|
||||
return fv::localEulerDdt::localRDeltaTf(sf.mesh())*sf;
|
||||
}
|
||||
else
|
||||
{
|
||||
return sf/sf.mesh().time().deltaT();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -105,16 +78,7 @@ int main(int argc, char *argv[])
|
||||
pimple.dict().lookupOrDefault("faceMomentum", false)
|
||||
);
|
||||
|
||||
bool implicitPhasePressure
|
||||
(
|
||||
mesh.solverDict(alpha1.name()).lookupOrDefault
|
||||
(
|
||||
"implicitPhasePressure", false
|
||||
)
|
||||
);
|
||||
|
||||
#include "pUf/createRDeltaTf.H"
|
||||
#include "pUf/createDDtU.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -159,7 +123,6 @@ int main(int argc, char *argv[])
|
||||
#include "pUf/UEqns.H"
|
||||
#include "EEqns.H"
|
||||
#include "pUf/pEqn.H"
|
||||
#include "pUf/DDtU.H"
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -1,657 +0,0 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd |
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2015-2017 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "alphatWallBoilingWallFunctionFvPatchScalarField.H"
|
||||
#include "fvPatchFieldMapper.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
#include "twoPhaseSystem.H"
|
||||
#include "phaseSystem.H"
|
||||
#include "ThermalPhaseChangePhaseSystem.H"
|
||||
#include "MomentumTransferPhaseSystem.H"
|
||||
#include "compressibleTurbulenceModel.H"
|
||||
#include "ThermalDiffusivity.H"
|
||||
#include "PhaseCompressibleTurbulenceModel.H"
|
||||
#include "saturationModel.H"
|
||||
#include "wallFvPatch.H"
|
||||
#include "uniformDimensionedFields.H"
|
||||
#include "mathematicalConstants.H"
|
||||
|
||||
using namespace Foam::constant::mathematical;
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
const Foam::Enum
|
||||
<
|
||||
Foam::compressible::
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField::phaseType
|
||||
>
|
||||
Foam::compressible::
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField::phaseTypeNames_
|
||||
({
|
||||
{ phaseType::vaporPhase, "vapor" },
|
||||
{ phaseType::liquidPhase, "liquid" },
|
||||
});
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace compressible
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField::
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField
|
||||
(
|
||||
const fvPatch& p,
|
||||
const DimensionedField<scalar, volMesh>& iF
|
||||
)
|
||||
:
|
||||
alphatPhaseChangeJayatillekeWallFunctionFvPatchScalarField(p, iF),
|
||||
phaseType_(liquidPhase),
|
||||
relax_(0.5),
|
||||
AbyV_(p.size(), 0),
|
||||
alphatConv_(p.size(), 0),
|
||||
dDep_(p.size(), 1e-5),
|
||||
qq_(p.size(), 0),
|
||||
partitioningModel_(nullptr),
|
||||
nucleationSiteModel_(nullptr),
|
||||
departureDiamModel_(nullptr),
|
||||
departureFreqModel_(nullptr)
|
||||
{
|
||||
AbyV_ = this->patch().magSf();
|
||||
forAll(AbyV_, facei)
|
||||
{
|
||||
const label faceCelli = this->patch().faceCells()[facei];
|
||||
AbyV_[facei] /= iF.mesh().V()[faceCelli];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField::
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField
|
||||
(
|
||||
const fvPatch& p,
|
||||
const DimensionedField<scalar, volMesh>& iF,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
alphatPhaseChangeJayatillekeWallFunctionFvPatchScalarField(p, iF, dict),
|
||||
phaseType_(phaseTypeNames_.get("phaseType", dict)),
|
||||
relax_(dict.lookupOrDefault<scalar>("relax", 0.5)),
|
||||
AbyV_(p.size(), 0),
|
||||
alphatConv_(p.size(), 0),
|
||||
dDep_(p.size(), 1e-5),
|
||||
qq_(p.size(), 0),
|
||||
partitioningModel_(nullptr),
|
||||
nucleationSiteModel_(nullptr),
|
||||
departureDiamModel_(nullptr),
|
||||
departureFreqModel_(nullptr)
|
||||
{
|
||||
switch (phaseType_)
|
||||
{
|
||||
case vaporPhase:
|
||||
{
|
||||
partitioningModel_ =
|
||||
wallBoilingModels::partitioningModel::New
|
||||
(
|
||||
dict.subDict("partitioningModel")
|
||||
);
|
||||
|
||||
dmdt_ = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
case liquidPhase:
|
||||
{
|
||||
partitioningModel_ =
|
||||
wallBoilingModels::partitioningModel::New
|
||||
(
|
||||
dict.subDict("partitioningModel")
|
||||
);
|
||||
|
||||
nucleationSiteModel_ =
|
||||
wallBoilingModels::nucleationSiteModel::New
|
||||
(
|
||||
dict.subDict("nucleationSiteModel")
|
||||
);
|
||||
|
||||
departureDiamModel_ =
|
||||
wallBoilingModels::departureDiameterModel::New
|
||||
(
|
||||
dict.subDict("departureDiamModel")
|
||||
);
|
||||
|
||||
departureFreqModel_ =
|
||||
wallBoilingModels::departureFrequencyModel::New
|
||||
(
|
||||
dict.subDict("departureFreqModel")
|
||||
);
|
||||
|
||||
if (dict.found("dDep"))
|
||||
{
|
||||
dDep_ = scalarField("dDep", dict, p.size());
|
||||
}
|
||||
|
||||
if (dict.found("qQuenching"))
|
||||
{
|
||||
qq_ = scalarField("qQuenching", dict, p.size());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dict.found("alphatConv"))
|
||||
{
|
||||
alphatConv_ = scalarField("alphatConv", dict, p.size());
|
||||
}
|
||||
|
||||
AbyV_ = this->patch().magSf();
|
||||
forAll(AbyV_, facei)
|
||||
{
|
||||
const label faceCelli = this->patch().faceCells()[facei];
|
||||
AbyV_[facei] /= iF.mesh().V()[faceCelli];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField::
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField
|
||||
(
|
||||
const alphatWallBoilingWallFunctionFvPatchScalarField& psf,
|
||||
const fvPatch& p,
|
||||
const DimensionedField<scalar, volMesh>& iF,
|
||||
const fvPatchFieldMapper& mapper
|
||||
)
|
||||
:
|
||||
alphatPhaseChangeJayatillekeWallFunctionFvPatchScalarField
|
||||
(
|
||||
psf,
|
||||
p,
|
||||
iF,
|
||||
mapper
|
||||
),
|
||||
relax_(psf.relax_),
|
||||
AbyV_(psf.AbyV_),
|
||||
alphatConv_(psf.alphatConv_, mapper),
|
||||
dDep_(psf.dDep_, mapper),
|
||||
qq_(psf.qq_, mapper),
|
||||
partitioningModel_(psf.partitioningModel_),
|
||||
nucleationSiteModel_(psf.nucleationSiteModel_),
|
||||
departureDiamModel_(psf.departureDiamModel_),
|
||||
departureFreqModel_(psf.departureFreqModel_)
|
||||
{}
|
||||
|
||||
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField::
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField
|
||||
(
|
||||
const alphatWallBoilingWallFunctionFvPatchScalarField& psf
|
||||
)
|
||||
:
|
||||
alphatPhaseChangeJayatillekeWallFunctionFvPatchScalarField(psf),
|
||||
relax_(psf.relax_),
|
||||
AbyV_(psf.AbyV_),
|
||||
alphatConv_(psf.alphatConv_),
|
||||
dDep_(psf.dDep_),
|
||||
qq_(psf.qq_),
|
||||
partitioningModel_(psf.partitioningModel_),
|
||||
nucleationSiteModel_(psf.nucleationSiteModel_),
|
||||
departureDiamModel_(psf.departureDiamModel_),
|
||||
departureFreqModel_(psf.departureFreqModel_)
|
||||
{}
|
||||
|
||||
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField::
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField
|
||||
(
|
||||
const alphatWallBoilingWallFunctionFvPatchScalarField& psf,
|
||||
const DimensionedField<scalar, volMesh>& iF
|
||||
)
|
||||
:
|
||||
alphatPhaseChangeJayatillekeWallFunctionFvPatchScalarField(psf, iF),
|
||||
relax_(psf.relax_),
|
||||
AbyV_(psf.AbyV_),
|
||||
alphatConv_(psf.alphatConv_),
|
||||
dDep_(psf.dDep_),
|
||||
qq_(psf.qq_),
|
||||
partitioningModel_(psf.partitioningModel_),
|
||||
nucleationSiteModel_(psf.nucleationSiteModel_),
|
||||
departureDiamModel_(psf.departureDiamModel_),
|
||||
departureFreqModel_(psf.departureFreqModel_)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void alphatWallBoilingWallFunctionFvPatchScalarField::updateCoeffs()
|
||||
{
|
||||
if (updated())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that partitioningModel has been constructed
|
||||
if (!partitioningModel_.valid())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "partitioningModel has not been constructed!"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
// Lookup the fluid model
|
||||
const ThermalPhaseChangePhaseSystem
|
||||
<
|
||||
MomentumTransferPhaseSystem<twoPhaseSystem>
|
||||
>& fluid =
|
||||
refCast
|
||||
<
|
||||
const ThermalPhaseChangePhaseSystem
|
||||
<
|
||||
MomentumTransferPhaseSystem<twoPhaseSystem>
|
||||
>
|
||||
>
|
||||
(
|
||||
db().lookupObject<phaseSystem>("phaseProperties")
|
||||
);
|
||||
|
||||
const label patchi = patch().index();
|
||||
|
||||
switch (phaseType_)
|
||||
{
|
||||
case vaporPhase:
|
||||
{
|
||||
const phaseModel& vapor
|
||||
(
|
||||
fluid.phase1().name() == internalField().group()
|
||||
? fluid.phase1()
|
||||
: fluid.phase2()
|
||||
);
|
||||
|
||||
const phaseModel& liquid(fluid.otherPhase(vapor));
|
||||
|
||||
// Liquid phase fraction at the wall
|
||||
const scalarField liquidw(liquid.boundaryField()[patchi]);
|
||||
|
||||
// Vapor Liquid phase fraction at the wall
|
||||
const scalarField vaporw(vapor.boundaryField()[patchi]);
|
||||
|
||||
const scalarField fLiquid
|
||||
(
|
||||
partitioningModel_->fLiquid(liquidw)
|
||||
);
|
||||
|
||||
operator==
|
||||
(
|
||||
calcAlphat(*this)*(1 - fLiquid)/max(vaporw, scalar(1e-8))
|
||||
);
|
||||
break;
|
||||
}
|
||||
case liquidPhase:
|
||||
{
|
||||
// Check that nucleationSiteModel has been constructed
|
||||
if (!nucleationSiteModel_.valid())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "nucleationSiteModel has not been constructed!"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
// Check that departureDiameterModel has been constructed
|
||||
if (!departureDiamModel_.valid())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "departureDiameterModel has not been constructed!"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
// Check that nucleationSiteModel has been constructed
|
||||
if (!departureFreqModel_.valid())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "departureFrequencyModel has not been constructed!"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
const phaseModel& liquid
|
||||
(
|
||||
fluid.phase1().name() == internalField().group()
|
||||
? fluid.phase1()
|
||||
: fluid.phase2()
|
||||
);
|
||||
|
||||
const phaseModel& vapor(fluid.otherPhase(liquid));
|
||||
|
||||
// Retrieve turbulence properties from model
|
||||
const phaseCompressibleTurbulenceModel& turbModel =
|
||||
liquid.turbulence();
|
||||
|
||||
const tmp<scalarField> tnutw = turbModel.nut(patchi);
|
||||
|
||||
const scalar Cmu25(pow025(Cmu_));
|
||||
|
||||
const scalarField& y = turbModel.y()[patchi];
|
||||
|
||||
const tmp<scalarField> tmuw = turbModel.mu(patchi);
|
||||
const scalarField& muw = tmuw();
|
||||
|
||||
const tmp<scalarField> talphaw = liquid.thermo().alpha(patchi);
|
||||
const scalarField& alphaw = talphaw();
|
||||
|
||||
const tmp<volScalarField> tk = turbModel.k();
|
||||
const volScalarField& k = tk();
|
||||
const fvPatchScalarField& kw = k.boundaryField()[patchi];
|
||||
|
||||
const fvPatchVectorField& Uw =
|
||||
turbModel.U().boundaryField()[patchi];
|
||||
const scalarField magUp(mag(Uw.patchInternalField() - Uw));
|
||||
const scalarField magGradUw(mag(Uw.snGrad()));
|
||||
|
||||
const fvPatchScalarField& rhow =
|
||||
turbModel.rho().boundaryField()[patchi];
|
||||
const fvPatchScalarField& hew =
|
||||
liquid.thermo().he().boundaryField()[patchi];
|
||||
|
||||
const fvPatchScalarField& Tw =
|
||||
liquid.thermo().T().boundaryField()[patchi];
|
||||
const scalarField Tc(Tw.patchInternalField());
|
||||
|
||||
const scalarField uTau(Cmu25*sqrt(kw));
|
||||
|
||||
const scalarField yPlus(uTau*y/(muw/rhow));
|
||||
|
||||
const scalarField Pr(muw/alphaw);
|
||||
|
||||
// Molecular-to-turbulent Prandtl number ratio
|
||||
const scalarField Prat(Pr/Prt_);
|
||||
|
||||
// Thermal sublayer thickness
|
||||
const scalarField P(this->Psmooth(Prat));
|
||||
|
||||
const scalarField yPlusTherm(this->yPlusTherm(P, Prat));
|
||||
|
||||
const fvPatchScalarField& rhoLiquidw =
|
||||
liquid.turbulence().rho().boundaryField()[patchi];
|
||||
|
||||
const fvPatchScalarField& rhoVaporw =
|
||||
vapor.turbulence().rho().boundaryField()[patchi];
|
||||
|
||||
tmp<volScalarField> tCp = liquid.thermo().Cp();
|
||||
const volScalarField& Cp = tCp();
|
||||
const fvPatchScalarField& Cpw = Cp.boundaryField()[patchi];
|
||||
|
||||
// Saturation temperature
|
||||
const tmp<volScalarField> tTsat =
|
||||
fluid.saturation().Tsat(liquid.thermo().p());
|
||||
const volScalarField& Tsat = tTsat();
|
||||
const fvPatchScalarField& Tsatw(Tsat.boundaryField()[patchi]);
|
||||
const scalarField Tsatc(Tsatw.patchInternalField());
|
||||
|
||||
const fvPatchScalarField& pw =
|
||||
liquid.thermo().p().boundaryField()[patchi];
|
||||
|
||||
const scalarField L
|
||||
(
|
||||
vapor.thermo().he(pw,Tsatc,patchi)-hew.patchInternalField()
|
||||
);
|
||||
|
||||
// Liquid phase fraction at the wall
|
||||
const scalarField liquidw(liquid.boundaryField()[patchi]);
|
||||
|
||||
const scalarField fLiquid(partitioningModel_->fLiquid(liquidw));
|
||||
|
||||
// Convective thermal diffusivity
|
||||
alphatConv_ = calcAlphat(alphatConv_);
|
||||
|
||||
for (label i=0; i<10; i++)
|
||||
{
|
||||
// Liquid temperature at y+=250 is estimated from logarithmic
|
||||
// thermal wall function (Koncar, Krepper & Egorov, 2005)
|
||||
const scalarField Tplus_y250(Prt_*(log(E_*250)/kappa_ + P));
|
||||
|
||||
const scalarField Tplus(Prt_*(log(E_*yPlus)/kappa_ + P));
|
||||
scalarField Tl(Tw - (Tplus_y250/Tplus)*(Tw - Tc));
|
||||
Tl = max(Tc - 40, Tl);
|
||||
|
||||
// Nucleation site density:
|
||||
const scalarField N
|
||||
(
|
||||
nucleationSiteModel_->N
|
||||
(
|
||||
liquid,
|
||||
vapor,
|
||||
patchi,
|
||||
Tl,
|
||||
Tsatw,
|
||||
L
|
||||
)
|
||||
);
|
||||
|
||||
// Bubble departure diameter:
|
||||
dDep_ = departureDiamModel_->dDeparture
|
||||
(
|
||||
liquid,
|
||||
vapor,
|
||||
patchi,
|
||||
Tl,
|
||||
Tsatw,
|
||||
L
|
||||
);
|
||||
|
||||
// Bubble departure frequency:
|
||||
const scalarField fDep
|
||||
(
|
||||
departureFreqModel_->fDeparture
|
||||
(
|
||||
liquid,
|
||||
vapor,
|
||||
patchi,
|
||||
dDep_
|
||||
)
|
||||
);
|
||||
|
||||
// Area fractions:
|
||||
|
||||
// Del Valle & Kenning (1985)
|
||||
const scalarField Ja
|
||||
(
|
||||
rhoLiquidw*Cpw*(Tsatw - Tl)/(rhoVaporw*L)
|
||||
);
|
||||
const scalarField Al
|
||||
(
|
||||
fLiquid*4.8*exp( min(-Ja/80,log(VGREAT)))
|
||||
);
|
||||
|
||||
const scalarField A2(min(pi*sqr(dDep_)*N*Al/4, scalar(1)));
|
||||
const scalarField A1(max(1 - A2, scalar(1e-4)));
|
||||
const scalarField A2E(min(pi*sqr(dDep_)*N*Al/4, scalar(5)));
|
||||
|
||||
// Volumetric mass source in the near wall cell due to the
|
||||
// wall boiling
|
||||
dmdt_ =
|
||||
(1 - relax_)*dmdt_
|
||||
+ relax_*(1.0/6.0)*A2E*dDep_*rhoVaporw*fDep*AbyV_;
|
||||
|
||||
// Volumetric source in the near wall cell due to the wall
|
||||
// boiling
|
||||
mDotL_ = dmdt_*L;
|
||||
|
||||
// Quenching heat transfer coefficient
|
||||
const scalarField hQ
|
||||
(
|
||||
2*(alphaw*Cpw)*fDep*sqrt((0.8/fDep)/(pi*alphaw/rhow))
|
||||
);
|
||||
|
||||
// Quenching heat flux
|
||||
qq_ = (A2*hQ*max(Tw - Tl, scalar(0)));
|
||||
|
||||
// Effective thermal diffusivity that corresponds to the
|
||||
// calculated convective, quenching and evaporative heat fluxes
|
||||
|
||||
operator==
|
||||
(
|
||||
(
|
||||
A1*alphatConv_
|
||||
+ (qq_ + qe())/max(hew.snGrad(), scalar(1e-16))
|
||||
)
|
||||
/max(liquidw, scalar(1e-8))
|
||||
);
|
||||
|
||||
scalarField TsupPrev(max((Tw - Tsatw),scalar(0)));
|
||||
const_cast<fvPatchScalarField&>(Tw).evaluate();
|
||||
scalarField TsupNew(max((Tw - Tsatw),scalar(0)));
|
||||
|
||||
scalar maxErr(max(mag(TsupPrev - TsupNew)));
|
||||
|
||||
if (maxErr < 1e-1)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
Info<< "Wall boiling wall function iterations: "
|
||||
<< i + 1 << endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
const scalarField qc
|
||||
(
|
||||
fLiquid*A1*(alphatConv_ + alphaw)*hew.snGrad()
|
||||
);
|
||||
|
||||
const scalarField qEff
|
||||
(
|
||||
liquidw*(*this + alphaw)*hew.snGrad()
|
||||
);
|
||||
|
||||
Info<< " L: " << gMin(L) << " - " << gMax(L) << endl;
|
||||
Info<< " Tl: " << gMin(Tl) << " - " << gMax(Tl) << endl;
|
||||
Info<< " N: " << gMin(N) << " - " << gMax(N) << endl;
|
||||
Info<< " dDep_: " << gMin(dDep_) << " - "
|
||||
<< gMax(dDep_) << endl;
|
||||
Info<< " fDep: " << gMin(fDep) << " - "
|
||||
<< gMax(fDep) << endl;
|
||||
Info<< " Al: " << gMin(Al) << " - " << gMax(Al) << endl;
|
||||
Info<< " A1: " << gMin(A1) << " - " << gMax(A1) << endl;
|
||||
Info<< " A2: " << gMin(A2) << " - " << gMax(A2) << endl;
|
||||
Info<< " A2E: " << gMin(A2E) << " - "
|
||||
<< gMax(A2E) << endl;
|
||||
Info<< " dmdtW: " << gMin(dmdt_) << " - "
|
||||
<< gMax(dmdt_) << endl;
|
||||
Info<< " qc: " << gMin(qc) << " - " << gMax(qc) << endl;
|
||||
Info<< " qq: " << gMin(fLiquid*qq()) << " - "
|
||||
<< gMax(fLiquid*qq()) << endl;
|
||||
Info<< " qe: " << gMin(fLiquid*qe()) << " - "
|
||||
<< gMax(fLiquid*qe()) << endl;
|
||||
Info<< " qEff: " << gMin(qEff) << " - "
|
||||
<< gMax(qEff) << endl;
|
||||
Info<< " alphat: " << gMin(*this) << " - "
|
||||
<< gMax(*this) << endl;
|
||||
Info<< " alphatConv: " << gMin(alphatConv_)
|
||||
<< " - " << gMax(alphatConv_) << endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Unknown phase type. Valid types are: "
|
||||
<< phaseTypeNames_ << nl << exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
fixedValueFvPatchScalarField::updateCoeffs();
|
||||
}
|
||||
|
||||
|
||||
void alphatWallBoilingWallFunctionFvPatchScalarField::write(Ostream& os) const
|
||||
{
|
||||
fvPatchField<scalar>::write(os);
|
||||
|
||||
os.writeEntry("phaseType", phaseTypeNames_[phaseType_]);
|
||||
|
||||
os.writeEntry("relax", relax_);
|
||||
|
||||
switch (phaseType_)
|
||||
{
|
||||
case vaporPhase:
|
||||
{
|
||||
os.beginBlock("partitioningModel");
|
||||
partitioningModel_->write(os);
|
||||
os.endBlock();
|
||||
break;
|
||||
}
|
||||
case liquidPhase:
|
||||
{
|
||||
os.beginBlock("partitioningModel");
|
||||
partitioningModel_->write(os);
|
||||
os.endBlock();
|
||||
|
||||
os.beginBlock("nucleationSiteModel");
|
||||
nucleationSiteModel_->write(os);
|
||||
os.endBlock();
|
||||
|
||||
os.beginBlock("departureDiamModel");
|
||||
departureDiamModel_->write(os);
|
||||
os.endBlock();
|
||||
|
||||
os.beginBlock("departureFreqModel");
|
||||
departureFreqModel_->write(os);
|
||||
os.endBlock();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dmdt_.writeEntry("dmdt", os);
|
||||
dDep_.writeEntry("dDep", os);
|
||||
qq_.writeEntry("qQuenching", os);
|
||||
alphatConv_.writeEntry("alphatConv", os);
|
||||
writeEntry("value", os);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
makePatchTypeField
|
||||
(
|
||||
fvPatchScalarField,
|
||||
alphatWallBoilingWallFunctionFvPatchScalarField
|
||||
);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace compressible
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -12,7 +12,15 @@
|
||||
)
|
||||
);
|
||||
|
||||
MULES::explicitSolve(alpha1, phi, alphaPhi, 1, 0);
|
||||
MULES::explicitSolve
|
||||
(
|
||||
geometricOneField(),
|
||||
alpha1,
|
||||
phi,
|
||||
alphaPhi,
|
||||
oneField(),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
rhoPhi = alphaPhi*(rho1 - rho2) + phi*rho2;
|
||||
|
||||
|
||||
@ -345,12 +345,12 @@ Foam::RASModels::kineticTheoryModel::divDevRhoReff
|
||||
void Foam::RASModels::kineticTheoryModel::correct()
|
||||
{
|
||||
// Local references
|
||||
const twoPhaseSystem& fluid = refCast<const twoPhaseSystem>(phase_.fluid());
|
||||
volScalarField alpha(max(alpha_, scalar(0)));
|
||||
const volScalarField& rho = phase_.rho();
|
||||
const surfaceScalarField& alphaRhoPhi = alphaRhoPhi_;
|
||||
const volVectorField& U = U_;
|
||||
const volVectorField& Uc_ =
|
||||
refCast<const twoPhaseSystem>(phase_.fluid()).otherPhase(phase_).U();
|
||||
const volVectorField& Uc_ = fluid.otherPhase(phase_).U();
|
||||
|
||||
const scalar sqrtPi = sqrt(constant::mathematical::pi);
|
||||
dimensionedScalar ThetaSmall("ThetaSmall", Theta_.dimensions(), 1.0e-6);
|
||||
@ -394,7 +394,11 @@ void Foam::RASModels::kineticTheoryModel::correct()
|
||||
// Drag
|
||||
volScalarField beta
|
||||
(
|
||||
refCast<const twoPhaseSystem>(phase_.fluid()).drag(phase_).K()
|
||||
fluid.lookupSubModel<dragModel>
|
||||
(
|
||||
phase_,
|
||||
fluid.otherPhase(phase_)
|
||||
).K()
|
||||
);
|
||||
|
||||
// Eq. 3.25, p. 50 Js = J1 - J2
|
||||
|
||||
@ -56,7 +56,7 @@ class hyperbolic
|
||||
// Private data
|
||||
|
||||
//- Maximum fraction of phases which can be considered dispersed
|
||||
HashTable<dimensionedScalar> maxDispersedAlpha_;
|
||||
HashTable<dimensionedScalar, word, word::hash> maxDispersedAlpha_;
|
||||
|
||||
//- Width of the transition
|
||||
const dimensionedScalar transitionAlphaScale_;
|
||||
|
||||
@ -56,10 +56,12 @@ class linear
|
||||
// Private data
|
||||
|
||||
//- Maximum fraction of phases which can be considered fully dispersed
|
||||
HashTable<dimensionedScalar> maxFullyDispersedAlpha_;
|
||||
HashTable<dimensionedScalar, word, word::hash>
|
||||
maxFullyDispersedAlpha_;
|
||||
|
||||
//- Maximum fraction of phases which can be considered partly dispersed
|
||||
HashTable<dimensionedScalar> maxPartlyDispersedAlpha_;
|
||||
HashTable<dimensionedScalar, word, word::hash>
|
||||
maxPartlyDispersedAlpha_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
@ -210,6 +210,18 @@ public:
|
||||
return thermo_->kappa();
|
||||
}
|
||||
|
||||
//- Thermal diffusivity for energy of mixture [kg/m/s]
|
||||
tmp<volScalarField> alphahe() const
|
||||
{
|
||||
return thermo_->alphahe();
|
||||
}
|
||||
|
||||
//- Thermal diffusivity for energy of mixture for patch [kg/m/s]
|
||||
tmp<scalarField> alphahe(const label patchi) const
|
||||
{
|
||||
return thermo_->alphahe(patchi);
|
||||
}
|
||||
|
||||
//- Return the laminar thermal conductivity
|
||||
tmp<volScalarField> kappaEff
|
||||
(
|
||||
|
||||
@ -29,6 +29,15 @@ License
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
Foam::phasePairKey::hash::hash()
|
||||
{}
|
||||
|
||||
|
||||
Foam::phasePairKey::phasePairKey()
|
||||
{}
|
||||
|
||||
|
||||
Foam::phasePairKey::phasePairKey
|
||||
(
|
||||
const word& name1,
|
||||
@ -41,12 +50,10 @@ Foam::phasePairKey::phasePairKey
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::phasePairKey::ordered() const
|
||||
{
|
||||
return ordered_;
|
||||
}
|
||||
Foam::phasePairKey::~phasePairKey()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
|
||||
@ -65,8 +72,12 @@ Foam::label Foam::phasePairKey::hash::operator()
|
||||
word::hash()(key.second())
|
||||
);
|
||||
}
|
||||
|
||||
return word::hash()(key.first()) + word::hash()(key.second());
|
||||
else
|
||||
{
|
||||
return
|
||||
word::hash()(key.first())
|
||||
+ word::hash()(key.second());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -78,12 +89,13 @@ bool Foam::operator==
|
||||
const phasePairKey& b
|
||||
)
|
||||
{
|
||||
const auto cmp = Pair<word>::compare(a,b);
|
||||
const auto c = Pair<word>::compare(a,b);
|
||||
|
||||
return
|
||||
(
|
||||
(a.ordered_ == b.ordered_)
|
||||
&& (a.ordered_ ? (cmp == 1) : cmp)
|
||||
&& (
|
||||
(a.ordered_ && (c == 1))
|
||||
|| (!a.ordered_ && (c != 0))
|
||||
);
|
||||
}
|
||||
|
||||
@ -119,8 +131,8 @@ Foam::Istream& Foam::operator>>(Istream& is, phasePairKey& key)
|
||||
FatalErrorInFunction
|
||||
<< "Phase pair type is not recognised. "
|
||||
<< temp
|
||||
<< "Use (phaseDispersed in phaseContinuous) for an ordered pair, "
|
||||
<< "or (phase1 and phase2) for an unordered pair."
|
||||
<< "Use (phaseDispersed in phaseContinuous) for an ordered"
|
||||
<< "pair, or (phase1 and pase2) for an unordered pair."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
|
||||
@ -59,6 +59,29 @@ class phasePairKey
|
||||
:
|
||||
public Pair<word>
|
||||
{
|
||||
public:
|
||||
|
||||
class hash
|
||||
:
|
||||
public Hash<phasePairKey>
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
// Construct null
|
||||
hash();
|
||||
|
||||
|
||||
// Member operators
|
||||
|
||||
// Generate a hash from a phase pair key
|
||||
label operator()(const phasePairKey& key) const;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
//- Flag to indicate whether ordering is important
|
||||
@ -66,30 +89,23 @@ class phasePairKey
|
||||
|
||||
public:
|
||||
|
||||
//- Ordered or unordered hashing of word pair
|
||||
struct hash
|
||||
{
|
||||
//- Generate a hash from a phase pair key
|
||||
label operator()(const phasePairKey& key) const;
|
||||
};
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
phasePairKey() {} // = default
|
||||
phasePairKey();
|
||||
|
||||
//- Construct from names and optional ordering flag
|
||||
//- Construct from names and the ordering flag
|
||||
phasePairKey
|
||||
(
|
||||
const word& name1,
|
||||
const word& name2,
|
||||
const bool ordered = false
|
||||
const bool ordered
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~phasePairKey() = default;
|
||||
virtual ~phasePairKey();
|
||||
|
||||
|
||||
// Access
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd |
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2013-2017 OpenFOAM Foundation
|
||||
| Copyright (C) 2013-2018 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -47,6 +47,7 @@ License
|
||||
#include "fixedValueFvsPatchFields.H"
|
||||
#include "blendingMethod.H"
|
||||
#include "HashPtrTable.H"
|
||||
#include "UniformField.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
@ -108,21 +109,21 @@ Foam::twoPhaseSystem::twoPhaseSystem
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
mesh,
|
||||
dimensionedScalar(dimless/dimTime, Zero)
|
||||
dimensionedScalar("dgdt", dimless/dimTime, 0)
|
||||
)
|
||||
{
|
||||
phase2_.volScalarField::operator=(scalar(1) - phase1_);
|
||||
|
||||
|
||||
// Blending
|
||||
for (const entry& dEntry : subDict("blending"))
|
||||
forAllConstIter(dictionary, subDict("blending"), iter)
|
||||
{
|
||||
blendingMethods_.insert
|
||||
(
|
||||
dEntry.dict().dictName(),
|
||||
iter().dict().dictName(),
|
||||
blendingMethod::New
|
||||
(
|
||||
dEntry.dict(),
|
||||
iter().dict(),
|
||||
wordList(lookup("phases"))
|
||||
)
|
||||
);
|
||||
@ -134,7 +135,7 @@ Foam::twoPhaseSystem::twoPhaseSystem
|
||||
phasePair::scalarTable sigmaTable(lookup("sigma"));
|
||||
phasePair::dictTable aspectRatioTable(lookup("aspectRatio"));
|
||||
|
||||
pair_.reset
|
||||
pair_.set
|
||||
(
|
||||
new phasePair
|
||||
(
|
||||
@ -145,7 +146,7 @@ Foam::twoPhaseSystem::twoPhaseSystem
|
||||
)
|
||||
);
|
||||
|
||||
pair1In2_.reset
|
||||
pair1In2_.set
|
||||
(
|
||||
new orderedPhasePair
|
||||
(
|
||||
@ -157,7 +158,7 @@ Foam::twoPhaseSystem::twoPhaseSystem
|
||||
)
|
||||
);
|
||||
|
||||
pair2In1_.reset
|
||||
pair2In1_.set
|
||||
(
|
||||
new orderedPhasePair
|
||||
(
|
||||
@ -172,100 +173,100 @@ Foam::twoPhaseSystem::twoPhaseSystem
|
||||
|
||||
// Models
|
||||
|
||||
drag_.reset
|
||||
drag_.set
|
||||
(
|
||||
new BlendedInterfacialModel<dragModel>
|
||||
(
|
||||
lookup("drag"),
|
||||
(
|
||||
blendingMethods_.found("drag")
|
||||
? *(blendingMethods_["drag"])
|
||||
: *(blendingMethods_["default"])
|
||||
? blendingMethods_["drag"]
|
||||
: blendingMethods_["default"]
|
||||
),
|
||||
*pair_,
|
||||
*pair1In2_,
|
||||
*pair2In1_,
|
||||
pair_,
|
||||
pair1In2_,
|
||||
pair2In1_,
|
||||
false // Do not zero drag coefficient at fixed-flux BCs
|
||||
)
|
||||
);
|
||||
|
||||
virtualMass_.reset
|
||||
virtualMass_.set
|
||||
(
|
||||
new BlendedInterfacialModel<virtualMassModel>
|
||||
(
|
||||
lookup("virtualMass"),
|
||||
(
|
||||
blendingMethods_.found("virtualMass")
|
||||
? *(blendingMethods_["virtualMass"])
|
||||
: *(blendingMethods_["default"])
|
||||
? blendingMethods_["virtualMass"]
|
||||
: blendingMethods_["default"]
|
||||
),
|
||||
*pair_,
|
||||
*pair1In2_,
|
||||
*pair2In1_
|
||||
pair_,
|
||||
pair1In2_,
|
||||
pair2In1_
|
||||
)
|
||||
);
|
||||
|
||||
heatTransfer_.reset
|
||||
heatTransfer_.set
|
||||
(
|
||||
new BlendedInterfacialModel<heatTransferModel>
|
||||
(
|
||||
lookup("heatTransfer"),
|
||||
(
|
||||
blendingMethods_.found("heatTransfer")
|
||||
? *(blendingMethods_["heatTransfer"])
|
||||
: *(blendingMethods_["default"])
|
||||
? blendingMethods_["heatTransfer"]
|
||||
: blendingMethods_["default"]
|
||||
),
|
||||
*pair_,
|
||||
*pair1In2_,
|
||||
*pair2In1_
|
||||
pair_,
|
||||
pair1In2_,
|
||||
pair2In1_
|
||||
)
|
||||
);
|
||||
|
||||
lift_.reset
|
||||
lift_.set
|
||||
(
|
||||
new BlendedInterfacialModel<liftModel>
|
||||
(
|
||||
lookup("lift"),
|
||||
(
|
||||
blendingMethods_.found("lift")
|
||||
? *(blendingMethods_["lift"])
|
||||
: *(blendingMethods_["default"])
|
||||
? blendingMethods_["lift"]
|
||||
: blendingMethods_["default"]
|
||||
),
|
||||
*pair_,
|
||||
*pair1In2_,
|
||||
*pair2In1_
|
||||
pair_,
|
||||
pair1In2_,
|
||||
pair2In1_
|
||||
)
|
||||
);
|
||||
|
||||
wallLubrication_.reset
|
||||
wallLubrication_.set
|
||||
(
|
||||
new BlendedInterfacialModel<wallLubricationModel>
|
||||
(
|
||||
lookup("wallLubrication"),
|
||||
(
|
||||
blendingMethods_.found("wallLubrication")
|
||||
? *(blendingMethods_["wallLubrication"])
|
||||
: *(blendingMethods_["default"])
|
||||
? blendingMethods_["wallLubrication"]
|
||||
: blendingMethods_["default"]
|
||||
),
|
||||
*pair_,
|
||||
*pair1In2_,
|
||||
*pair2In1_
|
||||
pair_,
|
||||
pair1In2_,
|
||||
pair2In1_
|
||||
)
|
||||
);
|
||||
|
||||
turbulentDispersion_.reset
|
||||
turbulentDispersion_.set
|
||||
(
|
||||
new BlendedInterfacialModel<turbulentDispersionModel>
|
||||
(
|
||||
lookup("turbulentDispersion"),
|
||||
(
|
||||
blendingMethods_.found("turbulentDispersion")
|
||||
? *(blendingMethods_["turbulentDispersion"])
|
||||
: *(blendingMethods_["default"])
|
||||
? blendingMethods_["turbulentDispersion"]
|
||||
: blendingMethods_["default"]
|
||||
),
|
||||
*pair_,
|
||||
*pair1In2_,
|
||||
*pair2In1_
|
||||
pair_,
|
||||
pair1In2_,
|
||||
pair2In1_
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -274,7 +275,7 @@ Foam::twoPhaseSystem::twoPhaseSystem
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::twoPhaseSystem::~twoPhaseSystem()
|
||||
{} // Define here (incomplete type in header)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
@ -362,8 +363,8 @@ void Foam::twoPhaseSystem::solve()
|
||||
alpha1.name()
|
||||
);
|
||||
|
||||
label nAlphaSubCycles(alphaControls.get<label>("nAlphaSubCycles"));
|
||||
label nAlphaCorr(alphaControls.get<label>("nAlphaCorr"));
|
||||
label nAlphaSubCycles(readLabel(alphaControls.lookup("nAlphaSubCycles")));
|
||||
label nAlphaCorr(readLabel(alphaControls.lookup("nAlphaCorr")));
|
||||
|
||||
word alphaScheme("div(phi," + alpha1.name() + ')');
|
||||
word alpharScheme("div(phir," + alpha1.name() + ')');
|
||||
@ -401,7 +402,7 @@ void Foam::twoPhaseSystem::solve()
|
||||
mesh_
|
||||
),
|
||||
mesh_,
|
||||
dimensionedScalar(dgdt_.dimensions(), Zero)
|
||||
dimensionedScalar("Sp", dgdt_.dimensions(), 0.0)
|
||||
);
|
||||
|
||||
volScalarField::Internal Su
|
||||
@ -466,8 +467,8 @@ void Foam::twoPhaseSystem::solve()
|
||||
alphaPhic10,
|
||||
(alphaSubCycle.index()*Sp)(),
|
||||
(Su - (alphaSubCycle.index() - 1)*Sp*alpha1)(),
|
||||
phase1_.alphaMax(),
|
||||
0
|
||||
UniformField<scalar>(phase1_.alphaMax()),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
if (alphaSubCycle.index() == 1)
|
||||
@ -492,8 +493,8 @@ void Foam::twoPhaseSystem::solve()
|
||||
alphaPhic1,
|
||||
Sp,
|
||||
Su,
|
||||
phase1_.alphaMax(),
|
||||
0
|
||||
UniformField<scalar>(phase1_.alphaMax()),
|
||||
zeroField()
|
||||
);
|
||||
|
||||
phase1_.alphaPhi() = alphaPhic1;
|
||||
@ -568,19 +569,6 @@ bool Foam::twoPhaseSystem::read()
|
||||
}
|
||||
|
||||
|
||||
const Foam::dragModel& Foam::twoPhaseSystem::drag(const phaseModel& phase) const
|
||||
{
|
||||
return drag_->phaseModel(phase);
|
||||
}
|
||||
|
||||
|
||||
const Foam::virtualMassModel&
|
||||
Foam::twoPhaseSystem::virtualMass(const phaseModel& phase) const
|
||||
{
|
||||
return virtualMass_->phaseModel(phase);
|
||||
}
|
||||
|
||||
|
||||
const Foam::dimensionedScalar& Foam::twoPhaseSystem::sigma() const
|
||||
{
|
||||
return pair_->sigma();
|
||||
|
||||
@ -96,7 +96,7 @@ class twoPhaseSystem
|
||||
autoPtr<orderedPhasePair> pair2In1_;
|
||||
|
||||
//- Blending methods
|
||||
HashTable<autoPtr<blendingMethod>> blendingMethods_;
|
||||
HashTable<autoPtr<blendingMethod>, word, word::hash> blendingMethods_;
|
||||
|
||||
//- Drag model
|
||||
autoPtr<BlendedInterfacialModel<dragModel>> drag_;
|
||||
@ -184,11 +184,17 @@ public:
|
||||
|
||||
// Access
|
||||
|
||||
//- Return the drag model for the given phase
|
||||
const dragModel& drag(const phaseModel& phase) const;
|
||||
//- Access a sub model between a phase pair
|
||||
template<class modelType>
|
||||
const modelType& lookupSubModel(const phasePair& key) const;
|
||||
|
||||
//- Return the virtual mass model for the given phase
|
||||
const virtualMassModel& virtualMass(const phaseModel& phase) const;
|
||||
//- Access a sub model between two phases
|
||||
template<class modelType>
|
||||
const modelType& lookupSubModel
|
||||
(
|
||||
const phaseModel& dispersed,
|
||||
const phaseModel& continuous
|
||||
) const;
|
||||
|
||||
//- Return the surface tension coefficient
|
||||
const dimensionedScalar& sigma() const;
|
||||
@ -238,6 +244,12 @@ public:
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "twoPhaseSystemTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -0,0 +1,77 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2015-2018 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "BlendedInterfacialModel.H"
|
||||
#include "dragModel.H"
|
||||
#include "virtualMassModel.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class modelType>
|
||||
const modelType& twoPhaseSystem::lookupSubModel
|
||||
(
|
||||
const phasePair& key
|
||||
) const
|
||||
{
|
||||
return
|
||||
mesh().lookupObject<modelType>
|
||||
(
|
||||
IOobject::groupName(modelType::typeName, key.name())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline const dragModel& twoPhaseSystem::lookupSubModel<dragModel>
|
||||
(
|
||||
const phaseModel& dispersed,
|
||||
const phaseModel& continuous
|
||||
) const
|
||||
{
|
||||
return drag_->phaseModel(dispersed);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline const virtualMassModel& twoPhaseSystem::lookupSubModel<virtualMassModel>
|
||||
(
|
||||
const phaseModel& dispersed,
|
||||
const phaseModel& continuous
|
||||
) const
|
||||
{
|
||||
return virtualMass_->phaseModel(dispersed);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -98,7 +98,7 @@ export WM_COMPILE_OPTION=Opt
|
||||
# = SYSTEMOPENMPI | OPENMPI | SYSTEMMPI | MPI | MPICH | MPICH-GM |
|
||||
# HPMPI | CRAY-MPICH | FJMPI | QSMPI | SGIMPI | INTELMPI | USERMPI
|
||||
# Also possible to use INTELMPI-xyz etc and define your own wmake rule
|
||||
export WM_MPLIB=SYSTEMOPENMPI
|
||||
export WM_MPLIB=OPENMPI
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
@ -108,6 +108,9 @@ wmake $targetType rigidBodyMeshMotion
|
||||
wmake $targetType semiPermeableBaffle
|
||||
wmake $targetType atmosphericModels
|
||||
|
||||
phaseSystemModels/Allwmake $targetType $*
|
||||
wmake $targetType TurbulenceModels/compressible/turbulentFluidThermoModels/
|
||||
|
||||
# Needs access to Turbulence
|
||||
|
||||
wmake $targetType thermophysicalModels/thermophysicalPropertiesFvPatchFields/liquidProperties
|
||||
|
||||
@ -58,6 +58,7 @@ $(ints)/lists/labelListIOList.C
|
||||
primitives/Scalar/doubleScalar/doubleScalar.C
|
||||
primitives/Scalar/floatScalar/floatScalar.C
|
||||
primitives/Scalar/scalar/scalar.C
|
||||
primitives/Scalar/scalar/incGamma.C
|
||||
primitives/Scalar/scalar/invIncGamma.C
|
||||
primitives/Scalar/lists/scalarList.C
|
||||
primitives/Scalar/lists/scalarIOList.C
|
||||
|
||||
@ -245,6 +245,36 @@ Foam::IOobject Foam::IOobject::selectIO
|
||||
}
|
||||
|
||||
|
||||
Foam::word Foam::IOobject::group(const word& name)
|
||||
{
|
||||
word::size_type i = name.find_last_of('.');
|
||||
|
||||
if (i == word::npos || i == 0)
|
||||
{
|
||||
return word::null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return name.substr(i+1, word::npos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::word Foam::IOobject::member(const word& name)
|
||||
{
|
||||
word::size_type i = name.find_last_of('.');
|
||||
|
||||
if (i == word::npos || i == 0)
|
||||
{
|
||||
return name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return name.substr(0, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::IOobject::IOobject
|
||||
|
||||
@ -229,6 +229,13 @@ public:
|
||||
template<class StringType>
|
||||
static inline word groupName(StringType name, const word& group);
|
||||
|
||||
|
||||
//- Return group (extension part of name)
|
||||
static word group(const word& name);
|
||||
|
||||
//- Return member (name without the extension)
|
||||
static word member(const word& name);
|
||||
|
||||
//- Return the IOobject, but also consider an alternative file name.
|
||||
//
|
||||
// \param io The expected IOobject to use
|
||||
|
||||
@ -63,6 +63,9 @@ public:
|
||||
|
||||
// Member Operators
|
||||
|
||||
|
||||
inline operator Type() const;
|
||||
|
||||
inline Type operator[](const label) const;
|
||||
|
||||
inline UniformField field() const;
|
||||
|
||||
@ -36,6 +36,13 @@ inline Foam::UniformField<Type>::UniformField(const Type& value)
|
||||
{}
|
||||
|
||||
|
||||
template<class Type>
|
||||
inline Foam::UniformField<Type>::operator Type() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
inline Type Foam::UniformField<Type>::operator[](const label) const
|
||||
{
|
||||
@ -50,4 +57,65 @@ inline Foam::UniformField<Type> Foam::UniformField<Type>::field() const
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
inline UniformField<Type> min
|
||||
(
|
||||
const UniformField<Type>& u1,
|
||||
const UniformField<Type>& u2
|
||||
)
|
||||
{
|
||||
return UniformField<Type>(min(u1.operator Type(), u2.operator Type()));
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class OtherType>
|
||||
inline OtherType min(const UniformField<Type>& u, const OtherType& o)
|
||||
{
|
||||
return min(u.operator Type(), o);
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class OtherType>
|
||||
inline OtherType min(const OtherType& o, const UniformField<Type>& u)
|
||||
{
|
||||
return min(o, u.operator Type());
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
inline UniformField<Type> max
|
||||
(
|
||||
const UniformField<Type>& u1,
|
||||
const UniformField<Type>& u2
|
||||
)
|
||||
{
|
||||
return UniformField<Type>(max(u1.operator Type(), u2.operator Type()));
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class OtherType>
|
||||
inline OtherType max(const UniformField<Type>& u, const OtherType& o)
|
||||
{
|
||||
return max(u.operator Type(), o);
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class OtherType>
|
||||
inline OtherType max(const OtherType& o, const UniformField<Type>& u)
|
||||
{
|
||||
return max(o, u.operator Type());
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -698,6 +698,161 @@ Foam::GeometricField<Type, PatchField, GeoMesh>::clone() const
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
Foam::tmp<Foam::GeometricField<Type, PatchField, GeoMesh>>
|
||||
Foam::GeometricField<Type, PatchField, GeoMesh>::New
|
||||
(
|
||||
const word& name,
|
||||
const Mesh& mesh,
|
||||
const dimensionSet& ds,
|
||||
const word& patchFieldType
|
||||
)
|
||||
{
|
||||
return tmp<GeometricField<Type, PatchField, GeoMesh>>
|
||||
(
|
||||
new GeometricField<Type, PatchField, GeoMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
name,
|
||||
mesh.thisDb().time().timeName(),
|
||||
mesh.thisDb(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
mesh,
|
||||
ds,
|
||||
patchFieldType
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
Foam::tmp<Foam::GeometricField<Type, PatchField, GeoMesh>>
|
||||
Foam::GeometricField<Type, PatchField, GeoMesh>::New
|
||||
(
|
||||
const word& name,
|
||||
const Mesh& mesh,
|
||||
const dimensioned<Type>& dt,
|
||||
const word& patchFieldType
|
||||
)
|
||||
{
|
||||
return tmp<GeometricField<Type, PatchField, GeoMesh>>
|
||||
(
|
||||
new GeometricField<Type, PatchField, GeoMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
name,
|
||||
mesh.thisDb().time().timeName(),
|
||||
mesh.thisDb(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
mesh,
|
||||
dt,
|
||||
patchFieldType
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
Foam::tmp<Foam::GeometricField<Type, PatchField, GeoMesh>>
|
||||
Foam::GeometricField<Type, PatchField, GeoMesh>::New
|
||||
(
|
||||
const word& name,
|
||||
const Mesh& mesh,
|
||||
const dimensioned<Type>& dt,
|
||||
const wordList& patchFieldTypes,
|
||||
const wordList& actualPatchTypes
|
||||
)
|
||||
{
|
||||
return tmp<GeometricField<Type, PatchField, GeoMesh>>
|
||||
(
|
||||
new GeometricField<Type, PatchField, GeoMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
name,
|
||||
mesh.thisDb().time().timeName(),
|
||||
mesh.thisDb(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
mesh,
|
||||
dt,
|
||||
patchFieldTypes,
|
||||
actualPatchTypes
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
Foam::tmp<Foam::GeometricField<Type, PatchField, GeoMesh>>
|
||||
Foam::GeometricField<Type, PatchField, GeoMesh>::New
|
||||
(
|
||||
const word& newName,
|
||||
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf
|
||||
)
|
||||
{
|
||||
return tmp<GeometricField<Type, PatchField, GeoMesh>>
|
||||
(
|
||||
new GeometricField<Type, PatchField, GeoMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
newName,
|
||||
tgf().instance(),
|
||||
tgf().local(),
|
||||
tgf().db(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
tgf
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
Foam::tmp<Foam::GeometricField<Type, PatchField, GeoMesh>>
|
||||
Foam::GeometricField<Type, PatchField, GeoMesh>::New
|
||||
(
|
||||
const word& newName,
|
||||
const tmp<GeometricField<Type, PatchField, GeoMesh>>& tgf,
|
||||
const wordList& patchFieldTypes,
|
||||
const wordList& actualPatchTypes
|
||||
)
|
||||
{
|
||||
return tmp<GeometricField<Type, PatchField, GeoMesh>>
|
||||
(
|
||||
new GeometricField<Type, PatchField, GeoMesh>
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
newName,
|
||||
tgf().instance(),
|
||||
tgf().local(),
|
||||
tgf().db(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
false
|
||||
),
|
||||
tgf,
|
||||
patchFieldTypes,
|
||||
actualPatchTypes
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
|
||||
@ -461,6 +461,53 @@ public:
|
||||
//- Clone
|
||||
tmp<GeometricField<Type, PatchField, GeoMesh>> clone() const;
|
||||
|
||||
//- Return a temporary field constructed from name, mesh, dimensionSet
|
||||
// and patch type.
|
||||
static tmp<GeometricField<Type, PatchField, GeoMesh>> New
|
||||
(
|
||||
const word& name,
|
||||
const Mesh&,
|
||||
const dimensionSet&,
|
||||
const word& patchFieldType=PatchField<Type>::calculatedType()
|
||||
);
|
||||
|
||||
//- Return a temporary field constructed from mesh, dimensioned<Type>
|
||||
// and patch type.
|
||||
static tmp<GeometricField<Type, PatchField, GeoMesh>> New
|
||||
(
|
||||
const word& name,
|
||||
const Mesh&,
|
||||
const dimensioned<Type>&,
|
||||
const word& patchFieldType=PatchField<Type>::calculatedType()
|
||||
);
|
||||
|
||||
//- Return a temporary field constructed from mesh, dimensioned<Type>
|
||||
// and patch types.
|
||||
static tmp<GeometricField<Type, PatchField, GeoMesh>> New
|
||||
(
|
||||
const word& name,
|
||||
const Mesh&,
|
||||
const dimensioned<Type>&,
|
||||
const wordList& patchFieldTypes,
|
||||
const wordList& actualPatchTypes = wordList()
|
||||
);
|
||||
|
||||
//- Rename temporary field and return
|
||||
static tmp<GeometricField<Type, PatchField, GeoMesh>> New
|
||||
(
|
||||
const word& newName,
|
||||
const tmp<GeometricField<Type, PatchField, GeoMesh>>&
|
||||
);
|
||||
|
||||
//- Rename and reset patch fields types of temporary field and return
|
||||
static tmp<GeometricField<Type, PatchField, GeoMesh>> New
|
||||
(
|
||||
const word& newName,
|
||||
const tmp<GeometricField<Type, PatchField, GeoMesh>>&,
|
||||
const wordList& patchFieldTypes,
|
||||
const wordList& actualPatchTypes = wordList()
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~GeometricField();
|
||||
|
||||
456
src/OpenFOAM/primitives/Scalar/scalar/incGamma.C
Normal file
456
src/OpenFOAM/primitives/Scalar/scalar/incGamma.C
Normal file
@ -0,0 +1,456 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration | Website: https://openfoam.org
|
||||
\\ / A nd | Copyright (C) 2019 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Global
|
||||
Foam::incGamma
|
||||
|
||||
Description
|
||||
Calculates the upper and lower incomplete gamma functions as well as their
|
||||
normalized versions.
|
||||
|
||||
The algorithm is described in detail in DiDonato et al. (1986).
|
||||
|
||||
\verbatim
|
||||
DiDonato, A. R., & Morris Jr, A. H. (1986).
|
||||
Computation of the incomplete gamma function ratios and their inverse.
|
||||
ACM Transactions on Mathematical Software (TOMS), 12(4), 377-393.
|
||||
\endverbatim
|
||||
|
||||
All equation numbers in the following code refer to the above paper.
|
||||
The algorithm in function 'incGammaRatio_Q' is described in section 3.
|
||||
The accuracy parameter IND is set to a value of 1.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "mathematicalConstants.H"
|
||||
|
||||
using namespace Foam::constant::mathematical;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Eqn. (13)
|
||||
static scalar calcQE11(const scalar a, const scalar x, const int e = 30)
|
||||
{
|
||||
scalar a_2n = 0;
|
||||
scalar b_2n = 1;
|
||||
|
||||
scalar a_2np1 = 1;
|
||||
scalar b_2np1 = x;
|
||||
|
||||
int n = 1;
|
||||
for (n = 1; (2*n) <= e; n++)
|
||||
{
|
||||
const scalar a_2nm1 = a_2np1;
|
||||
const scalar b_2nm1 = b_2np1;
|
||||
|
||||
a_2n = a_2nm1 + (n - a)*a_2n;
|
||||
b_2n = b_2nm1 + (n - a)*b_2n;
|
||||
|
||||
a_2np1 = x*a_2n + n*a_2nm1;
|
||||
b_2np1 = x*b_2n + n*b_2nm1;
|
||||
}
|
||||
|
||||
if (2*(n - 1) < e)
|
||||
{
|
||||
return a_2np1/b_2np1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return a_2n/b_2n;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Eqn. (15)
|
||||
static scalar calcPE15(const scalar a, const scalar x, const int nmax = 20)
|
||||
{
|
||||
scalar prod = 1;
|
||||
scalar sum = 0;
|
||||
|
||||
for (int n = 1; n <= nmax; n++)
|
||||
{
|
||||
prod *= (a + n);
|
||||
sum += pow(x, n)/prod;
|
||||
}
|
||||
|
||||
const scalar R = (exp(-x)*pow(x, a))/tgamma(a);
|
||||
|
||||
return R/a*(1 + sum);
|
||||
}
|
||||
|
||||
|
||||
// Eq. (16)
|
||||
static scalar calcQE16(const scalar a, const scalar x, const int N = 20)
|
||||
{
|
||||
scalar an = 1;
|
||||
scalar sum = 0;
|
||||
|
||||
for (int n = 1; n <= (N - 1); n++)
|
||||
{
|
||||
an *= (a - n);
|
||||
sum += an/pow(x, n);
|
||||
}
|
||||
|
||||
const scalar R = (exp(-x)*pow(x, a))/tgamma(a);
|
||||
|
||||
return R/x*(1 + sum);
|
||||
}
|
||||
|
||||
|
||||
// Eq. (18)
|
||||
static scalar calcTE18
|
||||
(
|
||||
const scalar a,
|
||||
const scalar e0,
|
||||
const scalar x,
|
||||
const scalar lambda,
|
||||
const scalar sigma,
|
||||
const scalar phi
|
||||
)
|
||||
{
|
||||
static const scalar D0[] =
|
||||
{
|
||||
-0.333333333333333E-00,
|
||||
0.833333333333333E-01,
|
||||
-0.148148148148148E-01,
|
||||
0.115740740740741E-02,
|
||||
0.352733686067019E-03,
|
||||
-0.178755144032922E-03,
|
||||
0.391926317852244E-04,
|
||||
-0.218544851067999E-05,
|
||||
-0.185406221071516E-05,
|
||||
0.829671134095309E-06,
|
||||
-0.176659527368261E-06,
|
||||
0.670785354340150E-08,
|
||||
0.102618097842403E-07,
|
||||
-0.438203601845335E-08
|
||||
};
|
||||
|
||||
static const scalar D1[] =
|
||||
{
|
||||
-0.185185185185185E-02,
|
||||
-0.347222222222222E-02,
|
||||
0.264550264550265E-02,
|
||||
-0.990226337448560E-03,
|
||||
0.205761316872428E-03,
|
||||
-0.401877572016461E-06,
|
||||
-0.180985503344900E-04,
|
||||
0.764916091608111E-05,
|
||||
-0.161209008945634E-05,
|
||||
0.464712780280743E-08,
|
||||
0.137863344691572E-06,
|
||||
-0.575254560351770E-07,
|
||||
0.119516285997781E-07
|
||||
};
|
||||
|
||||
static const scalar D2[] =
|
||||
{
|
||||
0.413359788359788E-02,
|
||||
-0.268132716049383E-02,
|
||||
0.771604938271605E-03,
|
||||
0.200938786008230E-05,
|
||||
-0.107366532263652E-03,
|
||||
0.529234488291201E-04,
|
||||
-0.127606351886187E-04,
|
||||
0.342357873409614E-07,
|
||||
0.137219573090629E-05,
|
||||
-0.629899213838006E-06,
|
||||
0.142806142060642E-06
|
||||
};
|
||||
|
||||
const scalar u = 1/a;
|
||||
scalar z = sqrt(2*phi);
|
||||
|
||||
if (lambda < 1)
|
||||
{
|
||||
z = -z;
|
||||
}
|
||||
|
||||
if (sigma > (e0/sqrt(a)))
|
||||
{
|
||||
const scalar C0 =
|
||||
D0[6]*pow6(z) + D0[5]*pow5(z) + D0[4]*pow4(z)
|
||||
+ D0[3]*pow3(z) + D0[2]*sqr(z) + D0[1]*z + D0[0];
|
||||
|
||||
const scalar C1 =
|
||||
D1[4]*pow4(z) + D1[3]*pow3(z) + D1[2]*sqr(z) + D1[1]*z + D1[0];
|
||||
|
||||
const scalar C2 = D2[1]*z + D2[0];
|
||||
|
||||
return C2*sqr(u) + C1*u + C0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const scalar C0 = D0[2]*sqr(z) + D0[1]*z + D0[0];
|
||||
const scalar C1 = D1[1]*z + D1[0];
|
||||
const scalar C2 = D2[1]*z + D2[0];
|
||||
|
||||
return C2*sqr(u) + C1*u + C0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::scalar Foam::incGammaRatio_Q(const scalar a, const scalar x)
|
||||
{
|
||||
const scalar BIG = 14;
|
||||
const scalar x0 = 17;
|
||||
const scalar e0 = 0.025;
|
||||
|
||||
if (a < 1)
|
||||
{
|
||||
if (a == 0.5)
|
||||
{
|
||||
// Eqn. (8)
|
||||
if (x < 0.25)
|
||||
{
|
||||
return 1 - erf(sqrt(x));
|
||||
}
|
||||
else
|
||||
{
|
||||
return erfc(sqrt(x));
|
||||
}
|
||||
}
|
||||
else if ( x < 1.1)
|
||||
{
|
||||
// Eqn. (12)
|
||||
scalar alpha = x/2.59;
|
||||
|
||||
if (x < 0.5)
|
||||
{
|
||||
alpha = log(sqrt(0.765))/log(x);
|
||||
}
|
||||
|
||||
scalar sum = 0;
|
||||
|
||||
for (int n = 1; n <= 10; n++)
|
||||
{
|
||||
sum += pow((-x), n)/((a + n)*factorial(n));
|
||||
}
|
||||
|
||||
const scalar J = -a*sum;
|
||||
|
||||
if (a > alpha || a == alpha)
|
||||
{
|
||||
// Eqn. (9)
|
||||
return 1 - (pow(x, a)*(1 - J))/tgamma(a + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Eqn. (10)
|
||||
const scalar L = exp(a*log(x)) - 1;
|
||||
const scalar H = 1/(tgamma(a + 1)) - 1;
|
||||
|
||||
return (pow(x, a)*J - L)/tgamma(a + 1) - H;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Eqn. (11)
|
||||
const scalar R = (exp(-x)*pow(x, a))/tgamma(a);
|
||||
|
||||
return R*calcQE11(a, x);
|
||||
}
|
||||
}
|
||||
else if (a >= BIG)
|
||||
{
|
||||
const scalar sigma = fabs(1 - x/a);
|
||||
|
||||
if (sigma <= e0/sqrt(a))
|
||||
{
|
||||
// Eqn. (19)
|
||||
const scalar lambda = x/a;
|
||||
const scalar phi = lambda - 1 - log(lambda);
|
||||
const scalar y = a*phi;
|
||||
|
||||
const scalar E = 0.5 - (1 - y/3)*sqrt(y/pi);
|
||||
|
||||
if (lambda <= 1)
|
||||
{
|
||||
return
|
||||
1
|
||||
- (
|
||||
E
|
||||
- (1 - y)/sqrt(2*pi*a)
|
||||
*calcTE18(a, e0, x, lambda, sigma, phi)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return
|
||||
E
|
||||
+ (1 - y)/sqrt(2*pi*a)
|
||||
*calcTE18(a, e0, x, lambda, sigma, phi);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sigma <= 0.4)
|
||||
{
|
||||
// Eqn. (17)
|
||||
const scalar lambda = x/a;
|
||||
const scalar phi = lambda - 1 - log(lambda);
|
||||
const scalar y = a*phi;
|
||||
|
||||
if (lambda <= 1)
|
||||
{
|
||||
return
|
||||
1
|
||||
- (0.5*erfc(sqrt(y))
|
||||
- exp(-y)/sqrt(2*pi*a)
|
||||
*calcTE18(a, e0, x, lambda, sigma, phi));
|
||||
}
|
||||
else
|
||||
{
|
||||
return
|
||||
0.5*erfc(sqrt(y))
|
||||
+ exp(-y)/sqrt(2*pi*a)
|
||||
*calcTE18(a, e0, x, lambda, sigma, phi);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x <= max(a, log(10.0)))
|
||||
{
|
||||
// Eqn. (15)
|
||||
return 1 - calcPE15(a, x);
|
||||
}
|
||||
else if (x < x0)
|
||||
{
|
||||
// Eqn. (11)
|
||||
const scalar R = (exp(-x)*pow(x, a))/tgamma(a);
|
||||
|
||||
return R*calcQE11(a, x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Eqn. (16)
|
||||
return calcQE16(a, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a > x || x >= x0)
|
||||
{
|
||||
if (x <= max(a, log(10.0)))
|
||||
{
|
||||
// Eqn. (15)
|
||||
return 1 - calcPE15(a, x);
|
||||
}
|
||||
else if ( x < x0)
|
||||
{
|
||||
// Eqn. (11)
|
||||
const scalar R = (exp(-x)*pow(x, a))/tgamma(a);
|
||||
|
||||
return R*calcQE11(a, x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Eqn. (16)
|
||||
return calcQE16(a, x);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (floor(2*a) == 2*a)
|
||||
{
|
||||
// Eqn. (14)
|
||||
if (floor(a) == a)
|
||||
{
|
||||
scalar sum = 0;
|
||||
|
||||
for (int n = 0; n <= (a - 1); n++)
|
||||
{
|
||||
sum += pow(x, n)/factorial(n);
|
||||
}
|
||||
|
||||
return exp(-x)*sum;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = a - 0.5;
|
||||
scalar prod = 1;
|
||||
scalar sum = 0;
|
||||
|
||||
for (int n = 1; n <= i; n++)
|
||||
{
|
||||
prod *= (n - 0.5);
|
||||
sum += pow(x, n)/prod;
|
||||
}
|
||||
|
||||
return erfc(sqrt(x)) + exp(-x)/sqrt(pi*x)*sum;
|
||||
}
|
||||
}
|
||||
else if (x <= max(a, log(10.0)))
|
||||
{
|
||||
// Eqn. (15)
|
||||
return 1 - calcPE15(a, x);
|
||||
}
|
||||
else if ( x < x0)
|
||||
{
|
||||
// Eqn. (11)
|
||||
const scalar R = (exp(-x)*pow(x, a))/tgamma(a);
|
||||
|
||||
return R*calcQE11(a, x);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Eqn. (16)
|
||||
return calcQE16(a, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::scalar Foam::incGammaRatio_P(const scalar a, const scalar x)
|
||||
{
|
||||
return 1 - incGammaRatio_Q(a, x);
|
||||
}
|
||||
|
||||
|
||||
Foam::scalar Foam::incGamma_Q(const scalar a, const scalar x)
|
||||
{
|
||||
return incGammaRatio_Q(a, x)*tgamma(a);
|
||||
}
|
||||
|
||||
|
||||
Foam::scalar Foam::incGamma_P(const scalar a, const scalar x)
|
||||
{
|
||||
return incGammaRatio_P(a, x)*tgamma(a);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -136,6 +136,18 @@ namespace Foam
|
||||
{
|
||||
//- Inverse normalized incomplete gamma function
|
||||
scalar invIncGamma(const scalar a, const scalar P);
|
||||
|
||||
//- Normalized upper incomplete gamma function
|
||||
scalar incGammaRatio_Q(const scalar a, const scalar x);
|
||||
|
||||
//- Normalized lower incomplete gamma function
|
||||
scalar incGammaRatio_P(const scalar a, const scalar x);
|
||||
|
||||
//- Upper incomplete gamma function
|
||||
scalar incGamma_Q(const scalar a, const scalar x);
|
||||
|
||||
//- Lower incomplete gamma function
|
||||
scalar incGamma_P(const scalar a, const scalar x);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -42,6 +42,25 @@ public:
|
||||
typedef arg2 type;
|
||||
};
|
||||
|
||||
inline scalar operator+(const scalar& t, const one&) noexcept
|
||||
{
|
||||
return t + 1;
|
||||
}
|
||||
|
||||
inline scalar operator+(const one&, const scalar& t) noexcept
|
||||
{
|
||||
return 1 + t;
|
||||
}
|
||||
|
||||
inline scalar operator-(const scalar& t, const one&) noexcept
|
||||
{
|
||||
return t - 1;
|
||||
}
|
||||
|
||||
inline scalar operator-(const one&, const scalar& t) noexcept
|
||||
{
|
||||
return 1 - t;
|
||||
}
|
||||
|
||||
inline constexpr const one& operator*(const one& o, const one&) noexcept
|
||||
{
|
||||
@ -83,6 +102,39 @@ inline constexpr const Type& operator/(const Type& val, const one&) noexcept
|
||||
return val;
|
||||
}
|
||||
|
||||
inline constexpr const one& min(const one& o, const one&) noexcept
|
||||
{
|
||||
return o;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
inline Type min(const one&, const Type& t) noexcept
|
||||
{
|
||||
return min(scalar(1), t);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
inline Type min(const Type& t, const one&) noexcept
|
||||
{
|
||||
return min(t, scalar(1));
|
||||
}
|
||||
|
||||
inline constexpr const one& max(const one& o, const one&) noexcept
|
||||
{
|
||||
return o;
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
inline Type max(const one&, const Type& t) noexcept
|
||||
{
|
||||
return max(scalar(1), t);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
inline Type max(const Type& t, const one&) noexcept
|
||||
{
|
||||
return max(t, scalar(1));
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user