36 template<
class CloudType>
41 "(absorb bounce splashBai)" 48 template<
class CloudType>
52 forAll(interactionTypeNames_, i)
54 if (interactionTypeNames_[i] == it)
61 <<
"Unknown interaction type " << it
62 <<
". Valid interaction types include: " << interactionTypeNames_
69 template<
class CloudType>
75 if (it >= interactionTypeNames_.size())
81 return interactionTypeNames_[it];
87 template<
class CloudType>
96 const scalar phiSi =
twoPi*rndGen_.sample01<scalar>();
99 const scalar thetaSi =
pi/180.0*(rndGen_.sample01<scalar>()*(50 - 5) + 5);
103 const scalar dcorr =
cos(thetaSi);
104 const vector normal = alpha*(tanVec1*
cos(phiSi) + tanVec2*
sin(phiSi));
108 return dirVec/
mag(dirVec);
112 template<
class CloudType>
125 Info<<
"Parcel " << p.origId() <<
" absorbInteraction" <<
endl;
132 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
138 const vector Un = nf*(Urel & nf);
141 const vector Ut = Urel - Un;
153 this->nParcelsTransferred()++;
155 keepParticle =
false;
159 template<
class CloudType>
170 Info<<
"Parcel " << p.origId() <<
" bounceInteraction" <<
endl;
177 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
183 p.U() -= 2.0*nf*(Urel & nf);
189 template<
class CloudType>
201 Info<<
"Parcel " << p.origId() <<
" drySplashInteraction" <<
endl;
207 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
211 const scalar pc = thermo_.thermo().p()[p.cell()];
214 const scalar m = p.mass()*p.nParticle();
215 const scalar
rho = p.rho();
216 const scalar d = p.d();
217 const scalar sigma = liq.
sigma(pc, p.T());
218 const scalar
mu = liq.
mu(pc, p.T());
220 const vector Un = nf*(Urel & nf);
223 const scalar La = rho*sigma*d/
sqr(mu);
229 const scalar Wec = Adry_*
pow(La, -0.183);
233 absorbInteraction(filmModel, p, pp, facei, m, keepParticle);
238 const scalar mRatio = 0.2 + 0.6*rndGen_.sample01<scalar>();
240 (filmModel, p, pp, facei, mRatio, We, Wec, sigma, keepParticle);
245 template<
class CloudType>
257 Info<<
"Parcel " << p.origId() <<
" wetSplashInteraction" <<
endl;
263 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
267 const scalar pc = thermo_.thermo().p()[p.cell()];
270 const scalar m = p.mass()*p.nParticle();
271 const scalar
rho = p.rho();
272 const scalar d = p.d();
274 const scalar sigma = liq.
sigma(pc, p.T());
275 const scalar
mu = liq.
mu(pc, p.T());
277 const vector Un = nf*(Urel & nf);
278 const vector Ut = Urel - Un;
281 const scalar La = rho*sigma*d/
sqr(mu);
287 const scalar Wec = Awet_*
pow(La, -0.183);
291 absorbInteraction(filmModel, p, pp, facei, m, keepParticle);
293 else if ((We >= 2) && (We < 20))
296 const scalar theta =
pi/2 -
acos(U/
mag(U) & nf);
299 const scalar
epsilon = 0.993 - theta*(1.76 - theta*(1.56 - theta*0.49));
302 U = -epsilon*(Un) + 5.0/7.0*(Ut);
307 else if ((We >= 20) && (We < Wec))
309 absorbInteraction(filmModel, p, pp, facei, m, keepParticle);
315 const scalar mRatio = 0.2 + 0.9*rndGen_.sample01<scalar>();
317 (filmModel, p, pp, facei, mRatio, We, Wec, sigma, keepParticle);
322 template<
class CloudType>
338 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
343 const vector tanVec2 = nf^tanVec1;
346 const scalar np = p.nParticle();
347 const scalar m = p.mass()*np;
348 const scalar d = p.d();
350 const vector Un = nf*(Urel & nf);
351 const vector Ut = Urel - Un;
352 const vector& posC = mesh.
C()[p.cell()];
356 const scalar mSplash = m*mRatio;
359 const scalar Ns = 5.0*(We/Wec - 1.0);
362 const scalar dBarSplash = 1/
cbrt(6.0)*
cbrt(mRatio/Ns)*d + rootVSmall;
365 const scalar dMax = 0.9*
cbrt(mRatio)*d;
366 const scalar dMin = 0.1*dMax;
367 const scalar
K =
exp(-dMin/dBarSplash) -
exp(-dMax/dBarSplash);
370 scalar ESigmaSec = 0;
377 const scalar
y = rndGen_.sample01<scalar>();
378 dNew[i] = -dBarSplash*
log(
exp(-dMin/dBarSplash) - y*K);
379 npNew[i] = mRatio*np*
pow3(d)/
pow3(dNew[i])/parcelsPerSplash_;
380 ESigmaSec += npNew[i]*sigma*p.areaS(dNew[i]);
384 const scalar EKIn = 0.5*m*
magSqr(Un);
387 const scalar ESigmaIn = np*sigma*p.areaS(d);
390 const scalar Ed =
max(0.8*EKIn, np*Wec/12*
pi*sigma*
sqr(d));
393 const scalar EKs = EKIn + ESigmaIn - ESigmaSec - Ed;
398 absorbInteraction(filmModel, p, pp, facei, m, keepParticle);
403 const scalar logD =
log(d);
404 const scalar coeff2 =
log(dNew[0]) - logD + rootVSmall;
408 coeff1 +=
sqr(
log(dNew[i]) - logD);
412 const scalar magUns0 =
413 sqrt(2.0*parcelsPerSplash_*EKs/mSplash/(1.0 + coeff1/
sqr(coeff2)));
418 const vector dirVec = splashDirection(tanVec1, tanVec2, -nf);
423 pPtr->origId() = pPtr->getNewParticleID();
427 if (splashParcelType_ >= 0)
429 pPtr->typeId() = splashParcelType_;
433 pPtr->track(0.5*rndGen_.sample01<scalar>()*(posC - posCf), 0);
435 pPtr->nParticle() = npNew[i];
439 pPtr->U() = dirVec*(
mag(Cf_*Ut) + magUns0*(
log(dNew[i]) - logD)/coeff2);
445 this->owner().addParticle(pPtr);
452 const scalar mDash = m - mSplash;
453 absorbInteraction(filmModel, p, pp, facei, mDash, keepParticle);
459 template<
class CloudType>
467 rndGen_(owner.rndGen()),
470 owner.db().objectRegistry::template lookupObject<SLGThermo>(
"SLGThermo")
476 interactionTypeEnum(this->coeffDict().
lookup(
"interactionType"))
479 splashParcelType_(0),
480 parcelsPerSplash_(0),
486 Info<<
" Applying " << interactionTypeStr(interactionType_)
487 <<
" interaction model" <<
endl;
489 if (interactionType_ == itSplashBai)
491 this->coeffDict().lookup(
"deltaWet") >> deltaWet_;
493 this->coeffDict().lookupOrDefault(
"splashParcelType", -1);
495 this->coeffDict().lookupOrDefault(
"parcelsPerSplash", 2);
496 this->coeffDict().lookup(
"Adry") >> Adry_;
497 this->coeffDict().lookup(
"Awet") >> Awet_;
498 this->coeffDict().lookup(
"Cf") >> Cf_;
503 template<
class CloudType>
527 template<
class CloudType>
534 template<
class CloudType>
546 this->owner().db().time().objectRegistry::template
550 "surfaceFilmProperties" 560 switch (interactionType_)
564 bounceInteraction(p, pp, facei, keepParticle);
570 const scalar m = p.nParticle()*p.mass();
571 absorbInteraction(filmModel, p, pp, facei, m, keepParticle);
577 bool dry = this->deltaFilmPatch_[
patchi][facei] < deltaWet_;
581 drySplashInteraction(filmModel, p, pp, facei, keepParticle);
585 wetSplashInteraction(filmModel, p, pp, facei, keepParticle);
593 <<
"Unknown interaction type enumeration" 607 template<
class CloudType>
610 const label filmPatchi,
611 const label primaryPatchi,
623 refCast<const regionModels::surfaceFilmModels::thermoSingleLayer>
629 filmModel.
toPrimary(filmPatchi, TFilmPatch_);
632 filmModel.
toPrimary(filmPatchi, CpFilmPatch_);
636 template<
class CloudType>
640 const label filmFacei
646 p.T() = TFilmPatch_[filmFacei];
647 p.Cp() = CpFilmPatch_[filmFacei];
651 template<
class CloudType>
656 label nSplash0 = this->
template getModelProperty<label>(
"nParcelsSplashed");
660 os <<
" New film splash parcels = " << nSplashTotal <<
endl;
662 if (this->writeTime())
664 this->setModelProperty(
"nParcelsSplashed", nSplashTotal);
665 nParcelsSplashed_ = 0;
scalar Awet_
Wet surface roughness coefficient.
virtual void info(Ostream &os)
Write surface film info to stream.
Thermo parcel surface film model.
dimensionedScalar acos(const dimensionedScalar &ds)
virtual const volScalarField & Cp() const
Return the film specific heat capacity [J/kg/K].
#define forAll(list, i)
Loop across all elements in list.
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.
scalar Cf_
Skin friction typically in the range 0.6 < Cf < 0.8.
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 log(const dimensionedScalar &ds)
Base class for surface film models.
A list of keyword definitions, which are a keyword followed by any number of values (e...
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
virtual void setParcelProperties(parcelType &p, const label filmFacei) const
Set the individual parcel properties.
bool isRegionPatch(const label primaryPatchi) const
Return true if patchi on the primary region is a coupled.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const surfaceVectorField & Cf() const
Return face centres as surfaceVectorField.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
const dimensionedScalar & sigma
Stefan-Boltzmann constant: default SI units: [W/m^2/K^4].
const Vector< label > & solutionD() const
Return the vector of solved-for directions in mesh.
ThermoSurfaceFilm(const dictionary &dict, CloudType &owner)
Construct from components.
scalar Adry_
Dry surface roughness coefficient.
virtual ~ThermoSurfaceFilm()
Destructor.
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
scalarList TFilmPatch_
Film temperature / patch face.
CGAL::Exact_predicates_exact_constructions_kernel K
void drySplashInteraction(regionModels::surfaceFilmModels::surfaceFilmRegionModel &, 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.
virtual void info(Ostream &os)
Write surface film info to stream.
virtual scalar sigma(scalar p, scalar T) const =0
Surface tension [N/m].
void toPrimary(const label regionPatchi, List< Type > ®ionField) const
Convert a local region field to the primary region.
interactionType interactionType_
Interaction type enumeration.
void absorbInteraction(regionModels::surfaceFilmModels::surfaceFilmRegionModel &, const parcelType &p, const polyPatch &pp, const label facei, const scalar mass, bool &keepParticle)
Absorb parcel into film.
stressControl lookup("compactNormalStress") >> compactNormalStress
Form normalised(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
dimensionedScalar cos(const dimensionedScalar &ds)
dimensionedScalar exp(const dimensionedScalar &ds)
interactionType interactionTypeEnum(const word &it) const
static wordList interactionTypeNames_
Word descriptions of interaction type names.
A class for handling words, derived from string.
dimensionedScalar cbrt(const dimensionedScalar &ds)
The thermophysical properties of a liquid.
virtual void cacheFilmFields(const label filmPatchi, const label primaryPatchi, const regionModels::surfaceFilmModels::surfaceFilmRegionModel &filmModel)
Cache the film fields in preparation for injection.
virtual const volScalarField & Ts() const
Return the film surface temperature [K].
const Field< PointType > & faceNormals() const
Return face normals for patch.
errorManip< error > abort(error &err)
const SLGThermo & thermo_
Reference to the cloud thermo package.
const scalar twoPi(2 *pi)
vector splashDirection(const vector &tanVec1, const vector &tanVec2, const vector &nf) const
Return splashed parcel direction.
dimensioned< scalar > magSqr(const dimensioned< Type > &)
An Ostream is an abstract base class for all output systems (streams, files, token lists...
dimensionedScalar sin(const dimensionedScalar &ds)
virtual void setParcelProperties(parcelType &p, const label filmFacei) const
Set the individual parcel properties.
void bounceInteraction(parcelType &p, const polyPatch &pp, const label facei, bool &keepParticle) const
Bounce parcel (flip parcel normal velocity)
Vector< Cmpt > perpendicular(const Vector< Cmpt > &v)
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
dimensionedScalar pow3(const dimensionedScalar &ds)
const dimensionedScalar & mu
Atomic mass unit.
CloudType::parcelType parcelType
Convenience typedef to the cloud's parcel type.
void splashInteraction(regionModels::surfaceFilmModels::surfaceFilmRegionModel &, 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.
Mesh data needed to do the Finite Volume discretisation.
label index() const
Return the index of this patch in the boundaryMesh.
label parcelsPerSplash_
Number of new parcels resulting from splash event.
dimensioned< scalar > mag(const dimensioned< Type > &)
virtual void cacheFilmFields(const label filmPatchi, const label primaryPatchi, const regionModels::surfaceFilmModels::surfaceFilmRegionModel &)
Cache the film fields in preparation for injection.
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
label nParcelsSplashed_
Counter for number of new splash parcels.
Random & rndGen_
Reference to the cloud random number generator.
const volVectorField & C() const
Return cell centres as volVectorField.
volScalarField alpha(IOobject("alpha", runTime.timeName(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
A patch is a list of labels that address the faces in the global face list.
word interactionTypeStr(const interactionType &it) const
virtual scalar mu(scalar p, scalar T) const =0
Liquid viscosity [Pa s].
virtual bool transferParcel(parcelType &p, const polyPatch &pp, bool &keepParticle)
Transfer parcel from cloud to surface film.
void wetSplashInteraction(regionModels::surfaceFilmModels::surfaceFilmRegionModel &, parcelType &p, const polyPatch &pp, const label facei, bool &keepParticle)
Parcel interaction with wetted surface.
scalar deltaWet_
Film thickness beyond which patch is assumed to be wet.
Templated base class for dsmc cloud.
label splashParcelType_
Splash parcel type label - id assigned to identify parcel for.
scalarList CpFilmPatch_
Film specific heat capacity / patch face.
Thermodynamic form of single-cell layer surface film model.
label whichFace(const label l) const
Return label of face in patch from global face label.