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 const areaFilm& regionFa
120 :
mesh.
time().objectRegistry::template csorted<areaFilm>()
123 areaFilms_.push_back(const_cast<areaFilm*>(®ionFa));
129 template<
class CloudType>
134 this->coeffDict().readEntry(
"pRef", pRef_);
135 this->coeffDict().readEntry(
"TRef", TRef_);
141 template<
class CloudType>
142 template<
class filmType>
153 DebugInfo<<
"Parcel " <<
p.origId() <<
" absorbInteraction" <<
endl;
159 const vector& Up = this->owner().U().boundaryField()[
pp.index()][facei];
180 this->nParcelsTransferred()++;
182 this->totalMassTransferred() += mass;
184 keepParticle =
false;
188 template<
class CloudType>
197 DebugInfo<<
"Parcel " <<
p.origId() <<
" bounceInteraction" <<
endl;
203 const vector& Up = this->owner().U().boundaryField()[
pp.index()][facei];
209 p.U() -= 2.0*nf*(
Urel & nf);
215 template<
class CloudType>
216 template<
class filmType>
228 DebugInfo<<
"Parcel " <<
p.origId() <<
" drySplashInteraction" <<
endl;
231 const vector& Up = this->owner().U().boundaryField()[
pp.index()][facei];
238 const scalar m =
p.mass()*
p.nParticle();
239 const scalar
rho =
p.rho();
240 const scalar d =
p.d();
251 const scalar Wec = Adry_*
pow(La, -0.183);
255 absorbInteraction<filmType>
256 (filmModel,
p,
pp, facei, m, keepParticle);
261 const scalar mRatio = 0.2 + 0.6*rndGen_.sample01<scalar>();
262 splashInteraction<filmType>
263 (filmModel,
p,
pp, facei, mRatio, We, Wec,
sigma, keepParticle);
268 template<
class CloudType>
269 template<
class filmType>
281 DebugInfo<<
"Parcel " <<
p.origId() <<
" wetSplashInteraction" <<
endl;
284 const vector& Up = this->owner().U().boundaryField()[
pp.index()][facei];
288 const scalar m =
p.mass()*
p.nParticle();
289 const scalar
rho =
p.rho();
290 const scalar d =
p.d();
303 const scalar Wec = Awet_*
pow(La, -0.183);
307 absorbInteraction<filmType>
308 (filmModel,
p,
pp, facei, m, keepParticle);
310 else if ((We >= 2) && (We < 20))
316 const scalar
epsilon = 0.993 - theta*(1.76 - theta*(1.56 - theta*0.49));
324 else if ((We >= 20) && (We < Wec))
326 absorbInteraction<filmType>
327 (filmModel,
p,
pp, facei, m, keepParticle);
333 const scalar mRatio = 0.2 + 0.9*rndGen_.sample01<scalar>();
334 splashInteraction<filmType>
335 (filmModel,
p,
pp, facei, mRatio, We, Wec,
sigma, keepParticle);
340 template<
class CloudType>
341 template<
class filmType>
357 const vector& Up = this->owner().U().boundaryField()[
pp.index()][facei];
361 const vector tanVec1(tangentVector(nf));
362 const vector tanVec2(nf^tanVec1);
365 const scalar np =
p.nParticle();
366 const scalar m =
p.mass()*np;
367 const scalar d =
p.d();
375 const scalar mSplash = m*mRatio;
378 const scalar Ns = 5.0*(We/Wec - 1.0);
381 const scalar dBarSplash = 1/
cbrt(6.0)*
cbrt(mRatio/Ns)*d + ROOTVSMALL;
384 const scalar dMax = dMaxSplash_ > 0 ? dMaxSplash_ : 0.9*
cbrt(mRatio)*d;
385 const scalar dMin = dMinSplash_ > 0 ? dMinSplash_ : 0.1*dMax;
386 const scalar
K =
exp(-dMin/dBarSplash) -
exp(-dMax/dBarSplash);
389 scalar ESigmaSec = 0;
396 const scalar
y = rndGen_.sample01<scalar>();
397 dNew[i] = -dBarSplash*
log(
exp(-dMin/dBarSplash) -
y*
K);
398 npNew[i] = mRatio*np*
pow3(d)/
pow3(dNew[i])/parcelsPerSplash_;
399 ESigmaSec += npNew[i]*
sigma*
p.areaS(dNew[i]);
403 const scalar EKIn = 0.5*m*
magSqr(Un);
406 const scalar ESigmaIn = np*
sigma*
p.areaS(d);
412 const scalar EKs = EKIn + ESigmaIn - ESigmaSec - Ed;
417 absorbInteraction<filmType>
418 (filmModel,
p,
pp, facei, m, keepParticle);
423 const scalar logD =
log(d);
424 const scalar coeff2 =
log(dNew[0]) - logD + ROOTVSMALL;
428 for (
int i = 1; i < parcelsPerSplash_; ++i)
430 coeff1 +=
sqr(
log(dNew[i]) - logD);
434 const scalar magUns0 =
435 sqrt(2.0*parcelsPerSplash_*EKs/mSplash/(1.0 + coeff1/
sqr(coeff2)));
440 const vector dirVec = splashDirection(tanVec1, tanVec2, -nf);
443 parcelType* pPtr =
new parcelType(
p);
445 pPtr->origId() = pPtr->getNewParticleID();
449 if (splashParcelType_ >= 0)
451 pPtr->typeId() = splashParcelType_;
455 pPtr->track(0.5*rndGen_.sample01<scalar>()*(posC - posCf), 0);
457 pPtr->nParticle() = npNew[i];
461 pPtr->U() = dirVec*(
mag(Cf_*Ut) + magUns0*(
log(dNew[i]) - logD)/coeff2);
467 this->owner().addParticle(pPtr);
474 const scalar mDash = m - mSplash;
475 absorbInteraction<filmType>
476 (filmModel,
p,
pp, facei, mDash, keepParticle);
482 template<
class CloudType>
498 interactionTypeNames.
get(
"interactionType", this->coeffDict())
500 parcelTypes_(this->coeffDict().getOrDefault(
"parcelTypes",
labelList())),
502 splashParcelType_(0),
503 parcelsPerSplash_(0),
512 <<
" interaction model" <<
endl;
532 template<
class CloudType>
540 rndGen_(sfm.rndGen_),
544 interactionType_(sfm.interactionType_),
545 parcelTypes_(sfm.parcelTypes_),
546 deltaWet_(sfm.deltaWet_),
547 splashParcelType_(sfm.splashParcelType_),
548 parcelsPerSplash_(sfm.parcelsPerSplash_),
549 dMaxSplash_(sfm.dMaxSplash_),
550 dMinSplash_(sfm.dMinSplash_),
554 nParcelsSplashed_(sfm.nParcelsSplashed_)
565 template<
class CloudType>
573 if (parcelTypes_.size() && parcelTypes_.find(
p.typeId()) == -1)
577 Pout<<
"transferParcel: ignoring particle with typeId=" 585 const label patchi =
pp.index();
586 const label meshFacei =
p.face();
587 const label facei =
pp.whichFace(meshFacei);
592 if (this->filmModel_ && this->filmModel_->isRegionPatch(patchi))
594 auto& film = *filmModel_;
596 switch (interactionType_)
598 case interactionType::bounce:
600 bounceInteraction(
p,
pp, facei, keepParticle);
605 case interactionType::absorb:
607 const scalar m =
p.nParticle()*
p.mass();
609 absorbInteraction<regionFilm>
610 (film,
p,
pp, facei, m, keepParticle);
615 case interactionType::splashBai:
618 const scalar
mu = thermo_->mu(pRef_, TRef_, X);
619 const scalar
sigma = thermo_->sigma(pRef_, TRef_, X);
623 this->deltaFilmPatch_[patchi][facei] < deltaWet_
628 drySplashInteraction<regionFilm>
629 (film,
sigma,
mu,
p,
pp, facei, keepParticle);
633 wetSplashInteraction<regionFilm>
634 (film,
sigma,
mu,
p,
pp, facei, keepParticle);
643 <<
"Unknown interaction type enumeration" 654 for (areaFilm& film : this->areaFilms_)
656 const label filmFacei
669 switch (interactionType_)
671 case interactionType::bounce:
673 bounceInteraction(
p,
pp, facei, keepParticle);
678 case interactionType::absorb:
680 const scalar m =
p.nParticle()*
p.mass();
682 absorbInteraction<areaFilm>
684 film,
p,
pp, facei, m, keepParticle
689 case interactionType::splashBai:
699 const scalar pRef = film.
pRef();
700 const scalar
TRef = liqFilm.Tref();
702 const scalar
mu = liqFilm.thermo().mu(pRef,
TRef, X);
703 const scalar
sigma = liqFilm.thermo().sigma(pRef,
TRef, X);
705 const bool dry = film.
h()[filmFacei] < this->deltaWet_;
709 drySplashInteraction<areaFilm>
710 (film,
sigma,
mu,
p,
pp, facei, keepParticle);
714 wetSplashInteraction<areaFilm>
715 (film,
sigma,
mu,
p,
pp, facei, keepParticle);
724 <<
"Unknown interaction type enumeration" 738 template<
class CloudType>
741 const label filmPatchi,
742 const label primaryPatchi,
755 template<
class CloudType>
765 template<
class CloudType>
769 const label filmFacei
776 template<
class CloudType>
781 label nSplash0 = this->
template getModelProperty<label>(
"nParcelsSplashed");
785 Log_<<
" - new splash parcels = " << nSplashTotal <<
endl;
787 if (this->writeTime())
789 this->setModelProperty(
"nParcelsSplashed", nSplashTotal);
790 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.
scalar pRef() const
Access to pRef.
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)
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) to Type reference.
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 areaScalarField & h() const noexcept
Access const reference h.
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.
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 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)