Go to the documentation of this file.
28 #include "multiphaseSystem.H"
29 #include "alphaContactAngleFvPatchScalarField.H"
34 #include "surfaceInterpolate.H"
43 const Foam::scalar Foam::multiphaseSystem::convertToRad =
49 void Foam::multiphaseSystem::calcAlphas()
56 alphas_ += level *
phase;
62 void Foam::multiphaseSystem::solveAlphas()
64 PtrList<surfaceScalarField> alphaPhiCorrs(phases_.size());
67 for (phaseModel& phase : phases_)
76 "phi" +
alpha1.name() +
"Corr",
81 "div(phi," +
alpha1.name() +
')'
88 for (phaseModel&
phase2 : phases_)
92 if (&
phase2 == &phase)
continue;
96 const auto cAlpha = cAlphas_.cfind(interfacePair(phase,
phase2));
108 const word phirScheme
121 phase.correctInflowOutflow(alphaPhiCorr);
125 1.0/mesh_.time().deltaT().value(),
147 mesh_.time().timeName(),
156 for (phaseModel& phase : phases_)
159 alphaPhi += upwind<scalar>(mesh_, phi_).flux(phase);
160 phase.correctInflowOutflow(
alphaPhi);
171 Info<< phase.name() <<
" volume fraction, min, max = "
172 << phase.weightedAverage(mesh_.V()).value()
173 <<
' ' <<
min(phase).value()
174 <<
' ' <<
max(phase).value()
182 Info<<
"Phase-sum volume fraction, min, max = "
183 << sumAlpha.weightedAverage(mesh_.V()).value()
184 <<
' ' <<
min(sumAlpha).value()
185 <<
' ' <<
max(sumAlpha).value()
190 for (phaseModel& phase : phases_)
222 return gradAlphaf/(
mag(gradAlphaf) + deltaN_);
243 void Foam::multiphaseSystem::correctContactAngle
247 surfaceVectorField::Boundary& nHatb
250 const volScalarField::Boundary& gbf
253 const fvBoundaryMesh&
boundary = mesh_.boundary();
257 if (isA<alphaContactAngleFvPatchScalarField>(gbf[patchi]))
259 const alphaContactAngleFvPatchScalarField& acap =
260 refCast<const alphaContactAngleFvPatchScalarField>(gbf[patchi]);
266 mesh_.Sf().boundaryField()[patchi]
267 /mesh_.magSf().boundaryField()[patchi]
276 <<
"Cannot find interface " << interfacePair(
phase1,
phase2)
277 <<
"\n in table of theta properties for patch "
278 << acap.patch().name()
282 bool matched = (tp.key().first() ==
phase1.
name());
284 scalar theta0 = convertToRad*tp().theta0(matched);
287 scalar uTheta = tp().uTheta();
292 scalar thetaA = convertToRad*tp().thetaA(matched);
293 scalar thetaR = convertToRad*tp().thetaR(matched);
298 phase1.
U().boundaryField()[patchi].patchInternalField()
299 -
phase1.
U().boundaryField()[patchi]
301 Uwall -= (AfHatPatch & Uwall)*AfHatPatch;
306 nHatPatch - (AfHatPatch & nHatPatch)*AfHatPatch
310 nWall /= (
mag(nWall) + SMALL);
316 theta += (thetaA - thetaR)*
tanh(uwall/uTheta);
330 b2[facei] =
cos(
acos(a12[facei]) - theta[facei]);
338 nHatPatch = a*AfHatPatch +
b*nHatPatch;
340 nHatPatch /= (
mag(nHatPatch) + deltaN_.value());
352 tmp<surfaceVectorField> tnHatfv = nHatfv(
phase1,
phase2);
357 return -
fvc::div(tnHatfv & mesh_.Sf());
373 "transportProperties",
376 IOobject::MUST_READ_IF_MODIFIED,
381 phases_(
lookup(
"phases"), phaseModel::iNew(
U.
mesh())),
400 sigmas_(
lookup(
"sigmas")),
401 dimSigma_(1, 0, -2, 0, 0),
402 cAlphas_(
lookup(
"interfaceCompression")),
403 Cvms_(
lookup(
"virtualMass")),
413 interfaceDictTable dragModelsDict(
lookup(
"drag"));
423 *
phases_.lookup(iter.key().first()),
424 *
phases_.lookup(iter.key().second())
440 if (sigmas_.
found(key) && !cAlphas_.
found(key))
443 <<
"Compression coefficient not specified for phase pair ("
445 <<
") for which a surface tension coefficient is specified"
457 auto iter = phases_.cbegin();
459 tmp<volScalarField>
trho = iter()*iter().rho();
462 for (++iter; iter != phases_.cend(); ++iter)
464 rho += iter()*iter().rho();
474 auto iter = phases_.cbegin();
476 tmp<scalarField>
trho = iter().boundaryField()[patchi]*iter().rho().value();
479 for (++iter; iter != phases_.cend(); ++iter)
481 rho += iter().boundaryField()[patchi]*iter().rho().value();
490 auto iter = phases_.cbegin();
492 tmp<volScalarField> tmu = iter()*(iter().rho()*iter().nu());
495 for (++iter; iter != phases_.cend(); ++iter)
497 mu += iter()*(iter().rho()*iter().nu());
507 auto iter = phases_.cbegin();
509 tmp<scalarField> tmu =
510 iter().boundaryField()[patchi]
511 *(iter().rho().value()*iter().nu().value());
514 for (++iter; iter != phases_.cend(); ++iter)
517 iter().boundaryField()[patchi]
518 *(iter().rho().value()*iter().nu().value());
521 return tmu/
rho(patchi);
527 const phaseModel& phase
530 tmp<volScalarField> tCvm
537 mesh_.time().timeName(),
545 for (
const phaseModel&
phase2 : phases_)
552 auto iterCvm = Cvms_.cfind(interfacePair(phase,
phase2));
560 iterCvm = Cvms_.cfind(interfacePair(
phase2, phase));
564 tCvm.
ref() += iterCvm()*phase.rho()*
phase2;
575 const phaseModel& phase
578 tmp<volVectorField> tSvm
585 mesh_.time().timeName(),
592 dimensionSet(1, -2, -2, 0, 0),
598 for (
const phaseModel&
phase2 : phases_)
605 auto Cvm = Cvms_.cfind(interfacePair(phase,
phase2));
613 Cvm = Cvms_.cfind(interfacePair(
phase2, phase));
622 volVectorField::Boundary& SvmBf =
623 tSvm.
ref().boundaryFieldRef();
626 forAll(phase.phi().boundaryField(), patchi)
630 isA<fixedValueFvsPatchScalarField>
632 phase.phi().boundaryField()[patchi]
636 SvmBf[patchi] =
Zero;
647 autoPtr<dragCoeffFields> dragCoeffsPtr(
new dragCoeffFields);
651 const dragModel& dm = *iter();
659 dm.phase1()*dm.phase2(),
660 dm.residualPhaseFraction()
666 mag(dm.phase1().U() - dm.phase2().U()),
675 forAll(dm.phase1().phi().boundaryField(), patchi)
679 isA<fixedValueFvsPatchScalarField>
681 dm.phase1().phi().boundaryField()[patchi]
689 dragCoeffsPtr().set(iter.key(), Kptr);
692 return dragCoeffsPtr;
698 const phaseModel& phase,
702 tmp<volScalarField> tdragCoeff
709 mesh_.time().timeName(),
716 dimensionSet(1, -3, -1, 0, 0),
722 dragModelTable::const_iterator dmIter = dragModels_.begin();
723 dragCoeffFields::const_iterator dcIter =
dragCoeffs.begin();
727 dmIter.good() && dcIter.good();
733 &phase == &dmIter()->phase1()
734 || &phase == &dmIter()->phase2()
737 tdragCoeff.ref() += *dcIter();
750 tmp<surfaceScalarField> tSurfaceTension
757 mesh_.time().timeName(),
764 dimensionSet(1, -2, -2, 0, 0),
769 tSurfaceTension.ref().setOriented();
771 for (
const phaseModel&
phase2 : phases_)
782 tSurfaceTension.ref() +=
792 return tSurfaceTension;
799 tmp<volScalarField> tnearInt
806 mesh_.time().timeName(),
814 for (
const phaseModel& phase : phases_)
817 max(tnearInt(),
pos0(phase - 0.01)*
pos0(0.99 - phase));
826 for (phaseModel& phase : phases_)
840 PtrList<volScalarField> alpha0s(phases_.size());
841 PtrList<surfaceScalarField> alphaPhiSums(phases_.size());
844 for (phaseModel& phase : phases_)
875 subCycleTime alphaSubCycle
880 !(++alphaSubCycle).
end();
886 for (
const phaseModel& phase : phases_)
895 for (phaseModel& phase : phases_)
899 phase.alphaPhi() = alphaPhiSums[
phasei];
925 PtrList<entry> phaseData(
lookup(
"phases"));
928 for (phaseModel& phase : phases_)
930 readOK &= phase.read(phaseData[
phasei++].
dict());
933 lookup(
"sigmas") >> sigmas_;
934 lookup(
"interfaceCompression") >> cAlphas_;
935 lookup(
"virtualMass") >> Cvms_;
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > snGrad(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
tmp< volScalarField > rho() const
Return the mixture density.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
tmp< volScalarField > nearInterface() const
Indicator of the proximity of the interface.
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Dimensionless.
tmp< surfaceScalarField > flux(const volVectorField &vvf)
Return the face-flux field obtained from the given volVectorField.
void explicitSolve(const RdeltaTType &rDeltaT, const RhoType &rho, volScalarField &psi, const surfaceScalarField &phiPsi, const SpType &Sp, const SuType &Su)
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
virtual void solve()
Solve for the phase fractions.
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 deltaT() const
Return time step.
const dimensionedScalar mu
Atomic mass unit.
const phaseModel & phase(const label i) const
Constant access phase model i.
A class for managing temporary objects.
UPtrList< phaseModel > phases_
Unallocated phase list.
static constexpr const zero Zero
Global zero (0)
virtual tmp< volScalarField > rho() const =0
Return the density field.
const dimensionSet dimDensity
const volScalarField & alpha2
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
const Time & time() const
Return time.
Calculate the snGrad of the given volField.
static word timeName(const scalar t, const int precision=precision_)
virtual bool read()
Read object.
autoPtr< dragCoeffFields > dragCoeffs() const
Return the drag coefficients for all of the interfaces.
multiphaseSystem(const fvMesh &mesh)
Construct from fvMesh.
Calculate the divergence of the given field.
const word & name() const
Return const reference to name.
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensionedScalar pos0(const dimensionedScalar &ds)
const volScalarField & alpha1
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
tmp< surfaceScalarField > surfaceTension(const phaseModel &phase) const
Return the surface tension force.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
#define forAll(list, i)
Loop across all elements in list.
Field< vector > vectorField
Specialisation of Field<T> for vector.
surfaceScalarField phic(mixture.cAlpha() *mag(alphaPhic/mesh.magSf()))
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
CGAL::Exact_predicates_exact_constructions_kernel K
tmp< volScalarField > trho
surfaceScalarField phir(fvc::flux(UdmModel.Udm()))
bool set(const Key &key, T *ptr)
Assign a new entry, overwriting existing entries.
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
dimensionedScalar tanh(const dimensionedScalar &ds)
surfaceScalarField alphaPhi(phi.name()+alpha1.name(), fvc::flux(phi, alpha1, alphaScheme))
messageStream Info
Information stream (uses stdout - output is on the master only)
const volVectorField & DDtU() const
const cellModel * lookup(const word &modelName)
Deprecated(2017-11) equivalent to cellModel::ptr static method.
void limitSum(UPtrList< scalarField > &phiPsiCorrs)
autoPtr< multiphaseSystem::dragCoeffFields > dragCoeffs(fluid.dragCoeffs())
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
T * ptr() noexcept
Same as release().
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
static autoPtr< dragModel > New(const dictionary &dict, const phasePair &pair)
ITstream & lookup(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
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.
errorManipArg< error, int > exit(error &err, const int errNo=1)
virtual tmp< surfaceScalarField > phi() const =0
Return the volumetric flux.
GeometricField< vector, fvPatchField, volMesh > volVectorField
const word & name() const
Return the name of this phase.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
constexpr scalar pi(M_PI)
forAllConstIters(mixture.phases(), phase)
virtual bool read()
Read thermophysical properties dictionary.
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
Internal & ref(const bool updateAccessTime=true)
Return a reference to the dimensioned internal field.
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
dimensionedScalar acos(const dimensionedScalar &ds)
Calculate the gradient of the given field.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Calculate the face-flux of the given field.
const dimensionedScalar e
Elementary charge.
virtual tmp< volVectorField > U() const =0
Return the velocity.
dimensionedScalar det(const dimensionedSphericalTensor &dt)
tmp< volScalarField > Cvm(const phaseModel &phase) const
Return the virtual-mass coefficient for the given phase.
dimensionedScalar sigma("sigma", dimMass/sqr(dimTime), transportProperties)
label timeIndex() const
Return current time index.
tmp< volScalarField > dragCoeff(const phaseModel &phase, const dragCoeffFields &dragCoeffs) const
Return the sum of the drag coefficients for the given phase.
GeometricField< vector, fvsPatchField, surfaceMesh > surfaceVectorField
bool found(const Key &key) const
Return true if hashed entry is found in table.
dimensionedScalar cbrt(const dimensionedScalar &ds)
Area-weighted average a surfaceField creating a volField.
MULES: Multidimensional universal limiter for explicit solution.
constant condensation/saturation model.
tmp< volScalarField > nu() const
Return the mixture laminar viscosity.
#define WarningInFunction
Report a warning using Foam::Warning.
tmp< volVectorField > Svm(const phaseModel &phase) const
Return the virtual-mass source for the given phase.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
dimensioned< Type > average(const DimensionedField< Type, GeoMesh > &df)
dimensionedScalar cos(const dimensionedScalar &ds)