27 #include "alphaContactAngleFvPatchScalarField.H" 37 #include "surfaceInterpolate.H" 49 void Foam::multiphaseMixtureThermo::calcAlphas()
54 forAllIter(PtrDictionary<phaseModel>, phases_, phase)
56 alphas_ += level*phase();
70 rhoThermo::composite(U.
mesh(), word::null),
71 phases_(
lookup(
"phases"), phaseModel::iNew(p_, T_)),
105 sigmas_(
lookup(
"sigmas")),
106 dimSigma_(1, 0, -2, 0, 0),
123 forAllIter(PtrDictionary<phaseModel>, phases_, phasei)
139 for (++phasei; phasei != phases_.end(); ++
phasei)
147 forAllIter(PtrDictionary<phaseModel>, phases_, phasei)
156 forAllIter(PtrDictionary<phaseModel>, phases_, phasei)
167 word name =
phasei().thermo().thermoName();
169 for (++ phasei; phasei != phases_.end(); ++
phasei)
171 name +=
',' +
phasei().thermo().thermoName();
184 ico &= phase().thermo().incompressible();
197 iso &= phase().thermo().incompressible();
214 for (++phasei; phasei != phases_.end(); ++
phasei)
216 the.ref() +=
phasei().Alpha()*
phasei().thermo().he(p, T);
236 for (++phasei; phasei != phases_.end(); ++
phasei)
259 for (++phasei; phasei != phases_.end(); ++
phasei)
263 *
phasei().thermo().he(T, patchi);
276 for (++phasei; phasei != phases_.end(); ++
phasei)
295 for (++phasei; phasei != phases_.end(); ++
phasei)
297 ths.ref() +=
phasei().Alpha()*
phasei().thermo().hs(p, T);
317 for (++phasei; phasei != phases_.end(); ++
phasei)
340 for (++phasei; phasei != phases_.end(); ++
phasei)
344 *
phasei().thermo().hs(T, patchi);
357 for (++phasei; phasei != phases_.end(); ++
phasei)
376 for (++phasei; phasei != phases_.end(); ++
phasei)
378 tha.ref() +=
phasei().Alpha()*
phasei().thermo().ha(p, T);
398 for (++phasei; phasei != phases_.end(); ++
phasei)
421 for (++phasei; phasei != phases_.end(); ++
phasei)
425 *
phasei().thermo().ha(T, patchi);
438 for (++phasei; phasei != phases_.end(); ++
phasei)
489 for (++phasei; phasei != phases_.end(); ++
phasei)
511 for (++phasei; phasei != phases_.end(); ++
phasei)
515 *
phasei().thermo().Cp(T, patchi);
528 for (++phasei; phasei != phases_.end(); ++
phasei)
550 for (++phasei; phasei != phases_.end(); ++
phasei)
554 *
phasei().thermo().Cv(T, patchi);
573 return Cp(T, patchi)/
Cv(T, patchi);
583 for (++phasei; phasei != phases_.end(); ++
phasei)
600 tmp<scalarField> tCpv
602 phasei().Alpha().boundaryField()[patchi]
606 for (++phasei; phasei != phases_.end(); ++
phasei)
610 *
phasei().thermo().Cpv(T, patchi);
623 for (++phasei; phasei != phases_.end(); ++
phasei)
644 for (++phasei; phasei != phases_.end(); ++
phasei)
648 /
phasei().thermo().W(patchi);
666 return mu(patchi)/
rho(patchi);
676 for (++phasei; phasei != phases_.end(); ++
phasei)
692 tmp<scalarField> tkappa
697 for (++phasei; phasei != phases_.end(); ++
phasei)
713 for (++phasei; phasei != phases_.end(); ++
phasei)
715 talphaEff.ref() +=
phasei()*
phasei().thermo().alphahe();
729 tmp<scalarField> talphaEff
731 phasei().boundaryField()[patchi]
735 for (++phasei; phasei != phases_.end(); ++
phasei)
739 *
phasei().thermo().alphahe(patchi);
755 for (++phasei; phasei != phases_.end(); ++
phasei)
757 tkappaEff.ref() +=
phasei()*
phasei().thermo().kappaEff(alphat);
772 tmp<scalarField> tkappaEff
774 phasei().boundaryField()[patchi]
778 for (++phasei; phasei != phases_.end(); ++
phasei)
782 *
phasei().thermo().kappaEff(alphat, patchi);
798 for (++phasei; phasei != phases_.end(); ++
phasei)
800 talphaEff.ref() +=
phasei()*
phasei().thermo().alphaEff(alphat);
815 tmp<scalarField> talphaEff
817 phasei().boundaryField()[patchi]
821 for (++phasei; phasei != phases_.end(); ++
phasei)
825 *
phasei().thermo().alphaEff(alphat, patchi);
838 for (++phasei; phasei != phases_.end(); ++
phasei)
850 tmp<surfaceScalarField> tstf
854 "surfaceTensionForce",
864 const phaseModel& alpha1 = phase1();
869 for (; phase2 != phases_.end(); ++phase2)
871 const phaseModel& alpha2 = phase2();
873 sigmaTable::const_iterator sigma =
874 sigmas_.find(interfacePair(alpha1, alpha2));
876 if (sigma == sigmas_.end())
879 <<
"Cannot find interface " << interfacePair(alpha1, alpha2)
880 <<
" in list of sigma values" 899 const Time& runTime = mesh_.time();
901 const dictionary& alphaControls = mesh_.solverDict(
"alpha");
903 scalar cAlpha(alphaControls.lookup<scalar>(
"cAlpha"));
915 !(++alphaSubCycle).end();
919 rhoPhiSum += (runTime.deltaT()/totalDeltaT)*rhoPhi_;
955 return gradAlphaf/(
mag(gradAlphaf) + deltaN_);
966 return nHatfv(alpha1, alpha2) & mesh_.Sf();
976 void Foam::multiphaseMixtureThermo::correctContactAngle
978 const phaseModel& alpha1,
979 const phaseModel& alpha2,
980 surfaceVectorField::Boundary& nHatb
983 const volScalarField::Boundary& a1bf = alpha1.boundaryField();
984 const volScalarField::Boundary& a2bf = alpha2.boundaryField();
986 const fvBoundaryMesh&
boundary = mesh_.boundary();
992 isA<alphaContactAngleFvPatchScalarField>(a1bf[patchi])
993 || isA<alphaContactAngleFvPatchScalarField>(a2bf[patchi])
998 isA<alphaContactAngleFvPatchScalarField>(a1bf[patchi])
999 && isA<alphaContactAngleFvPatchScalarField>(a2bf[patchi])
1003 <<
"alphaContactAngle boundary condition " 1004 "specified on patch " << boundary[
patchi].name()
1005 <<
" for both " << alpha1.name() <<
" and " << alpha2.name()
1006 <<
nl <<
"which may be inconsistent." 1010 const alphaContactAngleFvPatchScalarField& acap =
1011 isA<alphaContactAngleFvPatchScalarField>(a1bf[
patchi])
1012 ? refCast<const alphaContactAngleFvPatchScalarField>(a1bf[patchi])
1013 :
refCast<const alphaContactAngleFvPatchScalarField>(a2bf[patchi])
1020 mesh_.Sf().boundaryField()[
patchi]
1021 /mesh_.magSf().boundaryField()[
patchi]
1024 alphaContactAngleFvPatchScalarField::thetaPropsTable::
1026 acap.thetaProps().find(interfacePair(alpha1, alpha2));
1028 if (tp == acap.thetaProps().end())
1031 <<
"Cannot find interface " << interfacePair(alpha1, alpha2)
1032 <<
"\n in table of theta properties for patch " 1033 << acap.patch().name()
1037 const bool matched = (tp.key().first() == alpha1.name());
1039 const scalar theta0 =
degToRad(tp().theta0(matched));
1041 scalarField theta(boundary[patchi].size(), theta0);
1043 const scalar uTheta = tp().uTheta();
1048 const scalar thetaA =
degToRad(tp().thetaA(matched));
1049 const scalar thetaR =
degToRad(tp().thetaR(matched));
1054 U_.boundaryField()[
patchi].patchInternalField()
1055 - U_.boundaryField()[
patchi]
1057 Uwall -= (AfHatPatch & Uwall)*AfHatPatch;
1062 nHatPatch - (AfHatPatch & nHatPatch)*AfHatPatch
1066 nWall /= (
mag(nWall) + small);
1072 theta += (thetaA - thetaR)*
tanh(uwall/uTheta);
1086 b2[facei] =
cos(
acos(a12[facei]) - theta[facei]);
1094 nHatPatch = a*AfHatPatch +
b*nHatPatch;
1096 nHatPatch /= (
mag(nHatPatch) + deltaN_.
value());
1104 const phaseModel& alpha1,
1105 const phaseModel& alpha2
1108 tmp<surfaceVectorField> tnHatfv = nHatfv(alpha1, alpha2);
1110 correctContactAngle(alpha1, alpha2, tnHatfv.ref().boundaryFieldRef());
1113 return -
fvc::div(tnHatfv & mesh_.Sf());
1120 tmp<volScalarField> tnearInt
1133 max(tnearInt(),
pos0(phase() - 0.01)*
pos0(0.99 - phase()));
1140 void Foam::multiphaseMixtureThermo::solveAlphas
1145 static label nSolves=-1;
1154 UPtrList<const volScalarField> alphas(phases_.size());
1155 PtrList<surfaceScalarField> alphaPhis(phases_.size());
1158 forAllIter(PtrDictionary<phaseModel>, phases_, phase)
1160 const phaseModel& alpha = phase();
1162 alphas.set(phasei, &alpha);
1169 phi_.name() + alpha.name(),
1181 forAllIter(PtrDictionary<phaseModel>, phases_, phase2)
1183 phaseModel& alpha2 = phase2();
1185 if (&alpha2 == &alpha)
continue;
1200 1.0/mesh_.time().deltaT().value(),
1201 geometricOneField(),
1224 mesh_.time().timeName(),
1235 forAllIter(PtrDictionary<phaseModel>, phases_, phase)
1237 phaseModel& alpha = phase();
1246 mesh_.time().timeName(),
1258 mesh_.time().timeName(),
1263 divU.v()*
min(alpha.v(), scalar(1))
1271 if (dgdt[celli] < 0.0 && alpha[celli] > 0.0)
1273 Sp[celli] += dgdt[celli]*alpha[celli];
1274 Su[celli] -= dgdt[celli]*alpha[celli];
1276 else if (dgdt[celli] > 0.0 && alpha[celli] < 1.0)
1278 Sp[celli] -= dgdt[celli]*(1.0 - alpha[celli]);
1285 const phaseModel& alpha2 = phase2();
1287 if (&alpha2 == &alpha)
continue;
1293 if (dgdt2[celli] > 0.0 && alpha2[celli] < 1.0)
1295 Sp[celli] -= dgdt2[celli]*(1.0 - alpha2[celli]);
1296 Su[celli] += dgdt2[celli]*alpha[celli];
1298 else if (dgdt2[celli] < 0.0 && alpha2[celli] > 0.0)
1300 Sp[celli] += dgdt2[celli]*alpha2[celli];
1307 geometricOneField(),
1316 Info<< alpha.name() <<
" volume fraction, min, max = " 1317 << alpha.weightedAverage(mesh_.V()).value()
1318 <<
' ' <<
min(alpha).value()
1319 <<
' ' <<
max(alpha).value()
1327 Info<<
"Phase-sum volume fraction, min, max = " 1328 << sumAlpha.weightedAverage(mesh_.V()).value()
1329 <<
' ' <<
min(sumAlpha).value()
1330 <<
' ' <<
max(sumAlpha).value()
scalar Cv(const scalar p, const scalar T) const
void limit(const RdeltaTType &rDeltaT, const RhoType &rho, const volScalarField &psi, const surfaceScalarField &phi, surfaceScalarField &phiPsi, const SpType &Sp, const SuType &Su, const PsiMaxType &psiMax, const PsiMinType &psiMin, const bool returnCorr)
dimensionedScalar tanh(const dimensionedScalar &ds)
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
dimensionedScalar acos(const dimensionedScalar &ds)
#define forAll(list, i)
Loop across all elements in list.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
fluidReactionThermo & thermo
volScalarField dgdt(alpha1 *fvc::div(phi))
errorManipArg< error, int > exit(error &err, const int errNo=1)
const word & name() const
Return const access to the source name.
virtual tmp< volScalarField > gamma() const
Gamma = Cp/Cv [].
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Unit conversion functions.
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
To & refCast(From &r)
Reference type cast template function.
virtual tmp< volScalarField > hc() const
Enthalpy of formation [J/kg].
volScalarField alpha(IOobject("alpha", runTime.timeName(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
static tmp< GeometricField< scalar, fvsPatchField, surfaceMesh > > New(const word &name, const Internal &, const PtrList< fvsPatchField< scalar >> &)
Return a temporary field constructed from name,.
virtual tmp< volScalarField > ha() const
Absolute enthalpy [J/kg].
GeometricField< vector, fvsPatchField, surfaceMesh > surfaceVectorField
const dimensionedScalar b
Wien displacement law constant: default SI units: [m K].
Ostream & endl(Ostream &os)
Add newline and flush stream.
Calculate the snGrad of the given volField.
surfaceScalarField phir(fvc::flux(UdmModel.Udm()))
const dimensionSet dimless
dimensionedScalar det(const dimensionedSphericalTensor &dt)
GeometricField< vector, fvPatchField, volMesh > volVectorField
T & first()
Return the first element of the list.
DimensionedField< scalar, volMesh > Internal
Type of the internal field from which this GeometricField is derived.
const dimensionedScalar h
Planck constant.
CGAL::Exact_predicates_exact_constructions_kernel K
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
virtual tmp< volScalarField > Cp() const
Heat capacity at constant pressure [J/kg/K].
virtual void correct()
Solve the film and update the sources.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
const dimensionedScalar sigma
Stefan-Boltzmann constant: default SI units: [W/m^2/K^4].
void correctRho(const volScalarField &dp)
Update densities for given pressure change.
const dimensionSet dimTime
void solve()
Solve for the mixture phase-fractions.
const dimensionedScalar kappa
Coulomb constant: default SI units: [N.m2/C2].
stressControl lookup("compactNormalStress") >> compactNormalStress
dimensionedScalar cos(const dimensionedScalar &ds)
void limitSum(UPtrList< scalarField > &phiPsiCorrs)
virtual tmp< volScalarField > alphahe() const
Thermal diffusivity for energy of mixture [kg/m/s].
Calculate the gradient of the given field.
tmp< volScalarField > rCv() const
Return the phase-averaged reciprocal Cv.
A class for handling words, derived from string.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Calculate the face-flux of the given field.
const Type & value() const
Return const reference to value.
surfaceScalarField alphaPhi(phi.name()+alpha1.name(), fvc::flux(phi, alpha1, alphaScheme))
List< label > labelList
A List of labels.
dimensioned< Type > average(const DimensionedField< Type, GeoMesh > &df)
faceListList boundary(nPatches)
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Calculate the divergence of the given field.
dimensionedScalar pos0(const dimensionedScalar &ds)
const dimensionedScalar mu
Atomic mass unit.
const label nAlphaSubCycles(alphaControls.lookup< label >("nAlphaSubCycles"))
defineTypeNameAndDebug(combustionModel, 0)
virtual tmp< volScalarField > nu() const
Kinematic viscosity of mixture [m^2/s].
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
tmp< volScalarField > divU
const dimensionSet dimMass
static tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > interpolate(const GeometricField< Type, fvPatchField, volMesh > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
const tmp< volScalarField::Internal > & Sp
Calculate the mesh motion flux and convert fluxes from absolute to relative and back.
Internal & ref()
Return a reference to the dimensioned internal field.
const word alphaScheme(mesh.divScheme(divAlphaName)[1].wordToken())
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
virtual tmp< volScalarField > kappaEff(const volScalarField &alphat) const
Effective thermal diffusivity of mixture [W/m/K].
multiphaseMixtureThermo(const volVectorField &U, const surfaceScalarField &phi)
Construct from components.
tmp< surfaceScalarField > absolute(const tmp< surfaceScalarField > &tphi, const volVectorField &U)
Return the given relative flux in absolute form.
virtual tmp< volScalarField > W() const
Molecular weight [kg/kmol].
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
const scalarList W(::W(thermo))
scalar Cp(const scalar p, const scalar T) const
word alpharScheme("div(phirb,alpha)")
virtual tmp< volScalarField > hs() const
Sensible enthalpy [J/kg].
tmp< volScalarField > nearInterface() const
Indicator of the proximity of the interface.
dimensioned< scalar > mag(const dimensioned< Type > &)
Field< vector > vectorField
Specialisation of Field<T> for vector.
MULES: Multidimensional universal limiter for explicit solution.
const doubleScalar e
Elementary charge.
const tmp< volScalarField::Internal > & Su
virtual tmp< volScalarField > Cv() const
Heat capacity at constant volume [J/kg/K].
A class for managing temporary objects.
tmp< surfaceScalarField > surfaceTensionForce() const
tmp< surfaceScalarField > flux(const volVectorField &vvf)
Return the face-flux field obtained from the given volVectorField.
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
virtual tmp< volScalarField > alphaEff(const volScalarField &alphat) const
Effective thermal diffusivity of mixture [W/m/K].
virtual tmp< volScalarField > Cpv() const
Heat capacity at constant pressure/volume [J/kg/K].
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
void explicitSolve(const RdeltaTType &rDeltaT, const RhoType &rho, volScalarField &psi, const surfaceScalarField &phiPsi, const SpType &Sp, const SuType &Su)
virtual tmp< volScalarField > kappa() const
Thermal diffusivity for temperature of mixture [W/m/K].
virtual bool isochoric() const
Return true if the equation of state is isochoric.
virtual word thermoName() const
Return the name of the thermo physics.
virtual void correctThermo()
Correct the thermodynamics of each phase.
virtual volScalarField & he()
Enthalpy/Internal energy [J/kg].
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > snGrad(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
friend class const_iterator
virtual tmp< volScalarField > THE(const volScalarField &h, const volScalarField &p, const volScalarField &T0) const
Temperature from enthalpy/internal energy.
virtual bool incompressible() const
Return true if the equation of state is incompressible.
virtual void correct()
Update properties.