38 template<
class CloudType>
47 const scalar phiSi =
twoPi*rndGen_.sample01<scalar>();
50 const scalar thetaSi =
pi/180.0*(rndGen_.sample01<scalar>()*(50 - 5) + 5);
54 const scalar dcorr =
cos(thetaSi);
59 return dirVec/
mag(dirVec);
63 template<
class CloudType>
76 Info<<
"Parcel " <<
p.origId() <<
" absorbInteraction" <<
endl;
87 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
95 const scalar pc = carrierThermo.
p()[
p.cell()];
102 mass*liq.
hs(pc,
p.T())
105 this->nParcelsTransferred()++;
107 keepParticle =
false;
111 template<
class CloudType>
122 Info<<
"Parcel " <<
p.origId() <<
" bounceInteraction" <<
endl;
129 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
132 const vector Urel =
p.U() - Up;
135 p.U() -= 2.0*nf*(Urel & nf);
141 template<
class CloudType>
153 Info<<
"Parcel " <<
p.origId() <<
" drySplashInteraction" <<
endl;
166 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
170 const scalar pc = carrierThermo.
p()[
p.cell()];
173 const scalar m =
p.mass()*
p.nParticle();
174 const scalar
rho =
p.rho();
175 const scalar d =
p.d();
177 const scalar
mu = liq.
mu(pc,
p.T());
178 const vector Urel =
p.U() - Up;
179 const vector Un = nf*(Urel & nf);
188 const scalar Wec = Adry_*
pow(La, -0.183);
192 absorbInteraction(filmCloudTransfer,
p, pp, facei, m, keepParticle);
197 const scalar mRatio = 0.2 + 0.6*rndGen_.sample01<scalar>();
214 template<
class CloudType>
226 Info<<
"Parcel " <<
p.origId() <<
" wetSplashInteraction" <<
endl;
239 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
243 const scalar pc = carrierThermo.
p()[
p.cell()];
246 const scalar m =
p.mass()*
p.nParticle();
247 const scalar
rho =
p.rho();
248 const scalar d =
p.d();
251 const scalar
mu = liq.
mu(pc,
p.T());
252 const vector Urel =
p.U() - Up;
253 const vector Un = nf*(Urel & nf);
254 const vector Ut = Urel - Un;
263 const scalar Wec = Awet_*
pow(La, -0.183);
267 absorbInteraction(filmCloudTransfer,
p, pp, facei, m, keepParticle);
269 else if ((We >= 2) && (We < 20))
275 const scalar
epsilon = 0.993 - theta*(1.76 - theta*(1.56 - theta*0.49));
283 else if ((We >= 20) && (We < Wec))
285 absorbInteraction(filmCloudTransfer,
p, pp, facei, m, keepParticle);
291 const scalar mRatio = 0.2 + 0.9*rndGen_.sample01<scalar>();
308 template<
class CloudType>
324 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
329 const vector tanVec2 = nf^tanVec1;
332 const scalar np =
p.nParticle();
333 const scalar m =
p.mass()*np;
334 const scalar d =
p.d();
335 const vector Urel =
p.U() - Up;
336 const vector Un = nf*(Urel & nf);
337 const vector Ut = Urel - Un;
338 const vector& posC = mesh.
C()[
p.cell()];
342 const scalar mSplash = m*mRatio;
345 const scalar Ns = 5.0*(We/Wec - 1.0);
348 const scalar dBarSplash = 1/
cbrt(6.0)*
cbrt(mRatio/Ns)*d + rootVSmall;
351 const scalar dMax = 0.9*
cbrt(mRatio)*d;
352 const scalar dMin = 0.1*dMax;
353 const scalar
K =
exp(-dMin/dBarSplash) -
exp(-dMax/dBarSplash);
356 scalar ESigmaSec = 0;
363 const scalar
y = rndGen_.sample01<scalar>();
364 dNew[i] = -dBarSplash*
log(
exp(-dMin/dBarSplash) -
y*
K);
365 npNew[i] = mRatio*np*
pow3(d)/
pow3(dNew[i])/parcelsPerSplash_;
366 ESigmaSec += npNew[i]*
sigma*
p.areaS(dNew[i]);
370 const scalar EKIn = 0.5*m*
magSqr(Un);
373 const scalar ESigmaIn = np*
sigma*
p.areaS(d);
379 const scalar EKs = EKIn + ESigmaIn - ESigmaSec - Ed;
384 absorbInteraction(filmCloudTransfer,
p, pp, facei, m, keepParticle);
389 const scalar logD =
log(d);
390 const scalar coeff2 =
log(dNew[0]) - logD + rootVSmall;
394 coeff1 +=
sqr(
log(dNew[i]) - logD);
398 const scalar magUns0 =
399 sqrt(2.0*parcelsPerSplash_*EKs/mSplash/(1.0 + coeff1/
sqr(coeff2)));
404 const vector dirVec = splashDirection(tanVec1, tanVec2, -nf);
409 pPtr->origId() = pPtr->getNewParticleIndex();
413 if (splashParcelType_ >= 0)
415 pPtr->typeId() = splashParcelType_;
419 pPtr->track(mesh, 0.5*rndGen_.sample01<scalar>()*(posC - posCf), 0);
421 pPtr->nParticle() = npNew[i];
425 pPtr->U() = dirVec*(
mag(Cf_*Ut) + magUns0*(
log(dNew[i]) - logD)/coeff2);
431 this->owner().addParticle(pPtr);
438 const scalar mDash = m - mSplash;
439 absorbInteraction(filmCloudTransfer,
p, pp, facei, mDash, keepParticle);
443 template<
class CloudType>
447 if (filmTransfers_.empty())
466 if (isType<fv::filmCloudTransfer>(
fvModels[i]))
469 &refCast<fv::filmCloudTransfer>(
fvModels[i]);
475 Info<<
"Found filmCloudTransfer fvModel "
479 filmTransfers_.resize(nFilms + 1);
480 filmPatches_.resize(nFilms + 1);
482 filmTransfers_.set(nFilms, filmCloudPtr);
483 filmPatches_[nFilms] =
patchi;
491 return filmTransfers_;
495 template<
class CloudType>
505 template<
class CloudType>
512 this->deltaFilmPatch_ = filmCloudTransfer.
deltaToCloud();
518 UFilmPatch_ = filmCloudTransfer.
UToCloud();
519 rhoFilmPatch_ = filmCloudTransfer.
rhoToCloud();
520 TFilmPatch_ = filmCloudTransfer.
TToCloud();
521 CpFilmPatch_ = filmCloudTransfer.
CpToCloud();
526 this->massParcelPatch_.setSize(0);
531 template<
class CloudType>
535 const label filmFacei
541 p.d() = this->diameterParcelPatch_[filmFacei];
542 p.U() = UFilmPatch_[filmFacei];
543 p.rho() = rhoFilmPatch_[filmFacei];
545 p.nParticle() = this->massParcelPatch_[filmFacei]/
p.rho()/vol;
547 if (this->ejectedParcelType_ >= 0)
549 p.typeId() = this->ejectedParcelType_;
553 p.T() = TFilmPatch_[filmFacei];
554 p.Cp() = CpFilmPatch_[filmFacei];
560 template<
class CloudType>
575 interactionTypeNames_.
read(this->coeffDict().lookup(
"interactionType"))
578 splashParcelType_(0),
579 parcelsPerSplash_(0),
586 <<
" interaction model" <<
endl;
602 template<
class CloudType>
609 rndGen_(sfm.rndGen_),
610 UFilmPatch_(sfm.UFilmPatch_),
611 rhoFilmPatch_(sfm.rhoFilmPatch_),
612 TFilmPatch_(sfm.TFilmPatch_),
613 CpFilmPatch_(sfm.CpFilmPatch_),
614 interactionType_(sfm.interactionType_),
615 deltaWet_(sfm.deltaWet_),
616 splashParcelType_(sfm.splashParcelType_),
617 parcelsPerSplash_(sfm.parcelsPerSplash_),
621 nParcelsSplashed_(sfm.nParcelsSplashed_)
627 template<
class CloudType>
634 template<
class CloudType>
644 forAll(this->filmTransferPtrs(), filmi)
646 if (
patchi == filmPatches_[filmi])
649 filmTransferPtrs()[filmi];
653 switch (interactionType_)
655 case interactionType::bounce:
657 bounceInteraction(
p, pp, facei, keepParticle);
660 case interactionType::absorb:
668 p.nParticle()*
p.mass(),
673 case interactionType::splashBai:
675 if (this->deltaFilmPatch_[facei] < deltaWet_)
702 <<
"Unknown interaction type enumeration"
717 template<
class CloudType>
722 label nSplash0 = this->
template getModelProperty<label>(
"nParcelsSplashed");
726 os <<
" New film splash parcels = " << nSplashTotal <<
endl;
728 if (this->writeTime())
730 this->setModelProperty(
"nParcelsSplashed", nSplashTotal);
731 nParcelsSplashed_ = 0;
#define forAll(list, i)
Loop across all elements in list.
Macros for easy insertion into run-time selection tables.
static const NamedEnum< interactionType, 3 > interactionTypeNames_
Interaction type names.
Thermo parcel<->film transfer model.
virtual void setParcelProperties(parcelType &p, const label filmFacei) const
Set the individual parcel properties.
label splashParcelType_
Splash parcel type label - id assigned to identify parcel for.
virtual void cacheFilmFields(const label filmi)
Cache the film fields in preparation for injection.
virtual const labelList & filmPatches() const
Return pointers to the films.
scalar Cf_
Skin friction typically in the range 0.6 < Cf < 0.8.
void drySplashInteraction(fv::filmCloudTransfer &, const parcelType &p, const polyPatch &pp, const label facei, bool &keepParticle)
Parcel interaction with dry surface.
scalar Awet_
Wet surface roughness coefficient.
virtual void info(Ostream &os)
Write film info to stream.
void splashInteraction(fv::filmCloudTransfer &, const parcelType &p, const polyPatch &pp, const label facei, const scalar mRatio, const scalar We, const scalar Wec, const scalar sigma, bool &keepParticle)
Bai parcel splash interaction model.
vector splashDirection(const vector &tanVec1, const vector &tanVec2, const vector &nf) const
Return splashed parcel direction.
void bounceInteraction(parcelType &p, const polyPatch &pp, const label facei, bool &keepParticle) const
Bounce parcel (flip parcel normal velocity)
void absorbInteraction(fv::filmCloudTransfer &, const parcelType &p, const polyPatch &pp, const label facei, const scalar mass, bool &keepParticle)
Absorb parcel into film.
scalar Adry_
Dry surface roughness coefficient.
scalar deltaWet_
Film thickness beyond which patch is assumed to be wet.
interactionType interactionType_
Interaction type enumeration.
virtual ~CloudFilmTransfer()
Destructor.
CloudFilmTransfer(const dictionary &dict, CloudType &owner)
Construct from components.
void wetSplashInteraction(fv::filmCloudTransfer &, parcelType &p, const polyPatch &pp, const label facei, bool &keepParticle)
Parcel interaction with wetted surface.
label parcelsPerSplash_
Number of new parcels resulting from splash event.
virtual bool transferParcel(parcelType &p, const polyPatch &pp, bool &keepParticle)
Transfer parcel from cloud to film.
Templated base class for dsmc cloud.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
const Field< PointType > & faceNormals() const
Return face normals for patch.
Templated wall surface film model class.
virtual void info(Ostream &os)
Write surface film info to stream.
CloudType::parcelType parcelType
Convenience typedef to the cloud's parcel type.
Templated base class for thermodynamic cloud.
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
A list of keyword definitions, which are a keyword followed by any number of values (e....
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T, if not found return the given default.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
static autoPtr< dictionary > New(Istream &)
Construct top-level dictionary on freestore from Istream.
Base-class for fluid thermodynamic properties.
virtual const volScalarField & p() const =0
Pressure [Pa].
Mesh data needed to do the Finite Volume discretisation.
const volVectorField & C() const
Return cell centres.
const surfaceVectorField & Cf() const
Return face centres.
const word & name() const
Return reference to name.
const polyMesh & mesh() const
Return reference to polyMesh.
Film<->cloud transfer model.
tmp< Field< scalar > > deltaToCloud() const
Transfer the film delta field to the cloud.
void resetFromCloudFields()
Reset the fields accumulated cloud transfer fields.
tmp< Field< scalar > > TToCloud() const
Transfer the film temperature field to the cloud.
tmp< Field< scalar > > CpToCloud() const
Transfer the film heat capacity field to the cloud.
tmp< Field< scalar > > ejectedDiameterToCloud() const
Transfer the ejected droplet diameter to the cloud.
tmp< Field< vector > > UToCloud() const
Transfer the film velocity field to the cloud.
void parcelFromCloud(const label facei, const scalar mass, const vector &momentum, const scalar energy)
Transfer parcel properties from cloud to the film.
tmp< Field< scalar > > ejectedMassToCloud() const
Transfer the ejected mass to the cloud.
bool ejecting() const
Return true if the film is ejecting to the cloud.
tmp< Field< scalar > > rhoToCloud() const
Transfer the film density field to the cloud.
The thermophysical properties of a liquid.
virtual scalar mu(scalar p, scalar T) const =0
Liquid viscosity [Pa s].
virtual scalar sigma(scalar p, scalar T) const =0
Surface tension [N/m].
virtual scalar hs(scalar p, scalar T) const =0
Liquid sensible enthalpy [J/kg].
Base class for fv patches that provide mapping between two fv patches.
const fvMesh & nbrMesh() const
Get the mesh for the region to map from.
Thermo package for (S)olids (L)iquids and (G)ases Takes reference to thermo package,...
label index() const
Return the index of this patch in the boundaryMesh.
const Vector< label > & solutionD() const
Return the vector of solved-for directions in mesh.
A patch is a list of labels that address the faces in the global face list.
label whichFace(const label l) const
Return label of face in patch from global face label.
const dictionary & coeffDict() const
Return const access to the coefficients dictionary.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const fvPatchList & patches
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
const scalar twoPi(2 *pi)
const dimensionedScalar sigma
Stefan-Boltzmann constant: default SI units: [W/m^2/K^4].
const dimensionedScalar mu
Atomic mass unit.
dimensionedScalar exp(const dimensionedScalar &ds)
bool read(const char *, int32_t &)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensionedScalar pow3(const dimensionedScalar &ds)
errorManip< error > abort(error &err)
dimensionedScalar sin(const dimensionedScalar &ds)
dimensionedScalar log(const dimensionedScalar &ds)
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
dimensionedScalar sqrt(const dimensionedScalar &ds)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
dimensionSet normalised(const dimensionSet &)
dimensioned< scalar > mag(const dimensioned< Type > &)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
dimensionedScalar cbrt(const dimensionedScalar &ds)
dimensionSet perpendicular(const dimensionSet &)
dimensioned< scalar > magSqr(const dimensioned< Type > &)
dimensionedScalar cos(const dimensionedScalar &ds)
dimensionedScalar acos(const dimensionedScalar &ds)
randomGenerator rndGen(653213)
fluidMulticomponentThermo & thermo