33 #include "surfaceTensionModel.H" 46 namespace diameterModels
55 void Foam::diameterModels::populationBalanceModel::registerVelocityGroups()
59 if (isA<velocityGroup>(fluid_.phases()[
phasei].dPtr()()))
61 const velocityGroup& velGroup =
62 refCast<const velocityGroup>(fluid_.phases()[
phasei].dPtr()());
64 if (velGroup.popBalName() == this->
name())
66 velocityGroups_.resize(velocityGroups_.size() + 1);
70 velocityGroups_.size() - 1,
71 &
const_cast<velocityGroup&
>(velGroup)
74 forAll(velGroup.sizeGroups(), i)
76 this->registerSizeGroups
78 const_cast<sizeGroup&>(velGroup.sizeGroups()[i])
87 void Foam::diameterModels::populationBalanceModel::registerSizeGroups
94 sizeGroups_.size() != 0
96 group.x().value() <= sizeGroups_.last().x().value()
100 <<
"Size groups must be entered according to their representative" 105 sizeGroups_.resize(sizeGroups_.size() + 1);
106 sizeGroups_.set(sizeGroups_.size() - 1, &
group);
109 if (sizeGroups_.size() == 1)
118 sizeGroups_.last().x()
129 sizeGroups_.last().x()
140 sizeGroups_[sizeGroups_.size()-2].x()
141 + sizeGroups_.last().x()
151 sizeGroups_.last().x()
156 delta_.append(
new PtrList<dimensionedScalar>());
165 fluid_.time().timeName(),
180 fluid_.time().timeName(),
190 void Foam::diameterModels::populationBalanceModel::createPhasePairs()
192 forAll(velocityGroups_, i)
194 const phaseModel& phasei = velocityGroups_[i].phase();
196 forAll(velocityGroups_, j)
198 const phaseModel& phasej = velocityGroups_[j].phase();
200 if (&phasei != &phasej)
202 const phasePairKey key
209 if (!phasePairs_.found(key))
230 void Foam::diameterModels::populationBalanceModel::correct()
234 forAll(velocityGroups_, v)
236 velocityGroups_[v].preSolve();
239 forAll(coalescence_, model)
241 coalescence_[model].correct();
246 breakup_[model].correct();
248 breakup_[model].dsdPtr()().
correct();
251 forAll(binaryBreakup_, model)
253 binaryBreakup_[model].correct();
258 drift_[model].correct();
261 forAll(nucleation_, model)
263 nucleation_[model].correct();
268 void Foam::diameterModels::populationBalanceModel::
275 const sizeGroup& fj = sizeGroups_[j];
276 const sizeGroup& fk = sizeGroups_[
k];
281 for (
label i = j; i < sizeGroups_.size(); i++)
286 if (Eta.value() == 0)
continue;
288 const sizeGroup& fi = sizeGroups_[i];
294 0.5*fi.x()*coalescenceRate_()*Eta
295 *fj*fj.phase()/fj.x()
296 *fk*fk.phase()/fk.x();
301 fi.x()*coalescenceRate_()*Eta
302 *fj*fj.phase()/fj.x()
303 *fk*fk.phase()/fk.x();
308 const phasePairKey pairij
314 if (pDmdt_.found(pairij))
316 const scalar dmdtSign
321 pDmdt_[pairij]->ref() += dmdtSign*fj.x()/v*Sui_*fi.phase().rho();
324 const phasePairKey pairik
330 if (pDmdt_.found(pairik))
332 const scalar dmdtSign
337 pDmdt_[pairik]->ref() += dmdtSign*fk.x()/v*Sui_*fi.phase().rho();
340 sizeGroups_[i].shapeModelPtr()->addCoalescence(Sui_, fj, fk);
345 void Foam::diameterModels::populationBalanceModel::
352 const sizeGroup& fi = sizeGroups_[i];
353 const sizeGroup& fj = sizeGroups_[j];
355 SuSp_[i] += coalescenceRate_()*fi.phase()*fj*fj.phase()/fj.x();
359 SuSp_[j] += coalescenceRate_()*fj.phase()*fi*fi.phase()/fi.x();
364 void Foam::diameterModels::populationBalanceModel::
371 const sizeGroup& fk = sizeGroups_[
k];
373 for (
label i = 0; i <=
k; i++)
375 const sizeGroup& fi = sizeGroups_[i];
378 fi.x()*breakupRate_()*breakup_[model].dsdPtr()().nik(i, k)
379 *fk*fk.phase()/fk.x();
383 const phasePairKey pair
389 if (pDmdt_.found(pair))
391 const scalar dmdtSign
396 pDmdt_[pair]->ref() += dmdtSign*Sui_*fi.phase().rho();
399 sizeGroups_[i].shapeModelPtr()->addBreakup(Sui_, fk);
404 void Foam::diameterModels::populationBalanceModel::deathByBreakup(
const label i)
406 const sizeGroup& fi = sizeGroups_[i];
408 SuSp_[i] += breakupRate_()*fi.phase();
412 void Foam::diameterModels::populationBalanceModel::calcDeltas()
416 if (delta_[i].empty())
418 for (
label j = 0; j <= sizeGroups_.size() - 1; j++)
426 v_[i+1].value() - v_[i].value()
432 v_[i].value() < 0.5*sizeGroups_[j].
x().value()
434 0.5*sizeGroups_[j].
x().value() < v_[i+1].value()
437 delta_[i][j] =
mag(0.5*sizeGroups_[j].
x() - v_[i]);
439 else if (0.5*sizeGroups_[j].
x().value() <= v_[i].value())
441 delta_[i][j].value() = 0;
449 void Foam::diameterModels::populationBalanceModel::
456 const sizeGroup& fj = sizeGroups_[j];
457 const sizeGroup& fi = sizeGroups_[i];
459 Sui_ = fi.x()*binaryBreakupRate_()*delta_[i][j]*fj*fj.phase()/fj.x();
463 sizeGroups_[i].shapeModelPtr()->addBreakup(Sui_, fj);
465 const phasePairKey pairij
471 if (pDmdt_.found(pairij))
473 const scalar dmdtSign
478 pDmdt_[pairij]->ref() += dmdtSign*Sui_*fi.phase().rho();
484 for (
label k = 0; k <= j; k++)
489 if (Eta.value() == 0)
continue;
491 const sizeGroup& fk = sizeGroups_[
k];
496 sizeGroups_[
k].x()*binaryBreakupRate_()*delta_[i][j]*Eta
497 *fj*fj.phase()/fj.x();
501 const phasePairKey pairkj
507 if (pDmdt_.found(pairkj))
509 const scalar dmdtSign
513 pDmdt_.find(pairkj).key(),
518 pDmdt_[pairkj]->ref() += dmdtSign*Suk*fi.phase().rho();
521 sizeGroups_[i].shapeModelPtr()->addBreakup(Suk, fj);
526 void Foam::diameterModels::populationBalanceModel::
535 SuSp_[i] += alphai*binaryBreakupRate_()*delta_[j][i];
539 void Foam::diameterModels::populationBalanceModel::drift
545 model.addToDriftRate(driftRate_(), i);
547 const sizeGroup& fp = sizeGroups_[i];
551 rx_() =
pos(driftRate_())*sizeGroups_[i+1].x()/sizeGroups_[i].x();
553 else if (i == sizeGroups_.size() - 1)
555 rx_() =
neg(driftRate_())*sizeGroups_[i-1].x()/sizeGroups_[i].x();
560 pos(driftRate_())*sizeGroups_[i+1].x()/sizeGroups_[i].x()
561 +
neg(driftRate_())*sizeGroups_[i-1].x()/sizeGroups_[i].x();
565 (
neg(1 - rx_()) +
neg(rx_() - rx_()/(1 - rx_())))*driftRate_()
566 *fp.phase()/((rx_() - 1)*fp.x());
571 if (i == sizeGroups_.size() - 2)
573 rx_() =
pos(driftRate_())*sizeGroups_[i+1].x()/sizeGroups_[i].x();
577 *(sizeGroups_[i+1].x() - sizeGroups_[i].x())
578 /(sizeGroups_[i].
x() - sizeGroups_[i-1].x());
580 else if (i < sizeGroups_.size() - 2)
582 rx_() =
pos(driftRate_())*sizeGroups_[i+2].x()/sizeGroups_[i+1].x();
586 *(sizeGroups_[i+2].x() - sizeGroups_[i+1].x())
587 /(sizeGroups_[i+1].
x() - sizeGroups_[i].x());
592 rx_() +=
neg(driftRate_())*sizeGroups_[i-1].x()/sizeGroups_[i].x();
596 *(sizeGroups_[i].x() - sizeGroups_[i-1].x())
597 /(sizeGroups_[i+1].
x() - sizeGroups_[i].x());
601 rx_() +=
neg(driftRate_())*sizeGroups_[i-2].x()/sizeGroups_[i-1].x();
605 *(sizeGroups_[i-1].x() - sizeGroups_[i-2].x())
606 /(sizeGroups_[i].
x() - sizeGroups_[i-1].x());
609 if (i != sizeGroups_.size() - 1)
611 const sizeGroup& fe = sizeGroups_[i+1];
615 pos(driftRate_())*driftRate_()*rdx_()
616 *fp*fp.phase()/fp.x()
621 const phasePairKey pairij
627 if (pDmdt_.found(pairij))
629 const scalar dmdtSign
634 pDmdt_[pairij]->ref() -= dmdtSign*Sue*fp.phase().rho();
637 sizeGroups_[i+1].shapeModelPtr()->addDrift(Sue, fp, model);
642 const sizeGroup& fw = sizeGroups_[i-1];
646 neg(driftRate_())*driftRate_()*rdx_()
647 *fp*fp.phase()/fp.x()
652 const phasePairKey pairih
658 if (pDmdt_.found(pairih))
660 const scalar dmdtSign
665 pDmdt_[pairih]->ref() -= dmdtSign*Suw*fp.phase().rho();
668 sizeGroups_[i-1].shapeModelPtr()->addDrift(Suw, fp, model);
673 void Foam::diameterModels::populationBalanceModel::
677 nucleationModel& model
680 const sizeGroup& fi = sizeGroups_[i];
682 model.addToNucleationRate(nucleationRate_(), i);
684 Sui_ = sizeGroups_[i].x()*nucleationRate_();
688 sizeGroups_[i].shapeModelPtr()->addNucleation(Sui_, fi, model);
692 void Foam::diameterModels::populationBalanceModel::sources()
696 sizeGroups_[i].shapeModelPtr()->reset();
708 pDmdt_(phasePairIter())->ref() =
Zero;
716 if (coalescence_.size() != 0)
718 for (
label j = 0; j <= i; j++)
720 coalescenceRate_() =
Zero;
722 forAll(coalescence_, model)
724 coalescence_[model].addToCoalescenceRate
732 birthByCoalescence(i, j);
734 deathByCoalescence(i, j);
738 if (breakup_.size() != 0)
742 breakup_[model].setBreakupRate(breakupRate_(), i);
744 birthByBreakup(i, model);
750 if (binaryBreakup_.size() != 0)
754 while (delta_[j][i].value() != 0)
756 binaryBreakupRate_() =
Zero;
758 forAll(binaryBreakup_, model)
760 binaryBreakup_[model].addToBinaryBreakupRate
762 binaryBreakupRate_(),
768 birthByBinaryBreakup(j, i);
770 deathByBinaryBreakup(j, i);
776 if (drift_.size() != 0)
781 drift(i, drift_[model]);
785 if (nucleation_.size() != 0)
787 forAll(nucleation_, model)
789 nucleationRate_() =
Zero;
790 nucleation(i, nucleation_[model]);
797 void Foam::diameterModels::populationBalanceModel::dmdt()
799 forAll(velocityGroups_, v)
801 velocityGroup& velGroup = velocityGroups_[v];
803 velGroup.dmdtRef() =
Zero;
807 if (&sizeGroups_[i].phase() == &velGroup.phase())
809 sizeGroup& fi = sizeGroups_[i];
811 velGroup.dmdtRef() += fi.phase().rho()*(Su_[i] - SuSp_[i]*fi);
818 void Foam::diameterModels::populationBalanceModel::calcAlphas()
822 forAll(velocityGroups_, v)
824 const phaseModel& phase = velocityGroups_[v].phase();
826 alphas_() +=
max(phase, phase.residualAlpha());
832 Foam::diameterModels::populationBalanceModel::calcDsm()
834 tmp<volScalarField> tInvDsm
846 forAll(velocityGroups_, v)
848 const phaseModel& phase = velocityGroups_[v].phase();
850 invDsm +=
max(phase, phase.residualAlpha())/(phase.d()*alphas_());
857 void Foam::diameterModels::populationBalanceModel::calcVelocity()
861 forAll(velocityGroups_, v)
863 const phaseModel& phase = velocityGroups_[v].phase();
865 U_() +=
max(phase, phase.residualAlpha())*phase.U()/alphas_();
869 bool Foam::diameterModels::populationBalanceModel::updateSources()
871 const bool result = sourceUpdateCounter_ % sourceUpdateInterval() == 0;
873 ++ sourceUpdateCounter_;
883 const phaseSystem& fluid,
885 HashPtrTable<volScalarField, phasePairKey, phasePairKey::hash>& pDmdt
893 fluid.time().constant(),
899 mesh_(fluid_.
mesh()),
903 fluid_.subDict(
"populationBalanceCoeffs").subDict(name_)
905 pimple_(mesh_.lookupObject<pimpleControl>(
"solutionControl")),
908 mesh_.lookupObject<phaseModel>
910 IOobject::groupName(
"alpha", dict_.
lookup(
"continuousPhase"))
932 dict_.
lookup(
"coalescenceModels"),
933 coalescenceModel::iNew(*this)
938 dict_.
lookup(
"breakupModels"),
939 breakupModel::iNew(*this)
944 dict_.
lookup(
"binaryBreakupModels"),
945 binaryBreakupModel::iNew(*this)
947 binaryBreakupRate_(),
950 dict_.
lookup(
"driftModels"),
951 driftModel::iNew(*this)
958 dict_.
lookup(
"nucleationModels"),
959 nucleationModel::iNew(*this)
965 sourceUpdateCounter_(0)
967 this->registerVelocityGroups();
969 this->createPhasePairs();
971 if (sizeGroups_.size() < 3)
974 <<
"The populationBalance " << name_
975 <<
" requires a minimum number of three sizeGroups to be specified." 980 if (coalescence_.size() != 0)
989 mesh_.time().timeName(),
998 if (breakup_.size() != 0)
1007 fluid_.time().timeName(),
1016 if (binaryBreakup_.size() != 0)
1018 binaryBreakupRate_.set
1024 "binaryBreakupRate",
1025 fluid_.time().timeName(),
1031 "binaryBreakupRate",
1039 if (drift_.size() != 0)
1048 fluid_.time().timeName(),
1063 fluid_.time().timeName(),
1078 fluid_.time().timeName(),
1087 if (nucleation_.size() != 0)
1096 fluid_.time().timeName(),
1110 if (velocityGroups_.size() > 1)
1119 fluid_.time().timeName(),
1136 fluid_.time().timeName(),
1153 fluid_.time().timeName(),
1176 return autoPtr<populationBalanceModel>(
nullptr);
1199 if (i != 0) lowerBoundary = sizeGroups_[i-1].x();
1201 if (i != sizeGroups_.size() - 1) upperBoundary = sizeGroups_[i+1].
x();
1203 if ((i == 0 && v < x0) || (i == sizeGroups_.size() - 1 && v > xm))
1207 else if (v < lowerBoundary || v > upperBoundary)
1211 else if (v.value() == xi.value())
1217 return (upperBoundary - v)/(upperBoundary - xi);
1221 return (v - lowerBoundary)/(xi - lowerBoundary);
1229 const phaseModel& dispersedPhase
1233 fluid_.lookupSubModel<surfaceTensionModel>
1235 phasePair(dispersedPhase, continuousPhase_)
1248 momentumTransportModel::typeName,
1249 continuousPhase_.name()
1257 const dictionary& solutionControls = mesh_.solverDict(name_);
1258 bool solveOnFinalIterOnly =
1259 solutionControls.lookupOrDefault<
bool>(
"solveOnFinalIterOnly",
false);
1261 if (!solveOnFinalIterOnly || pimple_.finalPimpleIter())
1264 const scalar tolerance =
1265 solutionControls.lookup<scalar>(
"tolerance");
1273 scalar maxInitialResidual = 1;
1275 while (++iCorr <= nCorr && maxInitialResidual > tolerance)
1277 Info<<
"populationBalance " 1283 if (updateSources())
1289 maxInitialResidual = 0;
1293 sizeGroup& fi = sizeGroups_[i];
1294 const phaseModel& phase = fi.phase();
1302 + fi.VelocityGroup().mvConvection()->fvmDiv
1304 phase.alphaRhoPhi(),
1309 fi.VelocityGroup().dmdt()
1320 sizeGroupEqn.relax();
1322 maxInitialResidual =
max 1324 sizeGroupEqn.solve().initialResidual(),
1334 sizeGroups_[i].correct();
1337 forAll(velocityGroups_, i)
1339 velocityGroups_[i].postSolve();
1343 if (velocityGroups_.size() > 1)
1352 sizeGroups_.first()*sizeGroups_.first().phase()
1357 sizeGroups_.last()*sizeGroups_.last().phase()
1360 Info<< this->
name() <<
" sizeGroup phase fraction first, last = " 1361 << fAlpha0.weightedAverage(this->
mesh().V()).value()
1362 <<
' ' << fAlphaN.weightedAverage(this->
mesh().V()).value()
Templated abstract base class for multiphase compressible turbulence models.
const char *const group
Group name for atomic constants.
virtual void correct()
Correct diameter independent expressions.
fvMatrix< scalar > fvScalarMatrix
#define forAll(list, i)
Loop across all elements in list.
tmp< fvMatrix< Type > > SuSp(const volScalarField::Internal &, const GeometricField< Type, fvPatchField, volMesh > &)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
PhaseCompressibleMomentumTransportModel< phaseModel > phaseCompressibleMomentumTransportModel
Typedef for phaseCompressibleMomentumTransportModel.
virtual ~populationBalanceModel()
Destructor.
errorManipArg< error, int > exit(error &err, const int errNo=1)
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
populationBalanceModel(const phaseSystem &fluid, const word &name, HashPtrTable< volScalarField, phasePairKey, phasePairKey::hash > &pDmdt)
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
const dimensionedScalar & sigma
Stefan-Boltzmann constant: default SI units: [W/m^2/K^4].
dimensionedSphericalTensor inv(const dimensionedSphericalTensor &dt)
static int compare(const Pair< word > &a, const Pair< word > &b)
Compare Pairs.
static tmp< GeometricField< scalar, fvPatchField, volMesh > > New(const word &name, const Internal &, const PtrList< fvPatchField< scalar >> &)
Return a temporary field constructed from name,.
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
Ostream & endl(Ostream &os)
Add newline and flush stream.
label k
Boltzmann constant.
Generic dimensioned Type class.
bool writeData(Ostream &) const
Dummy write for regIOobject.
GeometricField< vector, fvPatchField, volMesh > volVectorField
dimensionedScalar neg(const dimensionedScalar &ds)
const dimensionedScalar eta(const label i, const dimensionedScalar &v) const
Return allocation coefficient.
tmp< GeometricField< Type, fvPatchField, volMesh > > ddt(const dimensioned< Type > dt, const fvMesh &mesh)
autoPtr< populationBalanceModel > clone() const
Return clone.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Calculate the first temporal derivative.
dimensionedScalar pos(const dimensionedScalar &ds)
const dimensionSet dimVolume(pow3(dimLength))
stressControl lookup("compactNormalStress") >> compactNormalStress
static word groupName(Name name, const word &group)
tmp< fvMatrix< Type > > ddt(const GeometricField< Type, fvPatchField, volMesh > &vf)
Calculate the matrix for the first temporal derivative.
const phaseCompressibleMomentumTransportModel & continuousTurbulence() const
Return reference to turbulence model of the continuous phase.
Calculate the field for explicit evaluation of implicit and explicit sources.
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Calculate the divergence of the given field.
Info<< "Predicted p max-min : "<< max(p).value()<< " "<< min(p).value()<< endl;rho==max(rho0+psi *p, rhoMin);# 1 "/home/ubuntu/OpenFOAM-8/applications/solvers/multiphase/cavitatingFoam/alphavPsi.H" 1{ alphav=max(min((rho - rholSat)/(rhovSat - rholSat), scalar(1)), scalar(0));alphal=1.0 - alphav;Info<< "max-min alphav: "<< max(alphav).value()<< " "<< min(alphav).value()<< endl;psiModel-> correct()
defineTypeNameAndDebug(combustionModel, 0)
word name(const complex &)
Return a string representation of a complex.
Internal & ref()
Return a reference to the dimensioned internal field.
#define notImplemented(functionName)
Issue a FatalErrorIn for a function not currently implemented.
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
dimensioned< scalar > mag(const dimensioned< Type > &)
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
const tmp< volScalarField > sigmaWithContinuousPhase(const phaseModel &dispersedPhase) const
Return the surface tension coefficient between a given dispersed.
A class for managing temporary objects.
void solve()
Solve the population balance equation.
tmp< GeometricField< Type, fvPatchField, volMesh > > Su(const GeometricField< Type, fvPatchField, volMesh > &su, const GeometricField< Type, fvPatchField, volMesh > &vf)
Calculate the matrix for implicit and explicit sources.
const dimensionSet dimVelocity