39 template<
class CloudType>
42 LocalInteraction<CloudType>& localInteraction
45 localInteraction_(localInteraction),
46 rndGen_(localInteraction.owner().
rndGen()),
51 template<
class CloudType>
54 const BaiGosman<CloudType>& bg,
55 LocalInteraction<CloudType>& localInteraction
58 localInteraction_(localInteraction),
59 rndGen_(localInteraction.owner().
rndGen()),
60 thermoPtr_(bg.thermoPtr_)
66 template<
class CloudType>
73 localInteraction_.owner().db().template cfindObject<SLGThermo>
81 <<
"Local patch interaction type " 83 <<
" requires " << SLGThermo::typeName
84 <<
" to be registered for cloud " 85 << localInteraction_.owner().name()
89 if (!thermoPtr_->hasLiquids() || thermoPtr_->liquids().size() == 0)
92 <<
"Local patch interaction type " 94 <<
" requires at least one liquid component in " 100 template<
class CloudType>
107 <<
"Local patch interaction type " 109 <<
" requires a thermo parcel type exposing T() and rho(). " 110 <<
"Use a thermo/reacting cloud or replace the patch entry with a " 111 <<
"standard localInteraction type." 116 template<
class CloudType>
123 <<
"Local patch interaction type " 125 <<
" was used before " << SLGThermo::typeName
133 template<
class CloudType>
140 scalar magTangent = 0;
143 for (label iter = 0; iter < 100 && magTangent < SMALL; ++iter)
146 tangent = vTest - (vTest & v)*v;
147 magTangent =
mag(tangent);
151 if (magTangent < SMALL)
155 if (absV.y() <= absV.x() && absV.y() <= absV.z())
159 else if (absV.z() <= absV.x() && absV.z() <= absV.y())
164 tangent = axis - (axis & v)*v;
165 magTangent =
mag(tangent);
167 if (magTangent < SMALL)
174 return tangent/magTangent;
178 template<
class CloudType>
189 const scalar thetaMin = 5.0;
190 const scalar thetaMax = 50.0;
191 const scalar thetaSi =
192 (thetaMin + (thetaMax - thetaMin)*rndGen_.sample01<scalar>())
196 const scalar dcorr =
cos(thetaSi);
201 return dirVec/
mag(dirVec);
205 template<
class CloudType>
214 const bool retainParticle,
215 const bool incrementStickCount
218 keepParticle = retainParticle;
222 const label facei =
pp.whichFace(
p.face());
224 localInteraction_.addStickCounters
236 template<
class CloudType>
251 template<
class CloudType>
263 const patchInteractionData& coeffs,
267 const fvMesh&
mesh = localInteraction_.
owner().mesh();
269 localInteraction_.owner().U().boundaryField()[
pp.index()][facei];
272 const vector tanVec1(tangentVector(nf));
273 const vector tanVec2(nf^tanVec1);
275 const scalar np =
p.nParticle();
276 const scalar m =
p.mass()*np;
277 const scalar d =
p.d();
284 const scalar mRatioLimited =
min(
max(mRatio, scalar(0)), scalar(1));
286 if (mRatioLimited <= VSMALL || Wec <= VSMALL || We <= Wec)
288 absorbInteraction(
p,
pp, patchi, idx, m, keepParticle);
292 const scalar mSplash = m*mRatioLimited;
293 const scalar Ns = 5.0*(We/Wec - 1.0);
297 absorbInteraction(
p,
pp, patchi, idx, m, keepParticle);
301 const scalar dBarSplash =
302 (1/
cbrt(6.0))*
cbrt(mRatioLimited/Ns)*d + ROOTVSMALL;
304 scalar dMax = coeffs.dMaxSplash();
307 dMax = 0.9*
cbrt(
max(mRatioLimited, scalar(ROOTVSMALL)))*d;
310 scalar dMin = coeffs.dMinSplash();
316 if (dMin <= ROOTVSMALL || dMax <= dMin)
318 absorbInteraction(
p,
pp, patchi, idx, m, keepParticle);
322 const scalar
K =
exp(-dMin/dBarSplash) -
exp(-dMax/dBarSplash);
325 absorbInteraction(
p,
pp, patchi, idx, m, keepParticle);
329 scalar ESigmaSec = 0;
331 const label parcelsPerSplash = coeffs.parcelsPerSplash();
337 const scalar
y = rndGen_.sample01<scalar>();
338 dNew[i] = -dBarSplash*
log(
exp(-dMin/dBarSplash) -
y*
K);
339 npNew[i] = mRatioLimited*np*
pow3(d)/
pow3(dNew[i])/parcelsPerSplash;
340 ESigmaSec += npNew[i]*
sigma*
p.areaS(dNew[i]);
343 const scalar EKIn = 0.5*m*
magSqr(Un);
344 const scalar ESigmaIn = np*
sigma*
p.areaS(d);
351 const scalar EKs = EKIn + ESigmaIn - ESigmaSec - Ed;
355 absorbInteraction(
p,
pp, patchi, idx, m, keepParticle);
359 const scalar logD =
log(d);
360 const scalar coeff2 =
log(dNew[0]) - logD + ROOTVSMALL;
363 for (
int i = 1; i < parcelsPerSplash; ++i)
365 coeff1 +=
sqr(
log(dNew[i]) - logD);
368 const scalar magUns0 =
374 2.0*parcelsPerSplash*EKs/mSplash/(1.0 + coeff1/
sqr(coeff2))
378 label nSplashParcels = 0;
382 if (dNew[i] <= ROOTVSMALL || npNew[i] <= ROOTVSMALL)
387 const vector dirVec = splashDirection(tanVec1, tanVec2, -nf);
391 pPtr->origId() = pPtr->getNewParticleID();
394 if (coeffs.splashParcelType() >= 0)
396 pPtr->typeId() = coeffs.splashParcelType();
399 pPtr->nParticle() = npNew[i];
406 + magUns0*(
log(dNew[i]) - logD)/coeff2
413 pPtr->track(0.5*rndGen_.sample01<scalar>()*(posC - posCf), 0);
418 localInteraction_.owner().addParticle(pPtr);
425 absorbInteraction(
p,
pp, patchi, idx, m, keepParticle);
429 localInteraction_.addSplashCounters(patchi, idx, mSplash);
431 const scalar mDash = m - mSplash;
434 localInteraction_.addStickCounters
445 keepParticle =
false;
451 template<
class CloudType>
460 const patchInteractionData& coeffs,
467 localInteraction_.owner().U().boundaryField()[
pp.index()][facei];
469 const scalar m =
p.mass()*
p.nParticle();
470 const scalar
rho =
p.rho();
471 const scalar d =
p.d();
477 const scalar Wec = coeffs.Adry()*
pow(
max(La, scalar(VSMALL)), -0.183);
481 absorbInteraction(
p,
pp, patchi, idx, m, keepParticle);
485 const scalar mRatio = 0.2 + 0.6*rndGen_.sample01<scalar>();
504 template<
class CloudType>
513 const patchInteractionData& coeffs,
520 localInteraction_.owner().U().boundaryField()[
pp.index()][facei];
522 const scalar m =
p.mass()*
p.nParticle();
523 const scalar
rho =
p.rho();
524 const scalar d =
p.d();
532 const scalar Wec = coeffs.Awet()*
pow(
max(La, scalar(VSMALL)), -0.183);
536 absorbInteraction(
p,
pp, patchi, idx, m, keepParticle);
540 if (We >= 2 && We < 20)
542 const scalar UMag =
max(
mag(
Urel), scalar(ROOTVSMALL));
546 0.993 - theta*(1.76 - theta*(1.56 - theta*0.49));
548 U = -
epsilon*(Un) + (5.0/7.0)*Ut + Up;
551 localInteraction_.addReboundCounters(patchi, idx, m);
555 if (We >= 20 && We < Wec)
557 absorbInteraction(
p,
pp, patchi, idx, m, keepParticle);
561 const scalar mRatio = 0.2 + 0.8*rndGen_.sample01<scalar>();
579 template<
class CloudType>
590 const patchInteractionData& coeffs = localInteraction_.patchData_[patchi];
594 localInteraction_.owner().patchData(
p,
pp, nw, Up);
596 const label meshFacei =
p.face();
597 const label facei =
pp.whichFace(meshFacei);
603 if (
mag(nw) <= ROOTVSMALL)
605 static bool warnedNormal =
false;
609 <<
"Invalid (zero-magnitude) patch normal for patch " 610 <<
pp.name() <<
"; parcel absorbed. Further occurrences " 611 <<
"will be silently absorbed." <<
nl;
617 p,
pp, patchi, idx,
p.mass()*
p.nParticle(), keepParticle
622 const label celli =
p.cell();
626 const scalar Td =
p.
T();
629 const scalar
sigma = liquid.sigma(pc, Td);
630 const scalar
rho = liquid.rho(pc, Td);
631 const scalar
mu = liquid.mu(pc, Td);
632 const scalar d =
p.d();
634 if (
sigma <= VSMALL ||
rho <= VSMALL ||
mu <= VSMALL || d <= VSMALL)
636 static bool warnedProps =
false;
640 <<
"Non-positive BaiGosman liquid properties for patch " 641 <<
pp.name() <<
" at (pc=" << pc <<
", Td=" << Td <<
"): " 642 <<
"sigma=" <<
sigma <<
", rho=" <<
rho <<
", mu=" <<
mu 643 <<
", d=" << d <<
"; parcel absorbed. Check thermo " 644 <<
"and injection settings. Further occurrences will be " 645 <<
"silently absorbed." <<
nl;
651 p,
pp, patchi, idx,
p.mass()*
p.nParticle(), keepParticle
656 const scalar m =
p.mass()*
p.nParticle();
666 if (Td > coeffs.Tmelt())
668 if (We < coeffs.Wec())
670 absorbInteraction(
p,
pp, patchi, idx, m, keepParticle);
672 else if (We > coeffs.Wec() &&
K > 57.7)
709 absorbInteraction(
p,
pp, patchi, idx, m, keepParticle);
714 const scalar denom =
max(coeffs.Tmelt() - Tc, scalar(ROOTVSMALL));
715 const scalar Tstar =
min(
max((Td - Tc)/denom, scalar(0)), scalar(1));
716 const scalar sigmay = 14e6*
pow(
max(1.0 - Tstar, scalar(0)), 0.7);
721 /(6.0*
max(sigmay, scalar(VSMALL))*
max(Td, scalar(VSMALL)));
722 const scalar
e =
max(0.0,
sqrt(
max(eArg, scalar(0))));
726 absorbInteraction(
p,
pp, patchi, idx, m, keepParticle);
732 bounceInteraction(
e, Un,
U);
733 localInteraction_.addReboundCounters(patchi, idx, m);
741 template<
class CloudType>
753 <<
"Patch " <<
pp.name() <<
" uses local patch interaction type " 755 <<
", but cloud " << localInteraction_.owner().name()
756 <<
" does not use thermo parcels exposing T() and rho()."
List< scalar > scalarList
List of scalar.
dimensionedScalar acos(const dimensionedScalar &ds)
dimensionedScalar log(const dimensionedScalar &ds)
errorManipArg< error, int > exit(error &err, const int errNo=1)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const surfaceVectorField & Cf() const
Return face centres as surfaceVectorField.
SLGThermo slgThermo(mesh, thermo)
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
const Vector< label > & solutionD() const
Return the vector of solved-for directions in mesh.
constexpr char nl
The newline '\n' character (0x0a)
dimensionedScalar sqrt(const dimensionedScalar &ds)
static int myProcNo(label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
virtual const volScalarField & T() const
Temperature [K].
CGAL::Exact_predicates_exact_constructions_kernel K
dimensionedScalar sigma("sigma", dimMass/sqr(dimTime), transportProperties)
#define forAll(list, i)
Loop across all elements in list.
virtual volScalarField & p()
Pressure [Pa].
const Field< point_type > & faceNormals() const
Return face unit normals for patch.
psiReactionThermo & thermo
Internal BaiGosman thermo parcel-patch interaction used by Foam::LocalInteraction.
const dimensionedScalar e
Elementary charge.
dimensionedScalar cos(const dimensionedScalar &ds)
dimensionedScalar exp(const dimensionedScalar &ds)
constexpr scalar twoPi(2 *M_PI)
dimensionedScalar cbrt(const dimensionedScalar &ds)
const liquidMixtureProperties & liquids() const
Return reference to the global (additional) liquids.
constexpr scalar pi(M_PI)
Thermo package for (S)olids (L)iquids and (G)ases Takes reference to thermo package, and provides:
constexpr scalar piByTwo(0.5 *M_PI)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
ParcelType parcelType
Type of parcel the cloud was instantiated for.
dimensionedScalar sin(const dimensionedScalar &ds)
tmp< GeometricField< Type, PatchField, GeoMesh > > T() const
Return transpose (only if it is a tensor field)
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
const labelUList & owner() const
Internal face owner. Note bypassing virtual mechanism so.
const dimensionedScalar mu
Atomic mass unit.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
dimensionedScalar pow3(const dimensionedScalar &ds)
#define WarningInFunction
Report a warning using Foam::Warning.
const volVectorField & C() const
Return cell centres as volVectorField.
const PtrList< liquidProperties > & properties() const
Return the liquid properties.
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
static const word beiGosmanTypeName
BaiGosman type keyword used in patch entries.
const fluidThermo & thermo() const
Return reference to the thermo database.
static constexpr const zero Zero
Global zero (0)