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:
Sergio Ferraris
2019-06-07 09:38:35 +01:00
committed by Andrew Heather
parent 0628bfb017
commit 8170f2ad92
914 changed files with 68142 additions and 8336 deletions

View File

@ -0,0 +1,5 @@
derivedFvPatchFields/turbulentTemperatureTwoPhaseRadCoupledMixed/turbulentTemperatureTwoPhaseRadCoupledMixedFvPatchScalarField.C
../solid/solidRegionDiffNo.C
chtMultiRegionTwoPhaseEulerFoam.C
EXE = $(FOAM_APPBIN)/chtMultiRegionTwoPhaseEulerFoam

View File

@ -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 \

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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;

View File

@ -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]
)
);
}

View File

@ -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());
}

View File

@ -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)
);

View File

@ -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];

View File

@ -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");
}

View File

@ -0,0 +1,2 @@
p_rghFluid[i].storePrevIter();
//rhoFluid[i].storePrevIter();

View File

@ -137,7 +137,8 @@
alphaPhi10, alphaPhi10,
talphaPhi1Corr0.ref(), talphaPhi1Corr0.ref(),
zeroField(), zeroField(), zeroField(), zeroField(),
1, 0 oneField(),
zeroField()
); );
alphaPhi10 += talphaPhi1Corr0(); alphaPhi10 += talphaPhi1Corr0();
@ -187,8 +188,8 @@
talphaPhi1Corr.ref(), talphaPhi1Corr.ref(),
Sp, Sp,
(-Sp*alpha1)(), (-Sp*alpha1)(),
1, oneField(),
0 zeroField()
); );
// Under-relax the correction for all but the 1st corrector // Under-relax the correction for all but the 1st corrector
@ -214,8 +215,8 @@
alphaPhi10, alphaPhi10,
Sp, Sp,
(Su + divU*min(alpha1(), scalar(1)))(), (Su + divU*min(alpha1(), scalar(1)))(),
1, oneField(),
0 zeroField()
); );
} }

View File

@ -133,7 +133,15 @@
if (alphaApplyPrevCorr && talphaPhi1Corr0.valid()) if (alphaApplyPrevCorr && talphaPhi1Corr0.valid())
{ {
Info<< "Applying the previous iteration compression flux" << endl; 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(); alphaPhi10 += talphaPhi1Corr0();
} }
@ -182,8 +190,8 @@
talphaPhi1Corr.ref(), talphaPhi1Corr.ref(),
Sp, Sp,
(-Sp*alpha1)(), (-Sp*alpha1)(),
1, oneField(),
0 zeroField()
); );
// Under-relax the correction for all but the 1st corrector // Under-relax the correction for all but the 1st corrector
@ -209,8 +217,8 @@
alphaPhi10, alphaPhi10,
Sp, Sp,
(Su + divU*min(alpha1(), scalar(1)))(), (Su + divU*min(alpha1(), scalar(1)))(),
1, oneField(),
0 zeroField()
); );
} }

View File

@ -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 Foam::tmp<Foam::volScalarField> Foam::twoPhaseMixtureThermo::kappaEff
( (
const volScalarField& alphat const volScalarField& alphat

View File

@ -268,6 +268,13 @@ public:
const label patchi const label patchi
) const; ) 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] //- Effective thermal diffusivity of mixture [J/m/s/K]
virtual tmp<volScalarField> kappaEff virtual tmp<volScalarField> kappaEff
( (

View File

@ -45,6 +45,9 @@ namespace Foam
defineTypeNameAndDebug(multiphaseMixtureThermo, 0); defineTypeNameAndDebug(multiphaseMixtureThermo, 0);
} }
const Foam::scalar Foam::multiphaseMixtureThermo::convertToRad =
Foam::constant::mathematical::pi/180.0;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * 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 Foam::tmp<Foam::volScalarField> Foam::multiphaseMixtureThermo::kappaEff
( (
const volScalarField& alphat const volScalarField& alphat
@ -1042,8 +1084,8 @@ void Foam::multiphaseMixtureThermo::solveAlphas
alphaPhiCorr, alphaPhiCorr,
zeroField(), zeroField(),
zeroField(), zeroField(),
1, oneField(),
0, zeroField(),
true true
); );

View File

@ -138,6 +138,10 @@ private:
//- Stabilisation for normalisation of the interface normal //- Stabilisation for normalisation of the interface normal
const dimensionedScalar deltaN_; const dimensionedScalar deltaN_;
//- Conversion factor for degrees into radians
static const scalar convertToRad;
// Private member functions // Private member functions
@ -388,6 +392,13 @@ public:
const label patchi const label patchi
) const; ) 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] //- Effective thermal diffusivity of mixture [J/m/s/K]
virtual tmp<volScalarField> kappaEff virtual tmp<volScalarField> kappaEff
( (

View File

@ -32,11 +32,12 @@
MULES::correct MULES::correct
( (
geometricOneField(),
alpha1, alpha1,
alphaPhi, alphaPhi,
talphaPhiCorr0.ref(), talphaPhiCorr0.ref(),
mixture.alphaMax(), UniformField<scalar>(mixture.alphaMax()),
0 zeroField()
); );
alphaPhi += talphaPhiCorr0(); alphaPhi += talphaPhiCorr0();
@ -71,11 +72,12 @@
MULES::correct MULES::correct
( (
geometricOneField(),
alpha1, alpha1,
talphaPhiUn(), talphaPhiUn(),
talphaPhiCorr.ref(), talphaPhiCorr.ref(),
mixture.alphaMax(), UniformField<scalar>(mixture.alphaMax()),
0 zeroField()
); );
// Under-relax the correction for all but the 1st corrector // Under-relax the correction for all but the 1st corrector
@ -95,11 +97,12 @@
MULES::explicitSolve MULES::explicitSolve
( (
geometricOneField(),
alpha1, alpha1,
phi, phi,
alphaPhi, alphaPhi,
mixture.alphaMax(), UniformField<scalar>(mixture.alphaMax()),
0 zeroField()
); );
} }
} }

View File

@ -72,7 +72,7 @@ MultiComponentPhaseModel
species_ = thermoPtr_->composition().species(); species_ = thermoPtr_->composition().species();
inertIndex_ = species_[thermoPtr_->getWord("inertSpecie")]; inertIndex_ = species_[thermoPtr_().template get<word>("inertSpecie")];
X_.setSize(thermoPtr_->composition().species().size()); X_.setSize(thermoPtr_->composition().species().size());
@ -104,6 +104,7 @@ MultiComponentPhaseModel
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class BasePhaseModel, class phaseThermo> template<class BasePhaseModel, class phaseThermo>
void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo> void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>
::calculateVolumeFractions() ::calculateVolumeFractions()
@ -190,7 +191,7 @@ void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>::solveYi
const dictionary& MULEScontrols = mesh.solverDict(alpha1.name()); const dictionary& MULEScontrols = mesh.solverDict(alpha1.name());
scalar cAlpha(MULEScontrols.get<scalar>("cYi")); scalar cAlpha(readScalar(MULEScontrols.lookup("cYi")));
PtrList<surfaceScalarField> phiYiCorrs(species_.size()); PtrList<surfaceScalarField> phiYiCorrs(species_.size());
const surfaceScalarField& phi = this->fluid().phi(); const surfaceScalarField& phi = this->fluid().phi();
@ -201,7 +202,7 @@ void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>::solveYi
surfaceScalarField phir(0.0*phi); surfaceScalarField phir(0.0*phi);
forAllConstIters(this->fluid().phases(),iter2) forAllConstIter(phaseSystem::phaseModelTable,this->fluid().phases(),iter2)
{ {
const volScalarField& alpha2 = iter2()(); const volScalarField& alpha2 = iter2()();
if (&alpha2 == &alpha1) if (&alpha2 == &alpha1)
@ -250,7 +251,10 @@ void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>::solveYi
surfaceScalarField& phiYiCorr = phiYiCorrs[i]; 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()().oldTime();
const volScalarField& alpha2 = iter2()(); const volScalarField& alpha2 = iter2()();
@ -298,8 +302,8 @@ void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>::solveYi
phiYiCorr, phiYiCorr,
Sp[i], Sp[i],
Su[i], Su[i],
1, oneField(),
0, zeroField(),
true true
); );
} }
@ -354,8 +358,8 @@ void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>::solveYi
phiYiCorr, phiYiCorr,
Sp[i], Sp[i],
Su[i], Su[i],
1, oneField(),
0 zeroField()
); );
} }
} }
@ -369,8 +373,8 @@ void Foam::MultiComponentPhaseModel<BasePhaseModel, phaseThermo>::solveYi
phiYiCorr, phiYiCorr,
Sp[i], Sp[i],
Su[i], Su[i],
1, oneField(),
0 zeroField()
); );
} }
Yt += Yi; Yt += Yi;

View File

@ -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 Foam::tmp<Foam::volScalarField>Foam::phaseModel::kappaEff
( (
const volScalarField& kappat const volScalarField& kappat

View File

@ -226,6 +226,12 @@ public:
//- Thermal diffusivity for temperature of phase for patch [J/m/s/K] //- Thermal diffusivity for temperature of phase for patch [J/m/s/K]
tmp<scalarField> kappa(const label patchi) const; 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] //- Effective thermal diffusivity for temperature of phase [J/m/s/K]
tmp<volScalarField> kappaEff(const volScalarField&) const; tmp<volScalarField> kappaEff(const volScalarField&) const;

View File

@ -414,8 +414,8 @@ void Foam::multiphaseSystem::solve()
phiAlphaCorr, phiAlphaCorr,
Sp, Sp,
Su, Su,
1, oneField(),
0, zeroField(),
true true
); );
++phasei; ++phasei;
@ -485,8 +485,8 @@ void Foam::multiphaseSystem::solve()
phiAlpha, phiAlpha,
(alphaSubCycle.index()*Sp)(), (alphaSubCycle.index()*Sp)(),
(Su - (alphaSubCycle.index() - 1)*Sp*alpha1)(), (Su - (alphaSubCycle.index() - 1)*Sp*alpha1)(),
1, oneField(),
0 zeroField()
); );
if (alphaSubCycle.index() == 1) if (alphaSubCycle.index() == 1)
@ -511,8 +511,8 @@ void Foam::multiphaseSystem::solve()
phiAlpha, phiAlpha,
Sp, Sp,
Su, Su,
1, oneField(),
0 zeroField()
); );
phase.alphaPhi() = phiAlpha; phase.alphaPhi() = phiAlpha;

View File

@ -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 Foam::tmp<Foam::volScalarField>Foam::phaseSystem::kappaEff
( (
const volScalarField& kappat const volScalarField& kappat

View File

@ -396,6 +396,12 @@ public:
const label patchi const label patchi
) const; ) 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 //- Effective thermal diffusivity for temperature
// of mixture [J/m/s/K] // of mixture [J/m/s/K]
virtual tmp<volScalarField> kappaEff virtual tmp<volScalarField> kappaEff

View File

@ -1,17 +1,11 @@
{ {
tmp<volScalarField> tcp(thermo->Cp()); tmp<volScalarField> tcp(thermo->Cp());
const volScalarField& cp = tcp(); const volScalarField& cp = tcp();
rhoCp = rho*cp; rhoCp = rho*cp;
kappaEff = thermo->kappa() + rho*cp*turbulence->nut()/Prt; 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); const surfaceScalarField rhoCpPhi(fvc::interpolate(cp)*rhoPhi);
Pair<tmp<volScalarField>> vDotAlphal = mixture->mDot(); Pair<tmp<volScalarField>> vDotAlphal = mixture->mDot();
@ -23,13 +17,13 @@
fvScalarMatrix TEqn fvScalarMatrix TEqn
( (
fvm::ddt(rhoCp, T) 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::Sp(fvc::ddt(rhoCp) + fvc::div(rhoCpPhi), T)
- fvm::laplacian(kappaEff, T) - fvm::laplacian(kappaEff, T)
+ thermo->hc()*vDotvmcAlphal + thermo->hc()*vDotvmcAlphal
+ pDivU
); );
TEqn.relax(); TEqn.relax();
TEqn.solve(); TEqn.solve();

View File

@ -57,8 +57,7 @@ volScalarField rho
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
alpha1*rho1 + alpha2*rho2, alpha1*rho1 + alpha2*rho2
alpha1.boundaryField().types()
); );
rho.oldTime(); rho.oldTime();
@ -123,19 +122,6 @@ volScalarField kappaEff
thermo->kappa() 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) // Need to store rho for ddt(rhoCp, U)
volScalarField rhoCp volScalarField rhoCp
( (
@ -149,4 +135,5 @@ volScalarField rhoCp
), ),
rho*thermo->Cp() rho*thermo->Cp()
); );
rhoCp.oldTime(); rhoCp.oldTime();

View File

@ -118,9 +118,8 @@ int main(int argc, char *argv[])
#include "alphaEqnSubCycle.H" #include "alphaEqnSubCycle.H"
solve(fvm::ddt(rho) + fvc::div(rhoPhi)); solve(fvm::ddt(rho) + fvc::div(rhoPhi));
#include "UEqn.H" #include "UEqn.H"
#include "eEqn.H" #include "TEqn.H"
// --- Pressure corrector loop // --- Pressure corrector loop
while (pimple.correct()) while (pimple.correct())

View File

@ -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 Foam::tmp<Foam::volScalarField> Foam::twoPhaseMixtureEThermo::kappaEff
( (
const volScalarField& kappat const volScalarField& kappat

View File

@ -246,6 +246,12 @@ public:
const label patchi const label patchi
) const; ) 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 //- Effective thermal diffusivity for temperature
//- of mixture [J/m/s/K] //- of mixture [J/m/s/K]
virtual tmp<volScalarField> kappaEff virtual tmp<volScalarField> kappaEff

View File

@ -87,8 +87,8 @@
alphaPhi1, alphaPhi1,
zeroField(), zeroField(),
zeroField(), zeroField(),
1, oneField(),
0 zeroField()
); );
} }
else else
@ -103,8 +103,8 @@
alphaPhi1, alphaPhi1,
zeroField(), zeroField(),
zeroField(), zeroField(),
1, oneField(),
0 zeroField()
); );
} }
@ -155,8 +155,8 @@
alphaPhi2, alphaPhi2,
zeroField(), zeroField(),
zeroField(), zeroField(),
1, oneField(),
0 zeroField()
); );
} }
else else
@ -171,8 +171,8 @@
alphaPhi2, alphaPhi2,
zeroField(), zeroField(),
zeroField(), zeroField(),
1, oneField(),
0 zeroField()
); );
} }

View File

@ -78,8 +78,8 @@
divU*(alpha10 - alpha100) divU*(alpha10 - alpha100)
- vDotvmcAlphal*alpha10 - vDotvmcAlphal*alpha10
)(), )(),
1, oneField(),
0 zeroField()
); );
// Under-relax the correction for all but the 1st corrector // Under-relax the correction for all but the 1st corrector
@ -103,8 +103,8 @@
talphaPhiCorr.ref(), talphaPhiCorr.ref(),
vDotvmcAlphal, vDotvmcAlphal,
(divU*alpha1 + vDotcAlphal)(), (divU*alpha1 + vDotcAlphal)(),
1, oneField(),
0 zeroField()
); );
talphaPhi = talphaPhiCorr; talphaPhi = talphaPhiCorr;

View File

@ -5,7 +5,7 @@
\\ / A nd | \\ / A nd |
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
| Copyright (C) 2011-2017 OpenFOAM Foundation | Copyright (C) 2011-2018 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -37,7 +37,12 @@ License
#include "fvcDiv.H" #include "fvcDiv.H"
#include "fvcFlux.H" #include "fvcFlux.H"
#include "fvcAverage.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 * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -124,8 +129,8 @@ void Foam::multiphaseSystem::solveAlphas()
alphaPhiCorr, alphaPhiCorr,
zeroField(), zeroField(),
zeroField(), zeroField(),
1, oneField(),
0, zeroField(),
true true
); );
@ -143,7 +148,7 @@ void Foam::multiphaseSystem::solveAlphas()
mesh_ mesh_
), ),
mesh_, mesh_,
dimensionedScalar(dimless, Zero) dimensionedScalar("sumAlpha", dimless, 0)
); );
phasei = 0; phasei = 0;
@ -158,9 +163,7 @@ void Foam::multiphaseSystem::solveAlphas()
( (
geometricOneField(), geometricOneField(),
phase, phase,
alphaPhi, alphaPhi
zeroField(),
zeroField()
); );
phase.alphaPhi() = alphaPhi; phase.alphaPhi() = alphaPhi;
@ -278,7 +281,7 @@ void Foam::multiphaseSystem::correctContactAngle
bool matched = (tp.key().first() == phase1.name()); 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); scalarField theta(boundary[patchi].size(), theta0);
scalar uTheta = tp().uTheta(); scalar uTheta = tp().uTheta();
@ -286,8 +289,8 @@ void Foam::multiphaseSystem::correctContactAngle
// Calculate the dynamic contact angle if required // Calculate the dynamic contact angle if required
if (uTheta > SMALL) if (uTheta > SMALL)
{ {
const scalar thetaA = degToRad(tp().thetaA(matched)); scalar thetaA = convertToRad*tp().thetaA(matched);
const scalar thetaR = degToRad(tp().thetaR(matched)); scalar thetaR = convertToRad*tp().thetaR(matched);
// Calculated the component of the velocity parallel to the wall // Calculated the component of the velocity parallel to the wall
vectorField Uwall vectorField Uwall
@ -391,7 +394,7 @@ Foam::multiphaseSystem::multiphaseSystem
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh_, mesh_,
dimensionedScalar(dimless, Zero) dimensionedScalar("alphas", dimless, 0.0)
), ),
sigmas_(lookup("sigmas")), sigmas_(lookup("sigmas")),
@ -411,7 +414,7 @@ Foam::multiphaseSystem::multiphaseSystem
forAllConstIters(dragModelsDict, iter) forAllConstIters(dragModelsDict, iter)
{ {
dragModels_.insert dragModels_.set
( (
iter.key(), iter.key(),
dragModel::New dragModel::New
@ -419,7 +422,7 @@ Foam::multiphaseSystem::multiphaseSystem
iter(), iter(),
*phases_.lookup(iter.key().first()), *phases_.lookup(iter.key().first()),
*phases_.lookup(iter.key().second()) *phases_.lookup(iter.key().second())
) ).ptr()
); );
} }
@ -583,7 +586,12 @@ Foam::tmp<Foam::volVectorField> Foam::multiphaseSystem::Svm
mesh_ mesh_
), ),
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::autoPtr<Foam::multiphaseSystem::dragCoeffFields>
Foam::multiphaseSystem::dragCoeffs() const Foam::multiphaseSystem::dragCoeffs() const
{ {
auto dragCoeffsPtr = autoPtr<dragCoeffFields>::New(); autoPtr<dragCoeffFields> dragCoeffsPtr(new dragCoeffFields);
forAllConstIters(dragModels_, iter) forAllConstIters(dragModels_, iter)
{ {
@ -646,8 +654,8 @@ Foam::multiphaseSystem::dragCoeffs() const
( (
max max
( (
//fvc::average(dm.phase1()*dm.phase2()), // fvc::average(dm.phase1()*dm.phase2()),
//fvc::average(dm.phase1())*fvc::average(dm.phase2()), // fvc::average(dm.phase1())*fvc::average(dm.phase2()),
dm.phase1()*dm.phase2(), dm.phase1()*dm.phase2(),
dm.residualPhaseFraction() dm.residualPhaseFraction()
) )
@ -702,7 +710,12 @@ Foam::tmp<Foam::volScalarField> Foam::multiphaseSystem::dragCoeff
mesh_ mesh_
), ),
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_
), ),
mesh_, mesh_,
dimensionedScalar(dimensionSet(1, -2, -2, 0, 0), Zero) dimensionedScalar
(
"surfaceTension",
dimensionSet(1, -2, -2, 0, 0),
0
)
) )
); );
tSurfaceTension.ref().setOriented(); tSurfaceTension.ref().setOriented();
@ -789,7 +807,7 @@ Foam::multiphaseSystem::nearInterface() const
mesh_ mesh_
), ),
mesh_, mesh_,
dimensionedScalar(dimless, Zero) dimensionedScalar("nearInterface", dimless, 0.0)
) )
); );
@ -813,7 +831,7 @@ void Foam::multiphaseSystem::solve()
const Time& runTime = mesh_.time(); const Time& runTime = mesh_.time();
const dictionary& alphaControls = mesh_.solverDict("alpha"); const dictionary& alphaControls = mesh_.solverDict("alpha");
label nAlphaSubCycles(alphaControls.get<label>("nAlphaSubCycles")); label nAlphaSubCycles(readLabel(alphaControls.lookup("nAlphaSubCycles")));
if (nAlphaSubCycles > 1) if (nAlphaSubCycles > 1)
{ {
@ -845,7 +863,7 @@ void Foam::multiphaseSystem::solve()
mesh_ mesh_
), ),
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()); readOK &= phase.read(phaseData[phasei++].dict());
} }
readEntry("sigmas", sigmas_); lookup("sigmas") >> sigmas_;
readEntry("interfaceCompression", cAlphas_); lookup("interfaceCompression") >> cAlphas_;
readEntry("virtualMass", Cvms_); lookup("virtualMass") >> Cvms_;
return readOK; return readOK;
} }
else
return false; {
return false;
}
} }

View File

@ -76,16 +76,30 @@ public:
{ {
public: public:
struct symmHash class symmHash
:
public Hash<interfacePair>
{ {
public:
symmHash()
{}
label operator()(const interfacePair& key) const label operator()(const interfacePair& key) const
{ {
return word::hash()(key.first()) + word::hash()(key.second()); return word::hash()(key.first()) + word::hash()(key.second());
} }
}; };
struct hash class hash
:
public Hash<interfacePair>
{ {
public:
hash()
{}
label operator()(const interfacePair& key) const label operator()(const interfacePair& key) const
{ {
return word::hash()(key.first(), word::hash()(key.second())); return word::hash()(key.first(), word::hash()(key.second()));
@ -95,7 +109,8 @@ public:
// Constructors // Constructors
interfacePair() {} // = default interfacePair()
{}
interfacePair(const word& alpha1Name, const word& alpha2Name) interfacePair(const word& alpha1Name, const word& alpha2Name)
: :
@ -174,6 +189,9 @@ private:
//- Stabilisation for normalisation of the interface normal //- Stabilisation for normalisation of the interface normal
const dimensionedScalar deltaN_; const dimensionedScalar deltaN_;
//- Conversion factor for degrees into radians
static const scalar convertToRad;
// Private member functions // Private member functions
@ -220,7 +238,8 @@ public:
//- Destructor //- Destructor
virtual ~multiphaseSystem() = default; virtual ~multiphaseSystem()
{}
// Member Functions // Member Functions

View File

@ -613,8 +613,8 @@ void Foam::multiphaseMixture::solveAlphas
alphaPhiCorr, alphaPhiCorr,
zeroField(), zeroField(),
zeroField(), zeroField(),
1, oneField(),
0, zeroField(),
true true
); );
@ -648,9 +648,7 @@ void Foam::multiphaseMixture::solveAlphas
( (
geometricOneField(), geometricOneField(),
alpha, alpha,
alphaPhi, alphaPhi
zeroField(),
zeroField()
); );
rhoPhi_ += alphaPhi*alpha.rho(); rhoPhi_ += alphaPhi*alpha.rho();

View File

@ -1,10 +1,8 @@
#!/bin/sh #!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory cd ${0%/*} || exit 1 # Run from this directory
wclean libso phaseSystems wclean reactingTwoPhaseEulerFoam
wclean libso interfacialModels wclean reactingMultiphaseEulerFoam
wclean libso interfacialCompositionModels wclean libso functionObjects
reactingTwoPhaseEulerFoam/Allwclean
reactingMultiphaseEulerFoam/Allwclean
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -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 $* reactingTwoPhaseEulerFoam/Allwmake $targetType $*
reactingMultiphaseEulerFoam/Allwmake $targetType $* reactingMultiphaseEulerFoam/Allwmake $targetType $*
wmake $targetType functionObjects
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -0,0 +1,4 @@
sizeDistribution/sizeDistribution.C
phaseForces/phaseForces.C
LIB = $(FOAM_LIBBIN)/libreactingEulerFoamFunctionObjects

View File

@ -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

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
);
}
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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));
}
// ************************************************************************* //

View File

@ -1,11 +1,9 @@
#!/bin/sh #!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory cd ${0%/*} || exit 1 # Run from this directory
# Parse arguments for library compilation
. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments . $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments
#------------------------------------------------------------------------------
wmake $targetType multiphaseSystem
wmake $targetType multiphaseCompressibleTurbulenceModels
wmake $targetType wmake $targetType
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -5,7 +5,7 @@
\\ / A nd | \\ / A nd |
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
| Copyright (C) 2011-2016 OpenFOAM Foundation | Copyright (C) 2011-2018 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.

View File

@ -7,32 +7,27 @@ for (int Ecorr=0; Ecorr<nEnergyCorrectors; Ecorr++)
phaseSystem::heatTransferTable& heatTransfer = heatTransferPtr(); 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& alpha = phase;
const volScalarField& rho = phase.rho(); const volScalarField& rho = phase.rho();
const volVectorField& U = phase.U(); const volVectorField& U = phase.U();
tmp<fvScalarMatrix> EEqn(phase.heEqn()); fvScalarMatrix EEqn
(
phase.heEqn()
==
*heatTransfer[phase.name()]
+ alpha*rho*(U&g)
+ fvOptions(alpha, rho, phase.thermoRef().he())
);
if (EEqn.valid()) EEqn.relax();
{ fvOptions.constrain(EEqn);
EEqn = EEqn.solve();
( fvOptions.correct(phase.thermoRef().he());
EEqn
==
*heatTransfer[phase.name()]
+ alpha*rho*(U&g)
+ fvOptions(alpha, rho, phase.thermo().he())
);
EEqn->relax();
fvOptions.constrain(EEqn.ref());
EEqn->solve();
fvOptions.correct(phase.thermo().he());
}
} }
fluid.correctThermo(); fluid.correctThermo();

View File

@ -1,15 +1,17 @@
EXE_INC = \ EXE_INC = \
-ImultiphaseSystem/lnInclude \
-I../phaseSystems/lnInclude \
-I../interfacialModels/lnInclude \
-I../interfacialCompositionModels/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/sampling/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)/thermophysicalModels/basic/lnInclude \
-I$(LIB_SRC)/transportModels/compressible/lnInclude \ -I$(LIB_SRC)/transportModels/compressible/lnInclude \
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \ -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
-I$(LIB_SRC)/TurbulenceModels/compressible/lnInclude \ -I$(LIB_SRC)/TurbulenceModels/compressible/lnInclude \
-I$(LIB_SRC)/TurbulenceModels/compressible/turbulentFluidThermoModels/turbulentFluidFvPatchFields/lnInclude \
-I$(LIB_SRC)/TurbulenceModels/phaseCompressible/lnInclude -I$(LIB_SRC)/TurbulenceModels/phaseCompressible/lnInclude
EXE_LIBS = \ EXE_LIBS = \

View File

@ -5,33 +5,26 @@
phaseSystem::massTransferTable& phaseSystem::massTransferTable&
massTransfer(massTransferPtr()); 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& alpha = phase;
const volScalarField& rho = phase.rho(); const volScalarField& rho = phase.rho();
forAll(Y, i) forAll(Y, i)
{ {
tmp<fvScalarMatrix> YiEqn(phase.YiEqn(Y[i])); fvScalarMatrix YiEqn
(
phase.YiEqn(Y[i])
==
*massTransfer[Y[i].name()]
+ fvOptions(alpha, rho, Y[i])
);
if (YiEqn.valid()) YiEqn.relax();
{ YiEqn.solve(mesh.solver("Yi"));
YiEqn =
(
YiEqn
==
*massTransfer[Y[i].name()]
+ fvOptions(alpha, rho, Y[i])
);
YiEqn->relax();
YiEqn->solve(mesh.solver("Yi"));
}
} }
} }
fluid.massTransfer(); // updates interfacial mass flow rates
} }

View File

@ -20,7 +20,7 @@ dimensionedScalar pMin
#include "gh.H" #include "gh.H"
volScalarField& p = phases[0].thermo().p(); volScalarField& p = phases[0].thermoRef().p();
Info<< "Reading field p_rgh\n" << endl; Info<< "Reading field p_rgh\n" << endl;
volScalarField p_rgh volScalarField p_rgh

View File

@ -9,17 +9,17 @@ PtrList<fvVectorMatrix> UEqns(phases.size());
phaseSystem::momentumTransferTable& phaseSystem::momentumTransferTable&
momentumTransfer(momentumTransferPtr()); momentumTransfer(momentumTransferPtr());
forAll(phases, phasei) forAll(fluid.movingPhases(), movingPhasei)
{ {
phaseModel& phase = phases[phasei]; phaseModel& phase = fluid.movingPhases()[movingPhasei];
const volScalarField& alpha = phase; const volScalarField& alpha = phase;
const volScalarField& rho = phase.rho(); const volScalarField& rho = phase.rho();
volVectorField& U = phase.U(); volVectorField& U = phase.URef();
UEqns.set UEqns.set
( (
phasei, phase.index(),
new fvVectorMatrix new fvVectorMatrix
( (
phase.UEqn() phase.UEqn()
@ -29,8 +29,8 @@ PtrList<fvVectorMatrix> UEqns(phases.size());
) )
); );
UEqns[phasei].relax(); UEqns[phase.index()].relax();
fvOptions.constrain(UEqns[phasei]); fvOptions.constrain(UEqns[phase.index()]);
fvOptions.correct(U); fvOptions.correct(U);
} }
} }

View File

@ -1,7 +1,5 @@
// Face volume fractions
PtrList<surfaceScalarField> alphafs(phases.size()); PtrList<surfaceScalarField> alphafs(phases.size());
PtrList<volScalarField> rAUs(phases.size());
PtrList<surfaceScalarField> alpharAUfs(phases.size());
forAll(phases, phasei) forAll(phases, phasei)
{ {
phaseModel& phase = phases[phasei]; phaseModel& phase = phases[phasei];
@ -9,21 +7,37 @@ forAll(phases, phasei)
alphafs.set(phasei, fvc::interpolate(alpha).ptr()); alphafs.set(phasei, fvc::interpolate(alpha).ptr());
alphafs[phasei].rename("pEqn" + alphafs[phasei].name()); 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 rAUs.set
( (
phasei, phase.index(),
new volScalarField new volScalarField
( (
IOobject::groupName("rAU", phase.name()), IOobject::groupName("rAU", phase.name()),
1.0 1.0
/( /(
UEqns[phasei].A() UEqns[phase.index()].A()
+ max(phase.residualAlpha() - alpha, scalar(0)) + byDt(max(phase.residualAlpha() - alpha, scalar(0))*phase.rho())
*phase.rho()/runTime.deltaT()
) )
) )
); );
}
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 alpharAUfs.set
( (
@ -34,57 +48,8 @@ forAll(phases, phasei)
); );
} }
// Lift, wall-lubrication and turbulent diffusion fluxes // Explicit force fluxes
PtrList<surfaceScalarField> phiFs(phases.size()); PtrList<surfaceScalarField> phiFs(fluid.phiFs(rAUs));
{
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]
)
);
}
}
}
}
// --- Pressure corrector loop // --- Pressure corrector loop
while (pimple.correct()) while (pimple.correct())
@ -94,67 +59,116 @@ while (pimple.correct())
// Correct p_rgh for consistency with p and the updated densities // Correct p_rgh for consistency with p and the updated densities
p_rgh = p - rho*gh; p_rgh = p - rho*gh;
PtrList<volVectorField> HbyAs(phases.size()); // Correct fixed-flux BCs to be consistent with the velocity BCs
forAll(fluid.movingPhases(), movingPhasei)
forAll(phases, phasei)
{ {
phaseModel& phase = phases[phasei]; phaseModel& phase = fluid.movingPhases()[movingPhasei];
const volScalarField& alpha = phase; MRF.correctBoundaryFlux(phase.U(), phase.phiRef());
// 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()
);
} }
surfaceScalarField ghSnGradRho // Combined buoyancy and force fluxes
(
"ghSnGradRho",
ghf*fvc::snGrad(rho)*mesh.magSf()
);
PtrList<surfaceScalarField> phigFs(phases.size()); PtrList<surfaceScalarField> phigFs(phases.size());
forAll(phases, phasei)
{ {
phaseModel& phase = phases[phasei]; const surfaceScalarField ghSnGradRho
phigFs.set
( (
phasei, "ghSnGradRho",
( ghf*fvc::snGrad(rho)*mesh.magSf()
alpharAUfs[phasei]
*(
ghSnGradRho
- (fvc::interpolate(phase.rho() - rho))*(g & mesh.Sf())
- fluid.surfaceTension(phase)*mesh.magSf()
)
).ptr()
); );
if (phiFs.set(phasei)) forAll(phases, phasei)
{ {
phigFs[phasei] += phiFs[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 (phiFs.set(phasei))
{
phigFs[phasei] += phiFs[phasei];
}
} }
} }
// Predicted velocities and fluxes for each phase
PtrList<volVectorField> HbyAs(phases.size());
PtrList<surfaceScalarField> phiHbyAs(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 surfaceScalarField phiHbyA
( (
IOobject IOobject
@ -166,84 +180,28 @@ while (pimple.correct())
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedScalar(dimArea*dimVelocity, Zero) dimensionedScalar("phiHbyA", dimArea*dimVelocity, 0)
); );
forAll(phases, phasei) 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]; 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); MRF.makeRelative(phiHbyA);
// Construct pressure "diffusivity" // Construct pressure "diffusivity"
@ -256,15 +214,15 @@ while (pimple.correct())
mesh mesh
), ),
mesh, mesh,
dimensionedScalar(dimensionSet(-1, 3, 1, 0, 0), Zero) dimensionedScalar("rAUf", dimensionSet(-1, 3, 1, 0, 0), 0)
); );
forAll(phases, phasei) forAll(phases, phasei)
{ {
rAUf += alphafs[phasei]*alpharAUfs[phasei]; rAUf += alphafs[phasei]*alpharAUfs[phasei];
} }
rAUf = mag(rAUf);
rAUf = mag(rAUf);
// Update the fixedFluxPressure BCs to ensure flux consistency // Update the fixedFluxPressure BCs to ensure flux consistency
{ {
@ -273,7 +231,8 @@ while (pimple.correct())
forAll(phases, phasei) forAll(phases, phasei)
{ {
phaseModel& phase = phases[phasei]; phaseModel& phase = phases[phasei];
phib += alphafs[phasei].boundaryField()*phase.phi().boundaryField(); phib +=
alphafs[phasei].boundaryField()*phase.phi()().boundaryField();
} }
setSnGrad<fixedFluxPressureFvPatchScalarField> setSnGrad<fixedFluxPressureFvPatchScalarField>
@ -285,12 +244,14 @@ while (pimple.correct())
); );
} }
// Compressible pressure equations
PtrList<fvScalarMatrix> pEqnComps(phases.size()); PtrList<fvScalarMatrix> pEqnComps(phases.size());
PtrList<volScalarField> dmdts(fluid.dmdts());
forAll(phases, phasei) forAll(phases, phasei)
{ {
phaseModel& phase = phases[phasei]; phaseModel& phase = phases[phasei];
const volScalarField& alpha = phase; const volScalarField& alpha = phase;
volScalarField& rho = phase.thermo().rho(); volScalarField& rho = phase.thermoRef().rho();
if (phase.compressible()) if (phase.compressible())
{ {
@ -307,7 +268,7 @@ while (pimple.correct())
phasei, phasei,
( (
( (
phase.continuityError() fvc::ddt(alpha, rho) + fvc::div(phase.alphaRhoPhi())
- fvc::Sp - fvc::Sp
( (
fvc::ddt(alpha) + fvc::div(phase.alphaPhi()), fvc::ddt(alpha) + fvc::div(phase.alphaPhi()),
@ -335,7 +296,7 @@ while (pimple.correct())
phasei, phasei,
( (
( (
phase.continuityError() fvc::ddt(alpha, rho) + fvc::div(phase.alphaRhoPhi())
- fvc::Sp - fvc::Sp
( (
(fvc::ddt(alpha) + fvc::div(phase.alphaPhi())), (fvc::ddt(alpha) + fvc::div(phase.alphaPhi())),
@ -348,27 +309,38 @@ while (pimple.correct())
); );
} }
} }
else
{
pEqnComps.set
(
phasei,
fvm::Su(-(fvOptions(alpha, rho)&rho)/rho, p_rgh).ptr()
);
}
if (fluid.transfersMass(phase)) // Add option sources
if (fvOptions.appliesToField(rho.name()))
{ {
tmp<fvScalarMatrix> optEqn = fvOptions(alpha, rho);
if (pEqnComps.set(phasei)) if (pEqnComps.set(phasei))
{ {
pEqnComps[phasei] -= fluid.dmdt(phase)/rho; pEqnComps[phasei] -= (optEqn&rho)/rho;
} }
else else
{ {
pEqnComps.set pEqnComps.set
( (
phasei, phasei,
fvm::Su(-fluid.dmdt(phase)/rho, p_rgh) fvm::Su(- (optEqn&rho)/rho, p_rgh).ptr()
);
}
}
// Add mass transfer
if (dmdts.set(phasei))
{
if (pEqnComps.set(phasei))
{
pEqnComps[phasei] -= dmdts[phasei]/rho;
}
else
{
pEqnComps.set
(
phasei,
fvm::Su(- dmdts[phasei]/rho, p_rgh)
); );
} }
} }
@ -412,16 +384,18 @@ while (pimple.correct())
surfaceScalarField mSfGradp("mSfGradp", pEqnIncomp.flux()/rAUf); 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 // 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; mSfGradp = pEqnIncomp.flux()/rAUf;
forAll(phases, phasei) forAll(fluid.movingPhases(), movingPhasei)
{ {
phaseModel& phase = phases[phasei]; phaseModel& phase = fluid.movingPhases()[movingPhasei];
phase.U() = phase.URef() =
HbyAs[phasei] HbyAs[phase.index()]
+ fvc::reconstruct + fvc::reconstruct
( (
alpharAUfs[phasei]*mSfGradp alpharAUfs[phase.index()]*mSfGradp
- phigFs[phasei] - 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) forAll(phases, phasei)
{ {
phaseModel& phase = 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 // Correct p_rgh for consistency with p and the updated densities

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -5,7 +5,7 @@
\\ / A nd | \\ / A nd |
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
| Copyright (C) 2011-2016 OpenFOAM Foundation | Copyright (C) 2011-2018 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -26,9 +26,6 @@ License
Application Application
reactingMultiphaseEulerFoam reactingMultiphaseEulerFoam
Group
grpMultiphaseSolvers
Description Description
Solver for a system of any number of compressible fluid phases with a Solver for a system of any number of compressible fluid phases with a
common pressure, but otherwise separate properties. The type of phase model common pressure, but otherwise separate properties. The type of phase model
@ -40,6 +37,7 @@ Description
#include "fvCFD.H" #include "fvCFD.H"
#include "multiphaseSystem.H" #include "multiphaseSystem.H"
#include "phaseCompressibleTurbulenceModel.H"
#include "pimpleControl.H" #include "pimpleControl.H"
#include "localEulerDdtScheme.H" #include "localEulerDdtScheme.H"
#include "fvcSmooth.H" #include "fvcSmooth.H"
@ -48,16 +46,10 @@ Description
int main(int argc, char *argv[]) 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 "postProcess.H"
#include "addCheckCaseOptions.H" #include "addCheckCaseOptions.H"
#include "setRootCaseLists.H" #include "setRootCase.H"
#include "createTime.H" #include "createTime.H"
#include "createMesh.H" #include "createMesh.H"
#include "createControl.H" #include "createControl.H"
@ -71,20 +63,14 @@ int main(int argc, char *argv[])
#include "setInitialDeltaT.H" #include "setInitialDeltaT.H"
} }
// bool faceMomentum Switch faceMomentum
// ( (
// pimple.dict().lookupOrDefault("faceMomentum", false) pimple.dict().lookupOrDefault<Switch>("faceMomentum", false)
// ); );
Switch partialElimination
// bool implicitPhasePressure (
// ( pimple.dict().lookupOrDefault<Switch>("partialElimination", false)
// mesh.solverDict(alpha1.name()).lookupOrDefault );
// (
// "implicitPhasePressure", false
// )
// );
//#include "pUf/createDDtU.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -109,7 +95,7 @@ int main(int argc, char *argv[])
#include "setDeltaT.H" #include "setDeltaT.H"
} }
++runTime; runTime++;
Info<< "Time = " << runTime.timeName() << nl << endl; Info<< "Time = " << runTime.timeName() << nl << endl;
// --- Pressure-velocity PIMPLE corrector loop // --- Pressure-velocity PIMPLE corrector loop
@ -120,14 +106,13 @@ int main(int argc, char *argv[])
#include "YEqns.H" #include "YEqns.H"
// if (faceMomentum) if (faceMomentum)
// { {
// #include "pUf/UEqns.H" #include "pUf/UEqns.H"
// #include "EEqns.H" #include "EEqns.H"
// #include "pUf/pEqn.H" #include "pUf/pEqn.H"
// #include "pUf/DDtU.H" }
// } else
// else
{ {
#include "pU/UEqns.H" #include "pU/UEqns.H"
#include "EEqns.H" #include "EEqns.H"
@ -144,7 +129,9 @@ int main(int argc, char *argv[])
runTime.write(); runTime.write();
runTime.printExecutionTime(Info); Info<< "ExecutionTime = "
<< runTime.elapsedCpuTime()
<< " s\n\n" << endl;
} }
Info<< "End\n" << endl; Info<< "End\n" << endl;

View File

@ -1,8 +1,6 @@
#!/bin/sh #!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory cd ${0%/*} || exit 1 # Run from this directory
wclean libso twoPhaseSystem
wclean libso twoPhaseCompressibleTurbulenceModels
wclean wclean
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -4,8 +4,6 @@ cd ${0%/*} || exit 1 # Run from this directory
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
wmake $targetType twoPhaseSystem
wmake $targetType twoPhaseCompressibleTurbulenceModels
wmake $targetType wmake $targetType
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -8,46 +8,38 @@ for (int Ecorr=0; Ecorr<nEnergyCorrectors; Ecorr++)
phaseSystem::heatTransferTable& phaseSystem::heatTransferTable&
heatTransfer = heatTransferPtr(); heatTransfer = heatTransferPtr();
if (!phase1.isothermal())
{ {
tmp<fvScalarMatrix> E1Eqn(phase1.heEqn()); fvScalarMatrix E1Eqn
(
phase1.heEqn()
==
*heatTransfer[phase1.name()]
+ alpha1*rho1*(U1&g)
+ fvOptions(alpha1, rho1, thermo1.he())
);
if (E1Eqn.valid()) E1Eqn.relax();
{ fvOptions.constrain(E1Eqn);
E1Eqn = E1Eqn.solve();
( fvOptions.correct(thermo1.he());
E1Eqn
==
*heatTransfer[phase1.name()]
+ alpha1*rho1*(U1&g)
+ fvOptions(alpha1, rho1, phase1.thermo().he())
);
E1Eqn->relax();
fvOptions.constrain(E1Eqn.ref());
E1Eqn->solve();
fvOptions.correct(phase1.thermo().he());
}
} }
if (!phase2.isothermal())
{ {
tmp<fvScalarMatrix> E2Eqn(phase2.heEqn()); fvScalarMatrix E2Eqn
(
phase2.heEqn()
==
*heatTransfer[phase2.name()]
+ alpha2*rho2*(U2&g)
+ fvOptions(alpha2, rho2, phase2.thermoRef().he())
);
if (E2Eqn.valid()) E2Eqn.relax();
{ fvOptions.constrain(E2Eqn);
E2Eqn = E2Eqn.solve();
( fvOptions.correct(thermo2.he());
E2Eqn
==
*heatTransfer[phase2.name()]
+ alpha2*rho2*(U2&g)
+ fvOptions(alpha2, rho2, phase2.thermo().he())
);
E2Eqn->relax();
fvOptions.constrain(E2Eqn.ref());
E2Eqn->solve();
fvOptions.correct(phase2.thermo().he());
}
} }
fluid.correctThermo(); fluid.correctThermo();

View File

@ -1,12 +1,12 @@
EXE_INC = \ EXE_INC = \
-ItwoPhaseSystem/lnInclude \
-I../phaseSystems/lnInclude \
-I../interfacialModels/lnInclude \
-I../interfacialCompositionModels/lnInclude \
-ItwoPhaseCompressibleTurbulenceModels/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/sampling/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)/thermophysicalModels/basic/lnInclude \
-I$(LIB_SRC)/transportModels/compressible/lnInclude \ -I$(LIB_SRC)/transportModels/compressible/lnInclude \
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \ -I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \

View File

@ -5,46 +5,41 @@
phaseSystem::massTransferTable& phaseSystem::massTransferTable&
massTransfer(massTransferPtr()); massTransfer(massTransferPtr());
PtrList<volScalarField>& Y1 = phase1.Y(); if (!phase1.pure())
PtrList<volScalarField>& Y2 = phase2.Y();
forAll(Y1, i)
{ {
tmp<fvScalarMatrix> Y1iEqn(phase1.YiEqn(Y1[i])); UPtrList<volScalarField>& Y1 = phase1.YActiveRef();
if (Y1iEqn.valid()) forAll(Y1, i)
{ {
Y1iEqn = fvScalarMatrix Y1iEqn
( (
Y1iEqn phase1.YiEqn(Y1[i])
== ==
*massTransfer[Y1[i].name()] *massTransfer[Y1[i].name()]
+ fvOptions(alpha1, rho1, Y1[i]) + fvOptions(alpha1, rho1, Y1[i])
); );
Y1iEqn->relax(); Y1iEqn.relax();
Y1iEqn->solve(mesh.solver("Yi")); Y1iEqn.solve(mesh.solver("Yi"));
} }
} }
forAll(Y2, i) if (!phase2.pure())
{ {
tmp<fvScalarMatrix> Y2iEqn(phase2.YiEqn(Y2[i])); UPtrList<volScalarField>& Y2 = phase2.YActiveRef();
if (Y2iEqn.valid()) forAll(Y2, i)
{ {
Y2iEqn = fvScalarMatrix Y2iEqn
( (
Y2iEqn phase2.YiEqn(Y2[i])
== ==
*massTransfer[Y2[i].name()] *massTransfer[Y2[i].name()]
+ fvOptions(alpha2, rho2, Y2[i]) + fvOptions(alpha2, rho2, Y2[i])
); );
Y2iEqn->relax(); Y2iEqn.relax();
Y2iEqn->solve(mesh.solver("Yi")); Y2iEqn.solve(mesh.solver("Yi"));
} }
} }
fluid.massTransfer(); // updates interfacial mass flow rates
} }

View File

@ -1,22 +1,21 @@
phaseModel& phase1 = fluid.phase1(); phaseModel& phase1 = fluid.phase1();
phaseModel& phase2 = fluid.phase2(); phaseModel& phase2 = fluid.phase2();
volScalarField& alpha1 = phase1; const volScalarField& alpha1 = phase1;
volScalarField& alpha2 = phase2; const volScalarField& alpha2 = phase2;
volVectorField& U1 = phase1.U(); volVectorField& U1 = phase1.URef();
surfaceScalarField& phi1 = phase1.phi(); surfaceScalarField& phi1 = phase1.phiRef();
surfaceScalarField& alphaPhi1 = phase1.alphaPhi(); const surfaceScalarField& alphaPhi1 = phase1.alphaPhi();
surfaceScalarField& alphaRhoPhi1 = phase1.alphaRhoPhi();
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(); surfaceScalarField& phi = fluid.phi();
rhoThermo& thermo1 = phase1.thermo(); rhoThermo& thermo1 = phase1.thermoRef();
rhoThermo& thermo2 = phase2.thermo(); rhoThermo& thermo2 = phase2.thermoRef();
volScalarField& rho1 = thermo1.rho(); volScalarField& rho1 = thermo1.rho();
const volScalarField& psi1 = thermo1.psi(); const volScalarField& psi1 = thermo1.psi();

View File

@ -19,7 +19,7 @@ dimensionedScalar pMin
#include "gh.H" #include "gh.H"
volScalarField& p = fluid.phase1().thermo().p(); volScalarField& p = fluid.phase1().thermoRef().p();
Info<< "Reading field p_rgh\n" << endl; Info<< "Reading field p_rgh\n" << endl;
volScalarField p_rgh volScalarField p_rgh

View File

@ -1,82 +1,54 @@
surfaceScalarField alphaf1("alphaf1", fvc::interpolate(alpha1)); const surfaceScalarField alphaf1("alphaf1", fvc::interpolate(alpha1));
surfaceScalarField alphaf2("alphaf2", scalar(1) - alphaf1); const surfaceScalarField alphaf2("alphaf2", scalar(1) - alphaf1);
volScalarField rAU1 PtrList<volScalarField> rAUs;
rAUs.append
( (
IOobject::groupName("rAU", phase1.name()), new volScalarField
1.0 (
/( IOobject::groupName("rAU", phase1.name()),
U1Eqn.A() 1.0
+ byDt(max(phase1.residualAlpha() - alpha1, scalar(0))*rho1) /(
U1Eqn.A()
+ byDt(max(phase1.residualAlpha() - alpha1, scalar(0))*rho1)
)
) )
); );
volScalarField rAU2 rAUs.append
( (
IOobject::groupName("rAU", phase2.name()), new volScalarField
1.0 (
/( IOobject::groupName("rAU", phase2.name()),
U2Eqn.A() 1.0
+ byDt(max(phase2.residualAlpha() - alpha2, scalar(0))*rho2) /(
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) fvc::interpolate(max(alpha1, phase1.residualAlpha())*rAU1)
); );
surfaceScalarField alpharAUf2 const surfaceScalarField alpharAUf2
( (
fvc::interpolate(max(alpha2, phase2.residualAlpha())*rAU2) fvc::interpolate(max(alpha2, phase2.residualAlpha())*rAU2)
); );
volScalarField Kd(fluid.Kd()); // Drag coefficients
const volScalarField Kd(fluid.Kd());
// Turbulent diffusion, particle-pressure, lift and wall-lubrication fluxes const volScalarField rAUKd1(rAU1*Kd);
tmp<surfaceScalarField> phiF1; const volScalarField rAUKd2(rAU2*Kd);
tmp<surfaceScalarField> phiF2; const surfaceScalarField phiKd1(fvc::interpolate(rAUKd1));
{ const surfaceScalarField phiKd2(fvc::interpolate(rAUKd2));
// 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);
}
}
// Explicit force fluxes
PtrList<surfaceScalarField> phiFs(fluid.phiFs(rAUs));
const surfaceScalarField& phiF1 = phiFs[0];
const surfaceScalarField& phiF2 = phiFs[1];
// --- Pressure corrector loop // --- Pressure corrector loop
while (pimple.correct()) while (pimple.correct())
@ -90,6 +62,34 @@ while (pimple.correct())
MRF.correctBoundaryFlux(U1, phi1); MRF.correctBoundaryFlux(U1, phi1);
MRF.correctBoundaryFlux(U2, phi2); 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 volVectorField HbyA1
( (
IOobject::groupName("HbyA", phase1.name()), IOobject::groupName("HbyA", phase1.name()),
@ -116,98 +116,42 @@ while (pimple.correct())
*U2.oldTime() *U2.oldTime()
); );
surfaceScalarField ghSnGradRho // Correction force fluxes
( PtrList<surfaceScalarField> ddtCorrByAs(fluid.ddtCorrByAs(rAUs));
"ghSnGradRho",
ghf*fvc::snGrad(rho)*mesh.magSf()
);
surfaceScalarField phig1 // Predicted fluxes
( const surfaceScalarField phiHbyA1
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
( (
IOobject::groupName("phiHbyA", phase1.name()), IOobject::groupName("phiHbyA", phase1.name()),
fvc::flux(HbyA1) fvc::flux(HbyA1) - phigF1 - ddtCorrByAs[0]
+ phiCorrCoeff1
*fvc::interpolate(byDt(alpha1.oldTime()*rho1.oldTime()*rAU1))
*(MRF.absolute(phi1.oldTime()) - fvc::flux(U1.oldTime()))
- phiF1()
- phig1
); );
// Phase-2 predicted flux const surfaceScalarField phiHbyA2
surfaceScalarField phiHbyA2
( (
IOobject::groupName("phiHbyA", phase2.name()), IOobject::groupName("phiHbyA", phase2.name()),
fvc::flux(HbyA2) fvc::flux(HbyA2) - phigF2 - ddtCorrByAs[1]
+ phiCorrCoeff2
*fvc::interpolate(byDt(alpha2.oldTime()*rho2.oldTime()*rAU2))
*(MRF.absolute(phi2.oldTime()) - fvc::flux(U2.oldTime()))
- phiF2()
- phig2
); );
// Face-drag coefficients ddtCorrByAs.clear();
surfaceScalarField rAUKd1(fvc::interpolate(rAU1*Kd));
surfaceScalarField rAUKd2(fvc::interpolate(rAU2*Kd));
// Construct the mean predicted flux // Drag fluxes
// including explicit drag contributions based on absolute fluxes PtrList<surfaceScalarField> phiKdPhis(fluid.phiKdPhis(rAUs));
const surfaceScalarField& phiKdPhi1 = phiKdPhis[0];
const surfaceScalarField& phiKdPhi2 = phiKdPhis[1];
// Total predicted flux
surfaceScalarField phiHbyA surfaceScalarField phiHbyA
( (
"phiHbyA", "phiHbyA",
alphaf1*(phiHbyA1 + rAUKd1*MRF.absolute(phi2)) alphaf1*(phiHbyA1 - phiKdPhi1) + alphaf2*(phiHbyA2 - phiKdPhi2)
+ alphaf2*(phiHbyA2 + rAUKd2*MRF.absolute(phi1))
); );
MRF.makeRelative(phiHbyA); MRF.makeRelative(phiHbyA);
phiKdPhis.clear();
// Construct pressure "diffusivity" // Construct pressure "diffusivity"
surfaceScalarField rAUf const surfaceScalarField rAUf
( (
"rAUf", "rAUf",
mag(alphaf1*alpharAUf1 + alphaf2*alpharAUf2) mag(alphaf1*alpharAUf1 + alphaf2*alpharAUf2)
@ -226,16 +170,13 @@ while (pimple.correct())
)/(mesh.magSf().boundaryField()*rAUf.boundaryField()) )/(mesh.magSf().boundaryField()*rAUf.boundaryField())
); );
tmp<fvScalarMatrix> pEqnComp1;
tmp<fvScalarMatrix> pEqnComp2;
// Construct the compressibility parts of the pressure equation // Construct the compressibility parts of the pressure equation
tmp<fvScalarMatrix> pEqnComp1, pEqnComp2;
if (phase1.compressible()) if (phase1.compressible())
{ {
if (pimple.transonic()) if (pimple.transonic())
{ {
surfaceScalarField phid1 const surfaceScalarField phid1
( (
IOobject::groupName("phid", phase1.name()), IOobject::groupName("phid", phase1.name()),
fvc::interpolate(psi1)*phi1 fvc::interpolate(psi1)*phi1
@ -243,7 +184,7 @@ while (pimple.correct())
pEqnComp1 = pEqnComp1 =
( (
phase1.continuityError() fvc::ddt(alpha1, rho1) + fvc::div(phase1.alphaRhoPhi())
- fvc::Sp(fvc::ddt(alpha1) + fvc::div(alphaPhi1), rho1) - fvc::Sp(fvc::ddt(alpha1) + fvc::div(alphaPhi1), rho1)
)/rho1 )/rho1
+ correction + correction
@ -261,22 +202,17 @@ while (pimple.correct())
{ {
pEqnComp1 = pEqnComp1 =
( (
phase1.continuityError() fvc::ddt(alpha1, rho1) + fvc::div(phase1.alphaRhoPhi())
- fvc::Sp(fvc::ddt(alpha1) + fvc::div(alphaPhi1), rho1) - fvc::Sp(fvc::ddt(alpha1) + fvc::div(alphaPhi1), rho1)
)/rho1 )/rho1
+ (alpha1*psi1/rho1)*correction(fvm::ddt(p_rgh)); + (alpha1*psi1/rho1)*correction(fvm::ddt(p_rgh));
} }
} }
else
{
pEqnComp1 = fvm::Su(-(fvOptions(alpha1, rho1)&rho1)/rho1, p_rgh);
}
if (phase2.compressible()) if (phase2.compressible())
{ {
if (pimple.transonic()) if (pimple.transonic())
{ {
surfaceScalarField phid2 const surfaceScalarField phid2
( (
IOobject::groupName("phid", phase2.name()), IOobject::groupName("phid", phase2.name()),
fvc::interpolate(psi2)*phi2 fvc::interpolate(psi2)*phi2
@ -284,7 +220,7 @@ while (pimple.correct())
pEqnComp2 = pEqnComp2 =
( (
phase2.continuityError() fvc::ddt(alpha2, rho2) + fvc::div(phase2.alphaRhoPhi())
- fvc::Sp(fvc::ddt(alpha2) + fvc::div(alphaPhi2), rho2) - fvc::Sp(fvc::ddt(alpha2) + fvc::div(alphaPhi2), rho2)
)/rho2 )/rho2
+ correction + correction
@ -302,40 +238,70 @@ while (pimple.correct())
{ {
pEqnComp2 = pEqnComp2 =
( (
phase2.continuityError() fvc::ddt(alpha2, rho2) + fvc::div(phase2.alphaRhoPhi())
- fvc::Sp(fvc::ddt(alpha2) + fvc::div(alphaPhi2), rho2) - fvc::Sp(fvc::ddt(alpha2) + fvc::div(alphaPhi2), rho2)
)/rho2 )/rho2
+ (alpha2*psi2/rho2)*correction(fvm::ddt(p_rgh)); + (alpha2*psi2/rho2)*correction(fvm::ddt(p_rgh));
} }
} }
else
// Add option sources
{ {
pEqnComp2 = fvm::Su(-(fvOptions(alpha2, rho2)&rho2)/rho2, p_rgh); if (fvOptions.appliesToField(rho1.name()))
{
tmp<fvScalarMatrix> optEqn1 = fvOptions(alpha1, rho1);
if (pEqnComp1.valid())
{
pEqnComp1.ref() -= (optEqn1 & rho1)/rho1;
}
else
{
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
{ {
if (pEqnComp1.valid()) PtrList<volScalarField> dmdts(fluid.dmdts());
if (dmdts.set(0))
{ {
pEqnComp1.ref() -= fluid.dmdt()/rho1; if (pEqnComp1.valid())
{
pEqnComp1.ref() -= dmdts[0]/rho1;
}
else
{
pEqnComp1 = fvm::Su(- dmdts[0]/rho1, p_rgh);
}
} }
else if (dmdts.set(1))
{ {
pEqnComp1 = fvm::Su(-fluid.dmdt()/rho1, p_rgh); if (pEqnComp2.valid())
} {
pEqnComp2.ref() -= dmdts[1]/rho2;
if (pEqnComp2.valid()) }
{ else
pEqnComp2.ref() += fluid.dmdt()/rho2; {
} pEqnComp2 = fvm::Su(- dmdts[1]/rho2, p_rgh);
else }
{
pEqnComp2 = fvm::Su(fluid.dmdt()/rho2, p_rgh);
} }
} }
// Cache p prior to solve for density update // 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 // Iterate over the pressure equation to correct for non-orthogonality
while (pimple.correctNonOrthogonal()) while (pimple.correctNonOrthogonal())
@ -360,11 +326,7 @@ while (pimple.correct())
pEqn += pEqnComp2(); pEqn += pEqnComp2();
} }
solve pEqn.solve();
(
pEqn,
mesh.solver(p_rgh.select(pimple.finalInnerIter()))
);
} }
// Correct fluxes and velocities on last non-orthogonal iteration // Correct fluxes and velocities on last non-orthogonal iteration
@ -372,24 +334,28 @@ while (pimple.correct())
{ {
phi = phiHbyA + pEqnIncomp.flux(); phi = phiHbyA + pEqnIncomp.flux();
surfaceScalarField mSfGradp("mSfGradp", pEqnIncomp.flux()/rAUf); surfaceScalarField mSfGradp
(
"mSfGradp",
pEqnIncomp.flux()/rAUf
);
// Partial-elimination phase-flux corrector // Partial-elimination phase-flux corrector
{ {
surfaceScalarField phi1s const surfaceScalarField phi1s
( (
phiHbyA1 + alpharAUf1*mSfGradp phiHbyA1 + alpharAUf1*mSfGradp
); );
surfaceScalarField phi2s const surfaceScalarField phi2s
( (
phiHbyA2 + alpharAUf2*mSfGradp phiHbyA2 + alpharAUf2*mSfGradp
); );
surfaceScalarField phir surfaceScalarField phir
( (
((phi1s + rAUKd1*phi2s) - (phi2s + rAUKd2*phi1s)) ((phi1s + phiKd1*phi2s) - (phi2s + phiKd2*phi1s))
/(1 - rAUKd1*rAUKd2) /(1 - phiKd1*phiKd2)
); );
phi1 = phi + alphaf2*phir; phi1 = phi + alphaf2*phir;
@ -413,23 +379,27 @@ while (pimple.correct())
// Partial-elimination phase-velocity corrector // Partial-elimination phase-velocity corrector
{ {
volVectorField Us1 const volVectorField Us1
( (
HbyA1 HbyA1
+ fvc::reconstruct(alpharAUf1*mSfGradp - phiF1() - phig1) + fvc::reconstruct(alpharAUf1*mSfGradp - phigF1)
); );
volVectorField Us2 const volVectorField Us2
( (
HbyA2 HbyA2
+ fvc::reconstruct(alpharAUf2*mSfGradp - phiF2() - phig2) + fvc::reconstruct(alpharAUf2*mSfGradp - phigF2)
); );
volScalarField D1(rAU1*Kd); const volVectorField U
volScalarField D2(rAU2*Kd); (
alpha1*(Us1 + rAUKd1*U2) + alpha2*(Us2 + rAUKd2*U1)
);
volVectorField U(alpha1*(Us1 + D1*U2) + alpha2*(Us2 + D2*U1)); const volVectorField Ur
volVectorField Ur(((1 - D2)*Us1 - (1 - D1)*Us2)/(1 - D1*D2)); (
((1 - rAUKd2)*Us1 - (1 - rAUKd1)*Us2)/(1 - rAUKd1*rAUKd2)
);
U1 = U + alpha2*Ur; U1 = U + alpha2*Ur;
U1.correctBoundaryConditions(); U1.correctBoundaryConditions();

View File

@ -1,2 +0,0 @@
tddtPhi1 = fvc::ddt(phi1);
tddtPhi2 = fvc::ddt(phi2);

View File

@ -4,33 +4,22 @@ fvVectorMatrix U1Eqn(U1, rho1.dimensions()*U1.dimensions()*dimVolume/dimTime);
fvVectorMatrix U2Eqn(U2, rho2.dimensions()*U2.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 autoPtr<phaseSystem::momentumTransferTable>
( momentumTransferPtr(fluid.momentumTransferf());
fvm::div(phi1, U1) - fvm::Sp(fvc::div(phi1), U1)
+ MRF.DDt(U1)
);
fvVectorMatrix UgradU2 phaseSystem::momentumTransferTable&
( momentumTransfer(momentumTransferPtr());
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()));
{ {
U1Eqn = U1Eqn =
( (
fvm::div(alphaRhoPhi1, U1) - fvm::Sp(fvc::div(alphaRhoPhi1), U1) phase1.UfEqn()
+ fvm::Sp(dmdt21, U1) - dmdt21*U2 ==
+ MRF.DDt(alpha1*rho1, U1) *momentumTransfer[phase1.name()]
+ phase1.turbulence().divDevRhoReff(U1) + fvOptions(alpha1, rho1, U1)
+ Vm*(UgradU1 - (UgradU2 & U2))
- fvOptions(alpha1, rho1, U1)
+ fvm::SuSp(fvOptions(alpha1, rho1)&rho1,U1)
); );
U1Eqn.relax(); U1Eqn.relax();
fvOptions.constrain(U1Eqn); fvOptions.constrain(U1Eqn);
@ -41,13 +30,10 @@ fvVectorMatrix U2Eqn(U2, rho2.dimensions()*U2.dimensions()*dimVolume/dimTime);
{ {
U2Eqn = U2Eqn =
( (
fvm::div(alphaRhoPhi2, U2) - fvm::Sp(fvc::div(alphaRhoPhi2), U2) phase2.UfEqn()
- fvm::Sp(dmdt12, U2) + dmdt12*U1 ==
+ MRF.DDt(alpha2*rho2, U2) *momentumTransfer[phase2.name()]
+ phase2.turbulence().divDevRhoReff(U2) + fvOptions(alpha2, rho2, U2)
+ Vm*(UgradU2 - (UgradU1 & U1))
- fvOptions(alpha2, rho2, U2)
+ fvm::SuSp(fvOptions(alpha2, rho2)&rho2,U2)
); );
U2Eqn.relax(); U2Eqn.relax();
fvOptions.constrain(U2Eqn); fvOptions.constrain(U2Eqn);

View File

@ -1,7 +0,0 @@
tmp<surfaceScalarField> tddtPhi1;
tmp<surfaceScalarField> tddtPhi2;
if (faceMomentum)
{
#include "pUf/DDtU.H"
}

View File

@ -22,73 +22,47 @@ surfaceScalarField alphaRhof20
); );
// Drag coefficient // Drag coefficient
surfaceScalarField Kdf("Kdf", fluid.Kdf()); const surfaceScalarField Kdf("Kdf", fluid.Kdf());
// Virtual-mass coefficient // Diagonal coefficients
surfaceScalarField Vmf("Vmf", fluid.Vmf()); PtrList<surfaceScalarField> AFfs(fluid.AFfs());
surfaceScalarField rAUf1 PtrList<surfaceScalarField> rAUfs;
rAUfs.append
( (
IOobject::groupName("rAUf", phase1.name()), new surfaceScalarField
1.0 (
/( IOobject::groupName("rAUf", phase1.name()),
byDt(alphaRhof10 + Vmf) 1.0
+ fvc::interpolate(U1Eqn.A()) /(
+ Kdf byDt(alphaRhof10)
+ fvc::interpolate(U1Eqn.A())
+ AFfs[0]
)
) )
); );
rAUfs.append
surfaceScalarField rAUf2
( (
IOobject::groupName("rAUf", phase2.name()), new surfaceScalarField
1.0 (
/( IOobject::groupName("rAUf", phase2.name()),
byDt(alphaRhof20 + Vmf) 1.0
+ fvc::interpolate(U2Eqn.A()) /(
+ Kdf byDt(alphaRhof20)
+ fvc::interpolate(U2Eqn.A())
+ AFfs[0]
)
) )
); );
const surfaceScalarField& rAUf1 = rAUfs[0];
const surfaceScalarField& rAUf2 = rAUfs[1];
AFfs.clear();
// Turbulent dispersion, particle-pressure, lift and wall-lubrication forces // Explicit force fluxes
tmp<surfaceScalarField> Ff1; PtrList<surfaceScalarField> phiFfs(fluid.phiFfs(rAUfs));
tmp<surfaceScalarField> Ff2; const surfaceScalarField& phiFf1 = phiFfs[0];
{ const surfaceScalarField& phiFf2 = phiFfs[1];
// 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;
}
while (pimple.correct()) while (pimple.correct())
@ -105,48 +79,47 @@ while (pimple.correct())
MRF.correctBoundaryFlux(U1, phi1); MRF.correctBoundaryFlux(U1, phi1);
MRF.correctBoundaryFlux(U2, phi2); MRF.correctBoundaryFlux(U2, phi2);
surfaceScalarField alpharAUf1 const surfaceScalarField alpharAUf1
( (
IOobject::groupName("alpharAUf", phase1.name()), IOobject::groupName("alpharAUf", phase1.name()),
max(alphaf1, phase1.residualAlpha())*rAUf1 max(alphaf1, phase1.residualAlpha())*rAUf1
); );
surfaceScalarField alpharAUf2 const surfaceScalarField alpharAUf2
( (
IOobject::groupName("alpharAUf", phase2.name()), IOobject::groupName("alpharAUf", phase2.name()),
max(alphaf2, phase2.residualAlpha())*rAUf2 max(alphaf2, phase2.residualAlpha())*rAUf2
); );
surfaceScalarField ghSnGradRho // Combined buoyancy and force fluxes
const surfaceScalarField ghSnGradRho
( (
"ghSnGradRho", "ghSnGradRho",
ghf*fvc::snGrad(rho)*mesh.magSf() ghf*fvc::snGrad(rho)*mesh.magSf()
); );
// Phase-1 buoyancy flux const surfaceScalarField phigF1
surfaceScalarField phig1
( (
IOobject::groupName("phig", phase1.name()),
alpharAUf1 alpharAUf1
*( *(
ghSnGradRho ghSnGradRho
- alphaf2*(rhof1 - rhof2)*(g & mesh.Sf()) - alphaf2*(rhof1 - rhof2)*(g & mesh.Sf())
) )
+ phiFf1
); );
// Phase-2 buoyancy flux const surfaceScalarField phigF2
surfaceScalarField phig2
( (
IOobject::groupName("phig", phase2.name()),
alpharAUf2 alpharAUf2
*( *(
ghSnGradRho ghSnGradRho
- alphaf1*(rhof2 - rhof1)*(g & mesh.Sf()) - alphaf1*(rhof2 - rhof1)*(g & mesh.Sf())
) )
+ phiFf2
); );
// Phase-1 predicted flux // Predicted fluxes
surfaceScalarField phiHbyA1 surfaceScalarField phiHbyA1
( (
IOobject::groupName("phiHbyA", phase1.name()), IOobject::groupName("phiHbyA", phase1.name()),
@ -156,15 +129,11 @@ while (pimple.correct())
phiHbyA1 = phiHbyA1 =
rAUf1 rAUf1
*( *(
(alphaRhof10 + Vmf) alphaRhof10*byDt(MRF.absolute(phi1.oldTime()))
*byDt(MRF.absolute(phi1.oldTime()))
+ fvc::flux(U1Eqn.H()) + fvc::flux(U1Eqn.H())
+ Vmf*tddtPhi2() )
+ Kdf*MRF.absolute(phi2) - phigF1;
- Ff1()
);
// Phase-2 predicted flux
surfaceScalarField phiHbyA2 surfaceScalarField phiHbyA2
( (
IOobject::groupName("phiHbyA", phase2.name()), IOobject::groupName("phiHbyA", phase2.name()),
@ -174,31 +143,34 @@ while (pimple.correct())
phiHbyA2 = phiHbyA2 =
rAUf2 rAUf2
*( *(
(alphaRhof20 + Vmf) alphaRhof20*byDt(MRF.absolute(phi2.oldTime()))
*byDt(MRF.absolute(phi2.oldTime()))
+ fvc::flux(U2Eqn.H()) + fvc::flux(U2Eqn.H())
+ Vmf*tddtPhi1() )
+ Kdf*MRF.absolute(phi1) - phigF2;
- Ff2()
);
// Drag fluxes
PtrList<surfaceScalarField> phiKdPhifs(fluid.phiKdPhifs(rAUfs));
const surfaceScalarField& phiKdPhif1 = phiKdPhifs[0];
const surfaceScalarField& phiKdPhif2 = phiKdPhifs[1];
// Total predicted flux
surfaceScalarField phiHbyA surfaceScalarField phiHbyA
( (
"phiHbyA", "phiHbyA",
alphaf1*(phiHbyA1 - phig1) + alphaf2*(phiHbyA2 - phig2) alphaf1*(phiHbyA1 - phiKdPhif1) + alphaf2*(phiHbyA2 - phiKdPhif2)
); );
MRF.makeRelative(phiHbyA); MRF.makeRelative(phiHbyA);
phiHbyA1 -= phig1; phiKdPhifs.clear();
phiHbyA2 -= phig2;
surfaceScalarField rAUf // Construct pressure "diffusivity"
const surfaceScalarField rAUf
( (
"rAUf", "rAUf",
mag(alphaf1*alpharAUf1 + alphaf2*alpharAUf2) mag(alphaf1*alpharAUf1 + alphaf2*alpharAUf2)
); );
// Update the fixedFluxPressure BCs to ensure flux consistency // Update the fixedFluxPressure BCs to ensure flux consistency
setSnGrad<fixedFluxPressureFvPatchScalarField> setSnGrad<fixedFluxPressureFvPatchScalarField>
( (
@ -212,10 +184,8 @@ while (pimple.correct())
)/(mesh.magSf().boundaryField()*rAUf.boundaryField()) )/(mesh.magSf().boundaryField()*rAUf.boundaryField())
); );
tmp<fvScalarMatrix> pEqnComp1;
tmp<fvScalarMatrix> pEqnComp2;
// Construct the compressibility parts of the pressure equation // Construct the compressibility parts of the pressure equation
tmp<fvScalarMatrix> pEqnComp1, pEqnComp2;
if (phase1.compressible()) if (phase1.compressible())
{ {
@ -229,7 +199,7 @@ while (pimple.correct())
pEqnComp1 = pEqnComp1 =
( (
phase1.continuityError() fvc::ddt(alpha1, rho1) + fvc::div(phase1.alphaRhoPhi())
- fvc::Sp(fvc::ddt(alpha1) + fvc::div(alphaPhi1), rho1) - fvc::Sp(fvc::ddt(alpha1) + fvc::div(alphaPhi1), rho1)
)/rho1 )/rho1
+ correction + correction
@ -247,16 +217,12 @@ while (pimple.correct())
{ {
pEqnComp1 = pEqnComp1 =
( (
phase1.continuityError() fvc::ddt(alpha1, rho1) + fvc::div(phase1.alphaRhoPhi())
- fvc::Sp(fvc::ddt(alpha1) + fvc::div(alphaPhi1), rho1) - fvc::Sp(fvc::ddt(alpha1) + fvc::div(alphaPhi1), rho1)
)/rho1 )/rho1
+ (alpha1*psi1/rho1)*correction(fvm::ddt(p_rgh)); + (alpha1*psi1/rho1)*correction(fvm::ddt(p_rgh));
} }
} }
else
{
pEqnComp1 = fvm::Su(-(fvOptions(alpha1, rho1)&rho1)/rho1, p_rgh);
}
if (phase2.compressible()) if (phase2.compressible())
{ {
@ -270,7 +236,7 @@ while (pimple.correct())
pEqnComp2 = pEqnComp2 =
( (
phase2.continuityError() fvc::ddt(alpha2, rho2) + fvc::div(phase2.alphaRhoPhi())
- fvc::Sp(fvc::ddt(alpha2) + fvc::div(alphaPhi2), rho2) - fvc::Sp(fvc::ddt(alpha2) + fvc::div(alphaPhi2), rho2)
)/rho2 )/rho2
+ correction + correction
@ -288,35 +254,66 @@ while (pimple.correct())
{ {
pEqnComp2 = pEqnComp2 =
( (
phase2.continuityError() fvc::ddt(alpha2, rho2) + fvc::div(phase2.alphaRhoPhi())
- fvc::Sp(fvc::ddt(alpha2) + fvc::div(alphaPhi2), rho2) - fvc::Sp(fvc::ddt(alpha2) + fvc::div(alphaPhi2), rho2)
)/rho2 )/rho2
+ (alpha2*psi2/rho2)*correction(fvm::ddt(p_rgh)); + (alpha2*psi2/rho2)*correction(fvm::ddt(p_rgh));
} }
} }
else
// Add option sources
{ {
pEqnComp2 = fvm::Su(-(fvOptions(alpha2, rho2)&rho2)/rho2, p_rgh); if (fvOptions.appliesToField(rho1.name()))
{
tmp<fvScalarMatrix> optEqn1 = fvOptions(alpha1, rho1);
if (pEqnComp1.valid())
{
pEqnComp1.ref() -= (optEqn1 & rho1)/rho1;
}
else
{
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())
{
if (pEqnComp1.valid())
{
pEqnComp1.ref() -= fluid.dmdt()/rho1;
}
else
{
pEqnComp1 = fvm::Su(-fluid.dmdt()/rho1, p_rgh);
}
if (pEqnComp2.valid()) // Add mass transfer
{
PtrList<volScalarField> dmdts(fluid.dmdts());
if (dmdts.set(0))
{ {
pEqnComp2.ref() += fluid.dmdt()/rho2; if (pEqnComp1.valid())
{
pEqnComp1.ref() -= dmdts[0]/rho1;
}
else
{
pEqnComp1 = fvm::Su(- dmdts[0]/rho1, p_rgh);
}
} }
else if (dmdts.set(1))
{ {
pEqnComp2 = fvm::Su(fluid.dmdt()/rho2, p_rgh); if (pEqnComp2.valid())
{
pEqnComp2.ref() -= dmdts[1]/rho2;
}
else
{
pEqnComp2 = fvm::Su(- dmdts[1]/rho2, p_rgh);
}
} }
} }
@ -357,18 +354,14 @@ while (pimple.correct())
phi = phiHbyA + pEqnIncomp.flux(); phi = phiHbyA + pEqnIncomp.flux();
surfaceScalarField phi1s const surfaceScalarField phi1s
( (
phiHbyA1 phiHbyA1 + alpharAUf1*mSfGradp
+ alpharAUf1*mSfGradp
- rAUf1*Kdf*MRF.absolute(phi2)
); );
surfaceScalarField phi2s const surfaceScalarField phi2s
( (
phiHbyA2 phiHbyA2 + alpharAUf2*mSfGradp
+ alpharAUf2*mSfGradp
- rAUf2*Kdf*MRF.absolute(phi1)
); );
surfaceScalarField phir surfaceScalarField phir

View File

@ -45,33 +45,6 @@ Description
#include "localEulerDdtScheme.H" #include "localEulerDdtScheme.H"
#include "fvcSmooth.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) pimple.dict().lookupOrDefault("faceMomentum", false)
); );
bool implicitPhasePressure
(
mesh.solverDict(alpha1.name()).lookupOrDefault
(
"implicitPhasePressure", false
)
);
#include "pUf/createRDeltaTf.H" #include "pUf/createRDeltaTf.H"
#include "pUf/createDDtU.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -159,7 +123,6 @@ int main(int argc, char *argv[])
#include "pUf/UEqns.H" #include "pUf/UEqns.H"
#include "EEqns.H" #include "EEqns.H"
#include "pUf/pEqn.H" #include "pUf/pEqn.H"
#include "pUf/DDtU.H"
} }
else else
{ {

View File

@ -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
// ************************************************************************* //

View File

@ -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; rhoPhi = alphaPhi*(rho1 - rho2) + phi*rho2;

View File

@ -345,12 +345,12 @@ Foam::RASModels::kineticTheoryModel::divDevRhoReff
void Foam::RASModels::kineticTheoryModel::correct() void Foam::RASModels::kineticTheoryModel::correct()
{ {
// Local references // Local references
const twoPhaseSystem& fluid = refCast<const twoPhaseSystem>(phase_.fluid());
volScalarField alpha(max(alpha_, scalar(0))); volScalarField alpha(max(alpha_, scalar(0)));
const volScalarField& rho = phase_.rho(); const volScalarField& rho = phase_.rho();
const surfaceScalarField& alphaRhoPhi = alphaRhoPhi_; const surfaceScalarField& alphaRhoPhi = alphaRhoPhi_;
const volVectorField& U = U_; const volVectorField& U = U_;
const volVectorField& Uc_ = const volVectorField& Uc_ = fluid.otherPhase(phase_).U();
refCast<const twoPhaseSystem>(phase_.fluid()).otherPhase(phase_).U();
const scalar sqrtPi = sqrt(constant::mathematical::pi); const scalar sqrtPi = sqrt(constant::mathematical::pi);
dimensionedScalar ThetaSmall("ThetaSmall", Theta_.dimensions(), 1.0e-6); dimensionedScalar ThetaSmall("ThetaSmall", Theta_.dimensions(), 1.0e-6);
@ -394,7 +394,11 @@ void Foam::RASModels::kineticTheoryModel::correct()
// Drag // Drag
volScalarField beta 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 // Eq. 3.25, p. 50 Js = J1 - J2

View File

@ -56,7 +56,7 @@ class hyperbolic
// Private data // Private data
//- Maximum fraction of phases which can be considered dispersed //- Maximum fraction of phases which can be considered dispersed
HashTable<dimensionedScalar> maxDispersedAlpha_; HashTable<dimensionedScalar, word, word::hash> maxDispersedAlpha_;
//- Width of the transition //- Width of the transition
const dimensionedScalar transitionAlphaScale_; const dimensionedScalar transitionAlphaScale_;

View File

@ -56,10 +56,12 @@ class linear
// Private data // Private data
//- Maximum fraction of phases which can be considered fully dispersed //- 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 //- Maximum fraction of phases which can be considered partly dispersed
HashTable<dimensionedScalar> maxPartlyDispersedAlpha_; HashTable<dimensionedScalar, word, word::hash>
maxPartlyDispersedAlpha_;
public: public:

View File

@ -210,6 +210,18 @@ public:
return thermo_->kappa(); 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 //- Return the laminar thermal conductivity
tmp<volScalarField> kappaEff tmp<volScalarField> kappaEff
( (

View File

@ -29,6 +29,15 @@ License
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::phasePairKey::hash::hash()
{}
Foam::phasePairKey::phasePairKey()
{}
Foam::phasePairKey::phasePairKey Foam::phasePairKey::phasePairKey
( (
const word& name1, const word& name1,
@ -41,12 +50,10 @@ Foam::phasePairKey::phasePairKey
{} {}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
bool Foam::phasePairKey::ordered() const Foam::phasePairKey::~phasePairKey()
{ {}
return ordered_;
}
// * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
@ -65,8 +72,12 @@ Foam::label Foam::phasePairKey::hash::operator()
word::hash()(key.second()) word::hash()(key.second())
); );
} }
else
return word::hash()(key.first()) + word::hash()(key.second()); {
return
word::hash()(key.first())
+ word::hash()(key.second());
}
} }
@ -78,13 +89,14 @@ bool Foam::operator==
const phasePairKey& b const phasePairKey& b
) )
{ {
const auto cmp = Pair<word>::compare(a,b); const auto c = Pair<word>::compare(a,b);
return return
(
(a.ordered_ == b.ordered_) (a.ordered_ == b.ordered_)
&& (a.ordered_ ? (cmp == 1) : cmp) && (
); (a.ordered_ && (c == 1))
|| (!a.ordered_ && (c != 0))
);
} }
@ -116,11 +128,11 @@ Foam::Istream& Foam::operator>>(Istream& is, phasePairKey& key)
} }
else else
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Phase pair type is not recognised. " << "Phase pair type is not recognised. "
<< temp << temp
<< "Use (phaseDispersed in phaseContinuous) for an ordered pair, " << "Use (phaseDispersed in phaseContinuous) for an ordered"
<< "or (phase1 and phase2) for an unordered pair." << "pair, or (phase1 and pase2) for an unordered pair."
<< exit(FatalError); << exit(FatalError);
} }

View File

@ -59,6 +59,29 @@ class phasePairKey
: :
public Pair<word> 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 // Private data
//- Flag to indicate whether ordering is important //- Flag to indicate whether ordering is important
@ -66,30 +89,23 @@ class phasePairKey
public: 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 // Constructors
//- Construct null //- Construct null
phasePairKey() {} // = default phasePairKey();
//- Construct from names and optional ordering flag //- Construct from names and the ordering flag
phasePairKey phasePairKey
( (
const word& name1, const word& name1,
const word& name2, const word& name2,
const bool ordered = false const bool ordered
); );
//- Destructor //- Destructor
virtual ~phasePairKey() = default; virtual ~phasePairKey();
// Access // Access

View File

@ -5,7 +5,7 @@
\\ / A nd | \\ / A nd |
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
| Copyright (C) 2013-2017 OpenFOAM Foundation | Copyright (C) 2013-2018 OpenFOAM Foundation
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -47,6 +47,7 @@ License
#include "fixedValueFvsPatchFields.H" #include "fixedValueFvsPatchFields.H"
#include "blendingMethod.H" #include "blendingMethod.H"
#include "HashPtrTable.H" #include "HashPtrTable.H"
#include "UniformField.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -108,21 +109,21 @@ Foam::twoPhaseSystem::twoPhaseSystem
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedScalar(dimless/dimTime, Zero) dimensionedScalar("dgdt", dimless/dimTime, 0)
) )
{ {
phase2_.volScalarField::operator=(scalar(1) - phase1_); phase2_.volScalarField::operator=(scalar(1) - phase1_);
// Blending // Blending
for (const entry& dEntry : subDict("blending")) forAllConstIter(dictionary, subDict("blending"), iter)
{ {
blendingMethods_.insert blendingMethods_.insert
( (
dEntry.dict().dictName(), iter().dict().dictName(),
blendingMethod::New blendingMethod::New
( (
dEntry.dict(), iter().dict(),
wordList(lookup("phases")) wordList(lookup("phases"))
) )
); );
@ -134,7 +135,7 @@ Foam::twoPhaseSystem::twoPhaseSystem
phasePair::scalarTable sigmaTable(lookup("sigma")); phasePair::scalarTable sigmaTable(lookup("sigma"));
phasePair::dictTable aspectRatioTable(lookup("aspectRatio")); phasePair::dictTable aspectRatioTable(lookup("aspectRatio"));
pair_.reset pair_.set
( (
new phasePair new phasePair
( (
@ -145,7 +146,7 @@ Foam::twoPhaseSystem::twoPhaseSystem
) )
); );
pair1In2_.reset pair1In2_.set
( (
new orderedPhasePair new orderedPhasePair
( (
@ -157,7 +158,7 @@ Foam::twoPhaseSystem::twoPhaseSystem
) )
); );
pair2In1_.reset pair2In1_.set
( (
new orderedPhasePair new orderedPhasePair
( (
@ -172,100 +173,100 @@ Foam::twoPhaseSystem::twoPhaseSystem
// Models // Models
drag_.reset drag_.set
( (
new BlendedInterfacialModel<dragModel> new BlendedInterfacialModel<dragModel>
( (
lookup("drag"), lookup("drag"),
( (
blendingMethods_.found("drag") blendingMethods_.found("drag")
? *(blendingMethods_["drag"]) ? blendingMethods_["drag"]
: *(blendingMethods_["default"]) : blendingMethods_["default"]
), ),
*pair_, pair_,
*pair1In2_, pair1In2_,
*pair2In1_, pair2In1_,
false // Do not zero drag coefficient at fixed-flux BCs false // Do not zero drag coefficient at fixed-flux BCs
) )
); );
virtualMass_.reset virtualMass_.set
( (
new BlendedInterfacialModel<virtualMassModel> new BlendedInterfacialModel<virtualMassModel>
( (
lookup("virtualMass"), lookup("virtualMass"),
( (
blendingMethods_.found("virtualMass") blendingMethods_.found("virtualMass")
? *(blendingMethods_["virtualMass"]) ? blendingMethods_["virtualMass"]
: *(blendingMethods_["default"]) : blendingMethods_["default"]
), ),
*pair_, pair_,
*pair1In2_, pair1In2_,
*pair2In1_ pair2In1_
) )
); );
heatTransfer_.reset heatTransfer_.set
( (
new BlendedInterfacialModel<heatTransferModel> new BlendedInterfacialModel<heatTransferModel>
( (
lookup("heatTransfer"), lookup("heatTransfer"),
( (
blendingMethods_.found("heatTransfer") blendingMethods_.found("heatTransfer")
? *(blendingMethods_["heatTransfer"]) ? blendingMethods_["heatTransfer"]
: *(blendingMethods_["default"]) : blendingMethods_["default"]
), ),
*pair_, pair_,
*pair1In2_, pair1In2_,
*pair2In1_ pair2In1_
) )
); );
lift_.reset lift_.set
( (
new BlendedInterfacialModel<liftModel> new BlendedInterfacialModel<liftModel>
( (
lookup("lift"), lookup("lift"),
( (
blendingMethods_.found("lift") blendingMethods_.found("lift")
? *(blendingMethods_["lift"]) ? blendingMethods_["lift"]
: *(blendingMethods_["default"]) : blendingMethods_["default"]
), ),
*pair_, pair_,
*pair1In2_, pair1In2_,
*pair2In1_ pair2In1_
) )
); );
wallLubrication_.reset wallLubrication_.set
( (
new BlendedInterfacialModel<wallLubricationModel> new BlendedInterfacialModel<wallLubricationModel>
( (
lookup("wallLubrication"), lookup("wallLubrication"),
( (
blendingMethods_.found("wallLubrication") blendingMethods_.found("wallLubrication")
? *(blendingMethods_["wallLubrication"]) ? blendingMethods_["wallLubrication"]
: *(blendingMethods_["default"]) : blendingMethods_["default"]
), ),
*pair_, pair_,
*pair1In2_, pair1In2_,
*pair2In1_ pair2In1_
) )
); );
turbulentDispersion_.reset turbulentDispersion_.set
( (
new BlendedInterfacialModel<turbulentDispersionModel> new BlendedInterfacialModel<turbulentDispersionModel>
( (
lookup("turbulentDispersion"), lookup("turbulentDispersion"),
( (
blendingMethods_.found("turbulentDispersion") blendingMethods_.found("turbulentDispersion")
? *(blendingMethods_["turbulentDispersion"]) ? blendingMethods_["turbulentDispersion"]
: *(blendingMethods_["default"]) : blendingMethods_["default"]
), ),
*pair_, pair_,
*pair1In2_, pair1In2_,
*pair2In1_ pair2In1_
) )
); );
} }
@ -274,7 +275,7 @@ Foam::twoPhaseSystem::twoPhaseSystem
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::twoPhaseSystem::~twoPhaseSystem() Foam::twoPhaseSystem::~twoPhaseSystem()
{} // Define here (incomplete type in header) {}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
@ -362,8 +363,8 @@ void Foam::twoPhaseSystem::solve()
alpha1.name() alpha1.name()
); );
label nAlphaSubCycles(alphaControls.get<label>("nAlphaSubCycles")); label nAlphaSubCycles(readLabel(alphaControls.lookup("nAlphaSubCycles")));
label nAlphaCorr(alphaControls.get<label>("nAlphaCorr")); label nAlphaCorr(readLabel(alphaControls.lookup("nAlphaCorr")));
word alphaScheme("div(phi," + alpha1.name() + ')'); word alphaScheme("div(phi," + alpha1.name() + ')');
word alpharScheme("div(phir," + alpha1.name() + ')'); word alpharScheme("div(phir," + alpha1.name() + ')');
@ -401,7 +402,7 @@ void Foam::twoPhaseSystem::solve()
mesh_ mesh_
), ),
mesh_, mesh_,
dimensionedScalar(dgdt_.dimensions(), Zero) dimensionedScalar("Sp", dgdt_.dimensions(), 0.0)
); );
volScalarField::Internal Su volScalarField::Internal Su
@ -466,8 +467,8 @@ void Foam::twoPhaseSystem::solve()
alphaPhic10, alphaPhic10,
(alphaSubCycle.index()*Sp)(), (alphaSubCycle.index()*Sp)(),
(Su - (alphaSubCycle.index() - 1)*Sp*alpha1)(), (Su - (alphaSubCycle.index() - 1)*Sp*alpha1)(),
phase1_.alphaMax(), UniformField<scalar>(phase1_.alphaMax()),
0 zeroField()
); );
if (alphaSubCycle.index() == 1) if (alphaSubCycle.index() == 1)
@ -492,8 +493,8 @@ void Foam::twoPhaseSystem::solve()
alphaPhic1, alphaPhic1,
Sp, Sp,
Su, Su,
phase1_.alphaMax(), UniformField<scalar>(phase1_.alphaMax()),
0 zeroField()
); );
phase1_.alphaPhi() = alphaPhic1; 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 const Foam::dimensionedScalar& Foam::twoPhaseSystem::sigma() const
{ {
return pair_->sigma(); return pair_->sigma();

View File

@ -96,7 +96,7 @@ class twoPhaseSystem
autoPtr<orderedPhasePair> pair2In1_; autoPtr<orderedPhasePair> pair2In1_;
//- Blending methods //- Blending methods
HashTable<autoPtr<blendingMethod>> blendingMethods_; HashTable<autoPtr<blendingMethod>, word, word::hash> blendingMethods_;
//- Drag model //- Drag model
autoPtr<BlendedInterfacialModel<dragModel>> drag_; autoPtr<BlendedInterfacialModel<dragModel>> drag_;
@ -184,11 +184,17 @@ public:
// Access // Access
//- Return the drag model for the given phase //- Access a sub model between a phase pair
const dragModel& drag(const phaseModel& phase) const; template<class modelType>
const modelType& lookupSubModel(const phasePair& key) const;
//- Return the virtual mass model for the given phase //- Access a sub model between two phases
const virtualMassModel& virtualMass(const phaseModel& phase) const; template<class modelType>
const modelType& lookupSubModel
(
const phaseModel& dispersed,
const phaseModel& continuous
) const;
//- Return the surface tension coefficient //- Return the surface tension coefficient
const dimensionedScalar& sigma() const; const dimensionedScalar& sigma() const;
@ -238,6 +244,12 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "twoPhaseSystemTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif #endif
// ************************************************************************* // // ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -98,7 +98,7 @@ export WM_COMPILE_OPTION=Opt
# = SYSTEMOPENMPI | OPENMPI | SYSTEMMPI | MPI | MPICH | MPICH-GM | # = SYSTEMOPENMPI | OPENMPI | SYSTEMMPI | MPI | MPICH | MPICH-GM |
# HPMPI | CRAY-MPICH | FJMPI | QSMPI | SGIMPI | INTELMPI | USERMPI # HPMPI | CRAY-MPICH | FJMPI | QSMPI | SGIMPI | INTELMPI | USERMPI
# Also possible to use INTELMPI-xyz etc and define your own wmake rule # Also possible to use INTELMPI-xyz etc and define your own wmake rule
export WM_MPLIB=SYSTEMOPENMPI export WM_MPLIB=OPENMPI
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

View File

@ -108,6 +108,9 @@ wmake $targetType rigidBodyMeshMotion
wmake $targetType semiPermeableBaffle wmake $targetType semiPermeableBaffle
wmake $targetType atmosphericModels wmake $targetType atmosphericModels
phaseSystemModels/Allwmake $targetType $*
wmake $targetType TurbulenceModels/compressible/turbulentFluidThermoModels/
# Needs access to Turbulence # Needs access to Turbulence
wmake $targetType thermophysicalModels/thermophysicalPropertiesFvPatchFields/liquidProperties wmake $targetType thermophysicalModels/thermophysicalPropertiesFvPatchFields/liquidProperties

View File

@ -58,6 +58,7 @@ $(ints)/lists/labelListIOList.C
primitives/Scalar/doubleScalar/doubleScalar.C primitives/Scalar/doubleScalar/doubleScalar.C
primitives/Scalar/floatScalar/floatScalar.C primitives/Scalar/floatScalar/floatScalar.C
primitives/Scalar/scalar/scalar.C primitives/Scalar/scalar/scalar.C
primitives/Scalar/scalar/incGamma.C
primitives/Scalar/scalar/invIncGamma.C primitives/Scalar/scalar/invIncGamma.C
primitives/Scalar/lists/scalarList.C primitives/Scalar/lists/scalarList.C
primitives/Scalar/lists/scalarIOList.C primitives/Scalar/lists/scalarIOList.C

View File

@ -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 * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::IOobject::IOobject Foam::IOobject::IOobject

View File

@ -229,6 +229,13 @@ public:
template<class StringType> template<class StringType>
static inline word groupName(StringType name, const word& group); 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. //- Return the IOobject, but also consider an alternative file name.
// //
// \param io The expected IOobject to use // \param io The expected IOobject to use

View File

@ -63,6 +63,9 @@ public:
// Member Operators // Member Operators
inline operator Type() const;
inline Type operator[](const label) const; inline Type operator[](const label) const;
inline UniformField field() const; inline UniformField field() const;

View File

@ -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> template<class Type>
inline Type Foam::UniformField<Type>::operator[](const label) const 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
// ************************************************************************* // // ************************************************************************* //

View File

@ -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 * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * * //
template<class Type, template<class> class PatchField, class GeoMesh> template<class Type, template<class> class PatchField, class GeoMesh>

View File

@ -461,6 +461,53 @@ public:
//- Clone //- Clone
tmp<GeometricField<Type, PatchField, GeoMesh>> clone() const; 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 //- Destructor
virtual ~GeometricField(); virtual ~GeometricField();

View 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);
}
// ************************************************************************* //

View File

@ -136,6 +136,18 @@ namespace Foam
{ {
//- Inverse normalized incomplete gamma function //- Inverse normalized incomplete gamma function
scalar invIncGamma(const scalar a, const scalar P); 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);
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -42,6 +42,25 @@ public:
typedef arg2 type; 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 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; 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