39 template<
class CloudType>
46 { interactionType::absorb,
"absorb" },
47 { interactionType::bounce,
"bounce" },
48 { interactionType::splashBai,
"splashBai" },
54 template<
class CloudType>
61 scalar magTangent = 0.0;
63 while (magTangent < SMALL)
66 tangent = vTest - (vTest & v)*v;
67 magTangent =
mag(tangent);
70 return tangent/magTangent;
74 template<
class CloudType>
83 const scalar phiSi =
twoPi*rndGen_.sample01<scalar>();
86 const scalar thetaSi =
degToRad(rndGen_.sample01<scalar>()*(50 - 5) + 5);
90 const scalar dcorr =
cos(thetaSi);
95 return dirVec/
mag(dirVec);
99 template<
class CloudType>
108 mesh.
time().objectRegistry::template getObjectPtr<regionFilm>
110 "surfaceFilmProperties" 115 if (areaFilms_.empty())
119 mesh.
time().objectRegistry::template sorted<areaFilm>()
122 for (
const auto& model : models)
124 areaFilms_.append(const_cast<areaFilm*>(&model));
130 template<
class CloudType>
135 this->coeffDict().readEntry(
"pRef", pRef_);
136 this->coeffDict().readEntry(
"TRef", TRef_);
142 template<
class CloudType>
143 template<
class filmType>
154 DebugInfo<<
"Parcel " <<
p.origId() <<
" absorbInteraction" <<
endl;
160 const vector& Up = this->owner().U().boundaryField()[
pp.index()][facei];
181 this->nParcelsTransferred()++;
183 this->totalMassTransferred() += mass;
185 keepParticle =
false;
189 template<
class CloudType>
198 DebugInfo<<
"Parcel " <<
p.origId() <<
" bounceInteraction" <<
endl;
204 const vector& Up = this->owner().U().boundaryField()[
pp.index()][facei];
210 p.U() -= 2.0*nf*(
Urel & nf);
216 template<
class CloudType>
217 template<
class filmType>
229 DebugInfo<<
"Parcel " <<
p.origId() <<
" drySplashInteraction" <<
endl;
232 const vector& Up = this->owner().U().boundaryField()[
pp.index()][facei];
239 const scalar m =
p.mass()*
p.nParticle();
240 const scalar
rho =
p.rho();
241 const scalar d =
p.d();
252 const scalar Wec = Adry_*
pow(La, -0.183);
256 absorbInteraction<filmType>
257 (filmModel,
p,
pp, facei, m, keepParticle);
262 const scalar mRatio = 0.2 + 0.6*rndGen_.sample01<scalar>();
263 splashInteraction<filmType>
264 (filmModel,
p,
pp, facei, mRatio, We, Wec,
sigma, keepParticle);
269 template<
class CloudType>
270 template<
class filmType>
282 DebugInfo<<
"Parcel " <<
p.origId() <<
" wetSplashInteraction" <<
endl;
285 const vector& Up = this->owner().U().boundaryField()[
pp.index()][facei];
289 const scalar m =
p.mass()*
p.nParticle();
290 const scalar
rho =
p.rho();
291 const scalar d =
p.d();
304 const scalar Wec = Awet_*
pow(La, -0.183);
308 absorbInteraction<filmType>
309 (filmModel,
p,
pp, facei, m, keepParticle);
311 else if ((We >= 2) && (We < 20))
317 const scalar
epsilon = 0.993 - theta*(1.76 - theta*(1.56 - theta*0.49));
325 else if ((We >= 20) && (We < Wec))
327 absorbInteraction<filmType>
328 (filmModel,
p,
pp, facei, m, keepParticle);
334 const scalar mRatio = 0.2 + 0.9*rndGen_.sample01<scalar>();
335 splashInteraction<filmType>
336 (filmModel,
p,
pp, facei, mRatio, We, Wec,
sigma, keepParticle);
341 template<
class CloudType>
342 template<
class filmType>
358 const vector& Up = this->owner().U().boundaryField()[
pp.index()][facei];
362 const vector tanVec1(tangentVector(nf));
363 const vector tanVec2(nf^tanVec1);
366 const scalar np =
p.nParticle();
367 const scalar m =
p.mass()*np;
368 const scalar d =
p.d();
376 const scalar mSplash = m*mRatio;
379 const scalar Ns = 5.0*(We/Wec - 1.0);
382 const scalar dBarSplash = 1/
cbrt(6.0)*
cbrt(mRatio/Ns)*d + ROOTVSMALL;
385 const scalar dMax = dMaxSplash_ > 0 ? dMaxSplash_ : 0.9*
cbrt(mRatio)*d;
386 const scalar dMin = dMinSplash_ > 0 ? dMinSplash_ : 0.1*dMax;
387 const scalar
K =
exp(-dMin/dBarSplash) -
exp(-dMax/dBarSplash);
390 scalar ESigmaSec = 0;
397 const scalar
y = rndGen_.sample01<scalar>();
398 dNew[i] = -dBarSplash*
log(
exp(-dMin/dBarSplash) -
y*
K);
399 npNew[i] = mRatio*np*
pow3(d)/
pow3(dNew[i])/parcelsPerSplash_;
400 ESigmaSec += npNew[i]*
sigma*
p.areaS(dNew[i]);
404 const scalar EKIn = 0.5*m*
magSqr(Un);
407 const scalar ESigmaIn = np*
sigma*
p.areaS(d);
413 const scalar EKs = EKIn + ESigmaIn - ESigmaSec - Ed;
418 absorbInteraction<filmType>
419 (filmModel,
p,
pp, facei, m, keepParticle);
424 const scalar logD =
log(d);
425 const scalar coeff2 =
log(dNew[0]) - logD + ROOTVSMALL;
429 for (
int i = 1; i < parcelsPerSplash_; ++i)
431 coeff1 +=
sqr(
log(dNew[i]) - logD);
435 const scalar magUns0 =
436 sqrt(2.0*parcelsPerSplash_*EKs/mSplash/(1.0 + coeff1/
sqr(coeff2)));
441 const vector dirVec = splashDirection(tanVec1, tanVec2, -nf);
444 parcelType* pPtr =
new parcelType(
p);
446 pPtr->origId() = pPtr->getNewParticleID();
450 if (splashParcelType_ >= 0)
452 pPtr->typeId() = splashParcelType_;
456 pPtr->track(0.5*rndGen_.sample01<scalar>()*(posC - posCf), 0);
458 pPtr->nParticle() = npNew[i];
462 pPtr->U() = dirVec*(
mag(Cf_*Ut) + magUns0*(
log(dNew[i]) - logD)/coeff2);
468 this->owner().addParticle(pPtr);
475 const scalar mDash = m - mSplash;
476 absorbInteraction<filmType>
477 (filmModel,
p,
pp, facei, mDash, keepParticle);
483 template<
class CloudType>
499 interactionTypeNames.
get(
"interactionType", this->coeffDict())
501 parcelTypes_(this->coeffDict().getOrDefault(
"parcelTypes",
labelList())),
503 splashParcelType_(0),
504 parcelsPerSplash_(0),
513 <<
" interaction model" <<
endl;
533 template<
class CloudType>
541 rndGen_(sfm.rndGen_),
545 interactionType_(sfm.interactionType_),
546 parcelTypes_(sfm.parcelTypes_),
547 deltaWet_(sfm.deltaWet_),
548 splashParcelType_(sfm.splashParcelType_),
549 parcelsPerSplash_(sfm.parcelsPerSplash_),
550 dMaxSplash_(sfm.dMaxSplash_),
551 dMinSplash_(sfm.dMinSplash_),
555 nParcelsSplashed_(sfm.nParcelsSplashed_)
566 template<
class CloudType>
574 if (parcelTypes_.size() && parcelTypes_.find(
p.typeId()) == -1)
578 Pout<<
"transferParcel: ignoring particle with typeId=" 586 const label patchi =
pp.index();
587 const label meshFacei =
p.face();
588 const label facei =
pp.whichFace(meshFacei);
593 if (this->filmModel_ && this->filmModel_->isRegionPatch(patchi))
595 auto& film = *filmModel_;
597 switch (interactionType_)
599 case interactionType::bounce:
601 bounceInteraction(
p,
pp, facei, keepParticle);
606 case interactionType::absorb:
608 const scalar m =
p.nParticle()*
p.mass();
610 absorbInteraction<regionFilm>
611 (film,
p,
pp, facei, m, keepParticle);
616 case interactionType::splashBai:
619 const scalar
mu = thermo_->mu(pRef_, TRef_, X);
620 const scalar
sigma = thermo_->sigma(pRef_, TRef_, X);
624 this->deltaFilmPatch_[patchi][facei] < deltaWet_
629 drySplashInteraction<regionFilm>
630 (film,
sigma,
mu,
p,
pp, facei, keepParticle);
634 wetSplashInteraction<regionFilm>
635 (film,
sigma,
mu,
p,
pp, facei, keepParticle);
644 <<
"Unknown interaction type enumeration" 655 for (areaFilm& film : this->areaFilms_)
657 const label filmFacei
670 switch (interactionType_)
672 case interactionType::bounce:
674 bounceInteraction(
p,
pp, facei, keepParticle);
679 case interactionType::absorb:
681 const scalar m =
p.nParticle()*
p.mass();
683 absorbInteraction<areaFilm>
685 film,
p,
pp, facei, m, keepParticle
690 case interactionType::splashBai:
700 const scalar pRef = film.
pRef();
701 const scalar
TRef = liqFilm.Tref();
703 const scalar
mu = liqFilm.thermo().mu(pRef,
TRef, X);
704 const scalar
sigma = liqFilm.thermo().sigma(pRef,
TRef, X);
706 const bool dry = film.
h()[filmFacei] < this->deltaWet_;
710 drySplashInteraction<areaFilm>
711 (film,
sigma,
mu,
p,
pp, facei, keepParticle);
715 wetSplashInteraction<areaFilm>
716 (film,
sigma,
mu,
p,
pp, facei, keepParticle);
725 <<
"Unknown interaction type enumeration" 739 template<
class CloudType>
742 const label filmPatchi,
743 const label primaryPatchi,
756 template<
class CloudType>
766 template<
class CloudType>
770 const label filmFacei
777 template<
class CloudType>
782 label nSplash0 = this->
template getModelProperty<label>(
"nParcelsSplashed");
786 Log_<<
" - new splash parcels = " << nSplashTotal <<
endl;
788 if (this->writeTime())
790 this->setModelProperty(
"nParcelsSplashed", nSplashTotal);
791 nParcelsSplashed_ = 0;
interactionType interactionType_
Interaction type enumeration.
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
interactionType
Options for the interaction types.
KinematicSurfaceFilm(const dictionary &dict, CloudType &owner, const word &type=typeName, bool initThermo=true)
Construct from components.
dimensionedScalar acos(const dimensionedScalar &ds)
bool isRegionPatch(const label patchi) const
True if patchi on the primary region is coupled to this region.
void wetSplashInteraction(filmType &, const scalar sigma, const scalar mu, parcelType &p, const polyPatch &pp, const label facei, bool &keepParticle)
Parcel interaction with wetted surface.
dimensionedScalar log(const dimensionedScalar &ds)
Base class for surface film models.
scalar Adry_
Dry surface roughness coefficient.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
const areaScalarField & h() const
Access const reference h.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
scalar Cf_
Skin friction typically in the range 0.6 < Cf < 0.8.
const surfaceVectorField & Cf() const
Return face centres as surfaceVectorField.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Unit conversion functions.
const Vector< label > & solutionD() const
Return the vector of solved-for directions in mesh.
Type & refCast(U &obj)
A dynamic_cast (for references). Generates a FatalError on failed casts and uses the virtual type() m...
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
label whichFace(const label meshFacei) const
The area-face corresponding to the mesh-face, -1 if not found.
void bounceInteraction(parcelType &p, const polyPatch &pp, const label facei, bool &keepParticle) const
Bounce parcel (flip parcel normal velocity)
static const Enum< interactionType > interactionTypeNames
Names for interactionType.
void splashInteraction(filmType &, 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.
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
virtual void setParcelProperties(parcelType &p, const label filmFacei) const
Set the individual parcel properties.
const Time & time() const
Return the top-level database.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
CGAL::Exact_predicates_exact_constructions_kernel K
dimensionedScalar sigma("sigma", dimMass/sqr(dimTime), transportProperties)
Macros for easy insertion into run-time selection tables.
scalar deltaWet_
Film thickness beyond which patch is assumed to be wet.
#define forAll(list, i)
Loop across all elements in list.
void init(bool binitThermo)
Initialise thermo.
const Field< point_type > & faceNormals() const
Return face unit normals for patch.
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, IOobjectOption::readOption readOpt=IOobjectOption::MUST_READ) const
Find entry and assign to T val. FatalIOError if it is found and the number of tokens is incorrect...
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
dimensionedScalar cos(const dimensionedScalar &ds)
#define Log_
Report write to Foam::Info if the class log switch is true.
dimensionedScalar exp(const dimensionedScalar &ds)
constexpr scalar twoPi(2 *M_PI)
A class for handling words, derived from Foam::string.
vector splashDirection(const vector &tanVec1, const vector &tanVec2, const vector &nf) const
Return splashed parcel direction.
virtual void cacheFilmFields(const areaFilm &film)
Cache the film fields in preparation for injection.
dimensionedScalar cbrt(const dimensionedScalar &ds)
const faMesh & regionMesh() const
Return the region mesh database.
void absorbInteraction(filmType &, const parcelType &p, const polyPatch &pp, const label facei, const scalar mass, bool &keepParticle)
Absorb parcel into film.
constexpr scalar pi(M_PI)
constexpr scalar piByTwo(0.5 *M_PI)
const dictionary & coeffDict() const
Return const access to the coefficients dictionary.
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
errorManip< error > abort(error &err)
#define DebugInfo
Report an information message using Foam::Info.
vector tangentVector(const vector &v) const
Return a vector tangential to input vector, v.
dimensionedScalar sin(const dimensionedScalar &ds)
Kinematic parcel surface film model.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
int debug
Static debugging option.
virtual void info()
Write surface film info.
virtual bool transferParcel(parcelType &p, const polyPatch &pp, bool &keepParticle)
Transfer parcel from cloud to surface film.
void initFilmModels()
Initialise pointers of films.
scalar dMinSplash_
Minimum splash particle diameter for Chi-square distribution.
Templated wall surface film model class.
virtual void setParcelProperties(parcelType &p, const label filmFacei) const
Set the individual parcel properties.
scalar pRef()
Access to pRef.
scalar Awet_
Wet surface roughness coefficient.
const dimensionedScalar mu
Atomic mass unit.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
dimensionedScalar pow3(const dimensionedScalar &ds)
virtual void cacheFilmFields(const label filmPatchi, const label primaryPatchi, const regionFilm &)
Cache the film fields in preparation for injection.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
scalar dMaxSplash_
Maximum splash particle diameter for Chi-square distribution.
Mesh data needed to do the Finite Volume discretisation.
messageStream Info
Information stream (stdout output on master, null elsewhere)
dimensionedScalar TRef("TRef", dimTemperature, laminarTransport)
void drySplashInteraction(filmType &, const scalar sigma, const scalar mu, const parcelType &p, const polyPatch &pp, const label facei, bool &keepParticle)
Parcel interaction with dry surface.
const volVectorField & C() const
Return cell centres as volVectorField.
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
A patch is a list of labels that address the faces in the global face list.
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
Templated base class for dsmc cloud.
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
label splashParcelType_
Splash parcel type label - id assigned to identify parcel for.
virtual void info()
Write surface film info.
static constexpr const zero Zero
Global zero (0)