39 template<
class CloudType>
42 "absorb",
"bounce",
"splashBai" 48 template<
class CloudType>
52 forAll(interactionTypeNames_, i)
54 if (interactionTypeNames_[i] == it)
56 return interactionType(i);
61 <<
"Unknown interaction type " << it
62 <<
". Valid interaction types include: " << interactionTypeNames_
69 template<
class CloudType>
72 const interactionType& it
75 if (it >= interactionTypeNames_.size())
81 return interactionTypeNames_[it];
87 template<
class CloudType>
94 scalar magTangent = 0.0;
96 while (magTangent < SMALL)
99 tangent = vTest - (vTest & v)*v;
100 magTangent =
mag(tangent);
103 return tangent/magTangent;
107 template<
class CloudType>
116 const scalar phiSi =
twoPi*rndGen_.sample01<scalar>();
119 const scalar thetaSi =
degToRad(rndGen_.sample01<scalar>()*(50 - 5) + 5);
123 const scalar dcorr =
cos(thetaSi);
128 return dirVec/
mag(dirVec);
132 template<
class CloudType>
141 mesh.
time().objectRegistry::template getObjectPtr<regionFilm>
143 "surfaceFilmProperties" 148 if (areaFilms_.empty())
152 mesh.
time().objectRegistry::template sorted<areaFilm>()
155 for (
const auto& model : models)
157 areaFilms_.append(const_cast<areaFilm*>(&model));
163 template<
class CloudType>
168 this->coeffDict().readEntry(
"pRef", pRef_);
169 this->coeffDict().readEntry(
"TRef", TRef_);
175 template<
class CloudType>
176 template<
class filmType>
187 DebugInfo<<
"Parcel " <<
p.origId() <<
" absorbInteraction" <<
endl;
193 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
214 this->nParcelsTransferred()++;
216 this->totalMassTransferred() += mass;
218 keepParticle =
false;
222 template<
class CloudType>
231 DebugInfo<<
"Parcel " <<
p.origId() <<
" bounceInteraction" <<
endl;
237 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
243 p.U() -= 2.0*nf*(
Urel & nf);
249 template<
class CloudType>
250 template<
class filmType>
262 DebugInfo<<
"Parcel " <<
p.origId() <<
" drySplashInteraction" <<
endl;
265 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
272 const scalar m =
p.mass()*
p.nParticle();
273 const scalar
rho =
p.rho();
274 const scalar d =
p.d();
285 const scalar Wec = Adry_*
pow(La, -0.183);
289 absorbInteraction<filmType>
290 (filmModel,
p, pp, facei, m, keepParticle);
295 const scalar mRatio = 0.2 + 0.6*rndGen_.sample01<scalar>();
296 splashInteraction<filmType>
297 (filmModel,
p, pp, facei, mRatio, We, Wec,
sigma, keepParticle);
302 template<
class CloudType>
303 template<
class filmType>
315 DebugInfo<<
"Parcel " <<
p.origId() <<
" wetSplashInteraction" <<
endl;
318 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
322 const scalar m =
p.mass()*
p.nParticle();
323 const scalar
rho =
p.rho();
324 const scalar d =
p.d();
337 const scalar Wec = Awet_*
pow(La, -0.183);
341 absorbInteraction<filmType>
342 (filmModel,
p, pp, facei, m, keepParticle);
344 else if ((We >= 2) && (We < 20))
350 const scalar
epsilon = 0.993 - theta*(1.76 - theta*(1.56 - theta*0.49));
358 else if ((We >= 20) && (We < Wec))
360 absorbInteraction<filmType>
361 (filmModel,
p, pp, facei, m, keepParticle);
367 const scalar mRatio = 0.2 + 0.9*rndGen_.sample01<scalar>();
368 splashInteraction<filmType>
369 (filmModel,
p, pp, facei, mRatio, We, Wec,
sigma, keepParticle);
374 template<
class CloudType>
375 template<
class filmType>
391 const vector& Up = this->owner().U().boundaryField()[pp.
index()][facei];
395 const vector tanVec1(tangentVector(nf));
396 const vector tanVec2(nf^tanVec1);
399 const scalar np =
p.nParticle();
400 const scalar m =
p.mass()*np;
401 const scalar d =
p.d();
409 const scalar mSplash = m*mRatio;
412 const scalar Ns = 5.0*(We/Wec - 1.0);
415 const scalar dBarSplash = 1/
cbrt(6.0)*
cbrt(mRatio/Ns)*d + ROOTVSMALL;
418 const scalar dMax = 0.9*
cbrt(mRatio)*d;
419 const scalar dMin = 0.1*dMax;
420 const scalar
K =
exp(-dMin/dBarSplash) -
exp(-dMax/dBarSplash);
423 scalar ESigmaSec = 0;
430 const scalar
y = rndGen_.sample01<scalar>();
431 dNew[i] = -dBarSplash*
log(
exp(-dMin/dBarSplash) -
y*
K);
432 npNew[i] = mRatio*np*
pow3(d)/
pow3(dNew[i])/parcelsPerSplash_;
433 ESigmaSec += npNew[i]*
sigma*
p.areaS(dNew[i]);
437 const scalar EKIn = 0.5*m*
magSqr(Un);
440 const scalar ESigmaIn = np*
sigma*
p.areaS(d);
446 const scalar EKs = EKIn + ESigmaIn - ESigmaSec - Ed;
451 absorbInteraction<filmType>
452 (filmModel,
p, pp, facei, m, keepParticle);
457 const scalar logD =
log(d);
458 const scalar coeff2 =
log(dNew[0]) - logD + ROOTVSMALL;
462 coeff1 +=
sqr(
log(dNew[i]) - logD);
466 const scalar magUns0 =
467 sqrt(2.0*parcelsPerSplash_*EKs/mSplash/(1.0 + coeff1/
sqr(coeff2)));
472 const vector dirVec = splashDirection(tanVec1, tanVec2, -nf);
475 parcelType* pPtr =
new parcelType(
p);
477 pPtr->origId() = pPtr->getNewParticleID();
481 if (splashParcelType_ >= 0)
483 pPtr->typeId() = splashParcelType_;
487 pPtr->track(0.5*rndGen_.sample01<scalar>()*(posC - posCf), 0);
489 pPtr->nParticle() = npNew[i];
493 pPtr->U() = dirVec*(
mag(Cf_*Ut) + magUns0*(
log(dNew[i]) - logD)/coeff2);
499 this->owner().addParticle(pPtr);
506 const scalar mDash = m - mSplash;
507 absorbInteraction<filmType>
508 (filmModel,
p, pp, facei, mDash, keepParticle);
514 template<
class CloudType>
530 interactionTypeEnum(this->coeffDict().getWord(
"interactionType"))
532 parcelTypes_(this->coeffDict().getOrDefault(
"parcelTypes",
labelList())),
534 splashParcelType_(0),
535 parcelsPerSplash_(0),
542 <<
" interaction model" <<
endl;
559 template<
class CloudType>
567 rndGen_(sfm.rndGen_),
571 interactionType_(sfm.interactionType_),
572 parcelTypes_(sfm.parcelTypes_),
573 deltaWet_(sfm.deltaWet_),
574 splashParcelType_(sfm.splashParcelType_),
575 parcelsPerSplash_(sfm.parcelsPerSplash_),
579 nParcelsSplashed_(sfm.nParcelsSplashed_)
590 template<
class CloudType>
598 if (parcelTypes_.size() && parcelTypes_.find(
p.typeId()) == -1)
602 Pout<<
"transferParcel: ignoring particle with typeId=" 610 const label patchi = pp.
index();
611 const label meshFacei =
p.face();
612 const label facei = pp.
whichFace(meshFacei);
617 if (this->filmModel_ && this->filmModel_->isRegionPatch(patchi))
619 auto& film = *filmModel_;
621 switch (interactionType_)
625 bounceInteraction(
p, pp, facei, keepParticle);
632 const scalar m =
p.nParticle()*
p.mass();
634 absorbInteraction<regionFilm>
635 (film,
p, pp, facei, m, keepParticle);
643 const scalar
mu = thermo_->mu(pRef_, TRef_, X);
644 const scalar
sigma = thermo_->sigma(pRef_, TRef_, X);
648 this->deltaFilmPatch_[patchi][facei] < deltaWet_
653 drySplashInteraction<regionFilm>
654 (film,
sigma,
mu,
p, pp, facei, keepParticle);
658 wetSplashInteraction<regionFilm>
659 (film,
sigma,
mu,
p, pp, facei, keepParticle);
668 <<
"Unknown interaction type enumeration" 679 for (areaFilm& film : this->areaFilms_)
681 const label filmFacei
694 switch (interactionType_)
698 bounceInteraction(
p, pp, facei, keepParticle);
705 const scalar m =
p.nParticle()*
p.mass();
707 absorbInteraction<areaFilm>
709 film,
p, pp, facei, m, keepParticle
724 const scalar pRef = film.
pRef();
725 const scalar
TRef = liqFilm.Tref();
727 const scalar
mu = liqFilm.thermo().mu(pRef,
TRef, X);
729 liqFilm.thermo().sigma(pRef,
TRef, X);
733 film.
h()[filmFacei] < this->deltaWet_
738 drySplashInteraction<areaFilm>
739 (film,
sigma,
mu,
p, pp, facei, keepParticle);
743 wetSplashInteraction<areaFilm>
744 (film,
sigma,
mu,
p, pp, facei, keepParticle);
753 <<
"Unknown interaction type enumeration" 767 template<
class CloudType>
770 const label filmPatchi,
771 const label primaryPatchi,
784 template<
class CloudType>
794 template<
class CloudType>
798 const label filmFacei
805 template<
class CloudType>
810 label nSplash0 = this->
template getModelProperty<label>(
"nParcelsSplashed");
814 Log_<<
" - new splash parcels = " << nSplashTotal <<
endl;
816 if (this->writeTime())
818 this->setModelProperty(
"nParcelsSplashed", nSplashTotal);
819 nParcelsSplashed_ = 0;
interactionType interactionType_
Interaction type enumeration.
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.
label whichFace(const label facei) const noexcept
Return label of face in patch from global face label.
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.
word interactionTypeStr(const interactionType &it) const
Return word from interaction type enum.
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) that generates FatalError on failed casts, uses the virtual type() me...
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)
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)
Number of this process (starting from masterNo() = 0)
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.
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.
Mesh data needed to do the Finite Volume discretisation.
messageStream Info
Information stream (stdout output on master, null elsewhere)
dimensionedScalar TRef("TRef", dimTemperature, laminarTransport)
label parcelsPerSplash_
Number of new parcels resulting from splash event.
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.
label index() const noexcept
The index of this patch in the boundaryMesh.
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.
interactionType interactionTypeEnum(const word &it) const
Return interaction type enum from word.
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.
static wordList interactionTypeNames_
Names for interactionType.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
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)