35 template<
class CloudType>
40 "(absorb bounce splashBai)" 47 template<
class CloudType>
51 forAll(interactionTypeNames_, i)
53 if (interactionTypeNames_[i] == it)
61 "ThermoSurfaceFilm<CloudType>::interactionType " 62 "ThermoSurfaceFilm<CloudType>::interactionTypeEnum" 66 ) <<
"Unknown interaction type " << it
67 <<
". Valid interaction types include: " << interactionTypeNames_
74 template<
class CloudType>
80 if (it >= interactionTypeNames_.size())
84 "ThermoSurfaceFilm<CloudType>::interactionType " 85 "ThermoSurfaceFilm<CloudType>::interactionTypeStr" 87 "const interactionType& it" 92 return interactionTypeNames_[it];
96 template<
class CloudType>
103 scalar magTangent = 0.0;
105 while (magTangent < SMALL)
108 tangent = vTest - (vTest & v)*v;
109 magTangent =
mag(tangent);
112 return tangent/magTangent;
116 template<
class CloudType>
125 const scalar phiSi =
twoPi*rndGen_.sample01<scalar>();
128 const scalar thetaSi =
pi/180.0*(rndGen_.sample01<scalar>()*(50 - 5) + 5);
132 const scalar dcorr =
cos(thetaSi);
137 return dirVec/
mag(dirVec);
141 template<
class CloudType>
154 Info<<
"Parcel " << p.origId() <<
" absorbInteraction" <<
endl;
161 const vector& Up = this->owner().U().boundaryField()[pp.
index()][faceI];
167 const vector Un = nf*(Urel & nf);
170 const vector Ut = Urel - Un;
182 this->nParcelsTransferred()++;
184 keepParticle =
false;
188 template<
class CloudType>
199 Info<<
"Parcel " << p.origId() <<
" bounceInteraction" <<
endl;
206 const vector& Up = this->owner().U().boundaryField()[pp.
index()][faceI];
212 p.U() -= 2.0*nf*(Urel & nf);
218 template<
class CloudType>
230 Info<<
"Parcel " << p.origId() <<
" drySplashInteraction" <<
endl;
236 const vector& Up = this->owner().U().boundaryField()[pp.
index()][faceI];
240 const scalar pc = thermo_.thermo().p()[p.cell()];
243 const scalar m = p.mass()*p.nParticle();
244 const scalar
rho = p.rho();
245 const scalar d = p.d();
246 const scalar sigma = liq.
sigma(pc, p.T());
247 const scalar
mu = liq.
mu(pc, p.T());
249 const vector Un = nf*(Urel & nf);
252 const scalar La = rho*sigma*d/
sqr(mu);
258 const scalar Wec = Adry_*
pow(La, -0.183);
262 absorbInteraction(filmModel, p, pp, faceI, m, keepParticle);
267 const scalar mRatio = 0.2 + 0.6*rndGen_.sample01<scalar>();
269 (filmModel, p, pp, faceI, mRatio, We, Wec, sigma, keepParticle);
274 template<
class CloudType>
286 Info<<
"Parcel " << p.origId() <<
" wetSplashInteraction" <<
endl;
292 const vector& Up = this->owner().U().boundaryField()[pp.
index()][faceI];
296 const scalar pc = thermo_.thermo().p()[p.cell()];
299 const scalar m = p.mass()*p.nParticle();
300 const scalar
rho = p.rho();
301 const scalar d = p.d();
303 const scalar sigma = liq.
sigma(pc, p.T());
304 const scalar
mu = liq.
mu(pc, p.T());
306 const vector Un = nf*(Urel & nf);
307 const vector Ut = Urel - Un;
310 const scalar La = rho*sigma*d/
sqr(mu);
316 const scalar Wec = Awet_*
pow(La, -0.183);
320 absorbInteraction(filmModel, p, pp, faceI, m, keepParticle);
322 else if ((We >= 1) && (We < 20))
325 const scalar theta =
pi/2 -
acos(U/
mag(U) & nf);
328 const scalar
epsilon = 0.993 - theta*(1.76 - theta*(1.56 - theta*0.49));
331 U = -epsilon*(Un) + 5/7*(Ut);
336 else if ((We >= 20) && (We < Wec))
338 absorbInteraction(filmModel, p, pp, faceI, m, keepParticle);
344 const scalar mRatio = 0.2 + 0.9*rndGen_.sample01<scalar>();
346 (filmModel, p, pp, faceI, mRatio, We, Wec, sigma, keepParticle);
351 template<
class CloudType>
367 const vector& Up = this->owner().U().boundaryField()[pp.
index()][faceI];
371 const vector tanVec1 = tangentVector(nf);
372 const vector tanVec2 = nf^tanVec1;
375 const scalar np = p.nParticle();
376 const scalar m = p.mass()*np;
377 const scalar d = p.d();
379 const vector Un = nf*(Urel & nf);
380 const vector Ut = Urel - Un;
381 const vector& posC = mesh.
C()[p.cell()];
385 const scalar mSplash = m*mRatio;
388 const scalar Ns = 5.0*(We/Wec - 1.0);
391 const scalar dBarSplash = 1/
cbrt(6.0)*
cbrt(mRatio/Ns)*d + ROOTVSMALL;
394 const scalar dMax = 0.9*
cbrt(mRatio)*d;
395 const scalar dMin = 0.1*dMax;
396 const scalar
K =
exp(-dMin/dBarSplash) -
exp(-dMax/dBarSplash);
399 scalar ESigmaSec = 0;
406 const scalar
y = rndGen_.sample01<scalar>();
407 dNew[i] = -dBarSplash*
log(
exp(-dMin/dBarSplash) - y*K);
408 npNew[i] = mRatio*np*
pow3(d)/
pow3(dNew[i])/parcelsPerSplash_;
409 ESigmaSec += npNew[i]*sigma*p.areaS(dNew[i]);
413 const scalar EKIn = 0.5*m*
magSqr(Urel);
416 const scalar ESigmaIn = np*sigma*p.areaS(d);
419 const scalar Ed =
max(0.8*EKIn, np*Wec/12*
pi*sigma*
sqr(d));
422 const scalar EKs = EKIn + ESigmaIn - ESigmaSec - Ed;
427 absorbInteraction(filmModel, p, pp, faceI, m, keepParticle);
432 const scalar logD =
log(d);
433 const scalar coeff2 =
log(dNew[0]) - logD + ROOTVSMALL;
437 coeff1 +=
sqr(
log(dNew[i]) - logD);
441 const scalar magUns0 =
442 sqrt(2.0*parcelsPerSplash_*EKs/mSplash/(1.0 + coeff1/
sqr(coeff2)));
447 const vector dirVec = splashDirection(tanVec1, tanVec2, -nf);
452 pPtr->origId() = pPtr->getNewParticleID();
456 if (splashParcelType_ >= 0)
458 pPtr->typeId() = splashParcelType_;
462 pPtr->position() += 0.5*rndGen_.sample01<scalar>()*(posC - posCf);
464 pPtr->nParticle() = npNew[i];
468 pPtr->U() = dirVec*(
mag(Cf_*Ut) + magUns0*(
log(dNew[i]) - logD)/coeff2);
474 this->owner().addParticle(pPtr);
481 const scalar mDash = m - mSplash;
482 absorbInteraction(filmModel, p, pp, faceI, mDash, keepParticle);
488 template<
class CloudType>
496 rndGen_(owner.rndGen()),
499 owner.db().objectRegistry::template lookupObject<SLGThermo>(
"SLGThermo")
505 interactionTypeEnum(this->coeffDict().
lookup(
"interactionType"))
508 splashParcelType_(0),
509 parcelsPerSplash_(0),
515 Info<<
" Applying " << interactionTypeStr(interactionType_)
516 <<
" interaction model" <<
endl;
518 if (interactionType_ == itSplashBai)
520 this->coeffDict().lookup(
"deltaWet") >> deltaWet_;
522 this->coeffDict().lookupOrDefault(
"splashParcelType", -1);
524 this->coeffDict().lookupOrDefault(
"parcelsPerSplash", 2);
525 this->coeffDict().lookup(
"Adry") >> Adry_;
526 this->coeffDict().lookup(
"Awet") >> Awet_;
527 this->coeffDict().lookup(
"Cf") >> Cf_;
532 template<
class CloudType>
556 template<
class CloudType>
563 template<
class CloudType>
575 this->owner().db().time().objectRegistry::template
576 lookupObject<regionModels::surfaceFilmModels::surfaceFilmModel>
578 "surfaceFilmProperties" 588 switch (interactionType_)
592 bounceInteraction(p, pp, faceI, keepParticle);
598 const scalar m = p.nParticle()*p.mass();
599 absorbInteraction(filmModel, p, pp, faceI, m, keepParticle);
605 bool dry = this->deltaFilmPatch_[patchI][faceI] < deltaWet_;
609 drySplashInteraction(filmModel, p, pp, faceI, keepParticle);
613 wetSplashInteraction(filmModel, p, pp, faceI, keepParticle);
622 "bool ThermoSurfaceFilm<CloudType>::transferParcel" 628 ) <<
"Unknown interaction type enumeration" 642 template<
class CloudType>
645 const label filmPatchI,
646 const label primaryPatchI,
658 filmModel.
toPrimary(filmPatchI, TFilmPatch_);
661 filmModel.
toPrimary(filmPatchI, CpFilmPatch_);
665 template<
class CloudType>
669 const label filmFaceI
675 p.T() = TFilmPatch_[filmFaceI];
676 p.Cp() = CpFilmPatch_[filmFaceI];
680 template<
class CloudType>
685 label nSplash0 = this->
template getModelProperty<label>(
"nParcelsSplashed");
689 os <<
" New film splash parcels = " << nSplashTotal <<
endl;
691 if (this->outputTime())
693 this->setModelProperty(
"nParcelsSplashed", nSplashTotal);
694 nParcelsSplashed_ = 0;
Templated wall surface film model class.
dimensionedScalar sqrt(const dimensionedScalar &ds)
dimensionedScalar pow3(const dimensionedScalar &ds)
The thermophysical properties of a liquidProperties.
const dimensionedScalar mu
Atomic mass unit.
Mesh data needed to do the Finite Volume discretisation.
CloudType::parcelType parcelType
Convenience typedef to the cloud's parcel type.
vector splashDirection(const vector &tanVec1, const vector &tanVec2, const vector &nf) const
Return splashed parcel direction.
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
dimensioned< scalar > mag(const dimensioned< Type > &)
GeometricBoundaryField & boundaryField()
Return reference to GeometricBoundaryField.
CGAL::Exact_predicates_exact_constructions_kernel K
void bounceInteraction(parcelType &p, const polyPatch &pp, const label faceI, bool &keepParticle) const
Bounce parcel (flip parcel normal velocity)
static wordList interactionTypeNames_
Word descriptions of interaction type names.
ThermoSurfaceFilm(const dictionary &dict, CloudType &owner)
Construct from components.
const dimensionedScalar sigma
Stefan-Boltzmann constant: default SI units: [W/m2/K4].
dimensioned< scalar > magSqr(const dimensioned< Type > &)
const Vector< label > & solutionD() const
Return the vector of solved-for directions in mesh.
virtual bool transferParcel(parcelType &p, const polyPatch &pp, bool &keepParticle)
Transfer parcel from cloud to surface film.
label index() const
Return the index of this patch in the boundaryMesh.
A class for handling words, derived from string.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
dimensionedScalar cbrt(const dimensionedScalar &ds)
dimensionedScalar exp(const dimensionedScalar &ds)
virtual void setParcelProperties(parcelType &p, const label filmFaceI) const
Set the individual parcel properties.
const surfaceVectorField & Cf() const
Return face centres as surfaceVectorField.
virtual const volScalarField & Ts() const =0
Return the film surface temperature [K].
scalar Adry_
Dry surface roughness coefficient.
A list of keyword definitions, which are a keyword followed by any number of values (e...
void absorbInteraction(regionModels::surfaceFilmModels::surfaceFilmModel &filmModel, const parcelType &p, const polyPatch &pp, const label faceI, const scalar mass, bool &keepParticle)
Absorb parcel into film.
cachedRandom & rndGen_
Reference to the cloud random number generator.
A patch is a list of labels that address the faces in the global face list.
dimensionedScalar log(const dimensionedScalar &ds)
scalarList CpFilmPatch_
Film specific heat capacity / patch face.
Ostream & endl(Ostream &os)
Add newline and flush stream.
stressControl lookup("compactNormalStress") >> compactNormalStress
void constrainDirection(const polyMesh &mesh, const Vector< label > &dirs, vector &d)
Set the constrained components of directions/velocity to zero.
const volVectorField & C() const
Return cell centres as volVectorField.
virtual void cacheFilmFields(const label filmPatchI, const label primaryPatchI, const regionModels::surfaceFilmModels::surfaceFilmModel &filmModel)
Cache the film fields in preparation for injection.
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
void wetSplashInteraction(regionModels::surfaceFilmModels::surfaceFilmModel &filmModel, parcelType &p, const polyPatch &pp, const label faceI, bool &keepParticle)
Parcel interaction with wetted surface.
virtual void cacheFilmFields(const label filmPatchI, const label primaryPatchI, const regionModels::surfaceFilmModels::surfaceFilmModel &filmModel)
Cache the film fields in preparation for injection.
dimensionedScalar cos(const dimensionedScalar &ds)
interactionType interactionType_
Interaction type enumeration.
void splashInteraction(regionModels::surfaceFilmModels::surfaceFilmModel &filmModel, 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.
void drySplashInteraction(regionModels::surfaceFilmModels::surfaceFilmModel &filmModel, const parcelType &p, const polyPatch &pp, const label faceI, bool &keepParticle)
Parcel interaction with dry surface.
Macros for easy insertion into run-time selection tables.
dimensionedScalar acos(const dimensionedScalar &ds)
errorManip< error > abort(error &err)
const Field< PointType > & faceNormals() const
Return face normals for patch.
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
virtual void setParcelProperties(parcelType &p, const label filmFaceI) const
Set the individual parcel properties.
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
virtual void info(Ostream &os)
Write surface film info to stream.
label nParcelsSplashed_
Counter for number of new splash parcels.
label parcelsPerSplash_
Number of new parcels resulting from splash event.
const SLGThermo & thermo_
Reference to the cloud thermo package.
virtual void addSources(const label patchI, const label faceI, const scalar massSource, const vector &momentumSource, const scalar pressureSource, const scalar energySource)=0
External hook to add sources to the film.
bool isRegionPatch(const label primaryPatchI) const
Return true if patchI on the primary region is a coupled.
scalar Awet_
Wet surface roughness coefficient.
A normal distribution model.
scalarList TFilmPatch_
Film temperature / patch face.
Base class for surface film models.
vector tangentVector(const vector &v) const
Return a vector tangential to input vector, v.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
scalar deltaWet_
Film thickness beyond which patch is assumed to be wet.
scalar Cf_
Skin friction typically in the range 0.6 < Cf < 0.8.
Templated base class for dsmc cloud.
word interactionTypeStr(const interactionType &it) const
virtual scalar mu(scalar p, scalar T) const
Liquid viscosity [Pa s].
interactionType interactionTypeEnum(const word &it) const
virtual void info(Ostream &os)
Write surface film info to stream.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
virtual const volScalarField & Cp() const =0
Return the film specific heat capacity [J/kg/K].
const scalar twoPi(2 *pi)
virtual ~ThermoSurfaceFilm()
Destructor.
void toPrimary(const label regionPatchI, List< Type > ®ionField) const
Convert a local region field to the primary region.
virtual scalar sigma(scalar p, scalar T) const
Surface tension [N/m].
label whichFace(const label l) const
Return label of face in patch from global face label.
Thermo parcel surface film model.
label splashParcelType_
Splash parcel type label - id assigned to identify parcel for.
dimensionedScalar sin(const dimensionedScalar &ds)