mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'film'
This commit is contained in:
@ -517,12 +517,18 @@ public:
|
||||
//- Return the fraction of time-step completed
|
||||
inline scalar stepFraction() const;
|
||||
|
||||
//- Return the originating processor id
|
||||
//- Return const access to the originating processor id
|
||||
inline label origProc() const;
|
||||
|
||||
//- Return the particle id on originating processor
|
||||
//- Return the originating processor id for manipulation
|
||||
inline label& origProc();
|
||||
|
||||
//- Return const access to the particle id on originating processor
|
||||
inline label origId() const;
|
||||
|
||||
//- Return the particle id on originating processor for manipulation
|
||||
inline label& origId();
|
||||
|
||||
|
||||
// Track
|
||||
|
||||
|
||||
@ -1117,6 +1117,13 @@ inline Foam::label Foam::Particle<ParticleType>::origProc() const
|
||||
}
|
||||
|
||||
|
||||
template<class ParticleType>
|
||||
inline Foam::label& Foam::Particle<ParticleType>::origProc()
|
||||
{
|
||||
return origProc_;
|
||||
}
|
||||
|
||||
|
||||
template<class ParticleType>
|
||||
inline Foam::label Foam::Particle<ParticleType>::origId() const
|
||||
{
|
||||
@ -1124,6 +1131,13 @@ inline Foam::label Foam::Particle<ParticleType>::origId() const
|
||||
}
|
||||
|
||||
|
||||
template<class ParticleType>
|
||||
inline Foam::label& Foam::Particle<ParticleType>::origId()
|
||||
{
|
||||
return origId_;
|
||||
}
|
||||
|
||||
|
||||
template<class ParticleType>
|
||||
inline bool Foam::Particle<ParticleType>::softImpact() const
|
||||
{
|
||||
|
||||
@ -426,11 +426,8 @@ bool Foam::KinematicParcel<ParcelType>::hitPatch
|
||||
td.cloud().postProcessing().postPatch(p, patchI);
|
||||
|
||||
// Invoke surface film model
|
||||
if (td.cloud().surfaceFilm().transferParcel(p, patchI))
|
||||
if (td.cloud().surfaceFilm().transferParcel(p, pp, td.keepParticle))
|
||||
{
|
||||
// Parcel transferred to the surface film
|
||||
td.keepParticle = false;
|
||||
|
||||
// All interactions done
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -37,10 +37,12 @@ Foam::SurfaceFilmModel<CloudType>::SurfaceFilmModel(CloudType& owner)
|
||||
:
|
||||
SubModelBase<CloudType>(owner),
|
||||
g_(dimensionedVector("zero", dimAcceleration, vector::zero)),
|
||||
ejectedParcelType_(0),
|
||||
massParcelPatch_(0),
|
||||
diameterParcelPatch_(0),
|
||||
UFilmPatch_(0),
|
||||
rhoFilmPatch_(0),
|
||||
deltaFilmPatch_(0),
|
||||
nParcelsTransferred_(0),
|
||||
nParcelsInjected_(0)
|
||||
{}
|
||||
@ -57,10 +59,15 @@ Foam::SurfaceFilmModel<CloudType>::SurfaceFilmModel
|
||||
:
|
||||
SubModelBase<CloudType>(owner, dict, type),
|
||||
g_(g),
|
||||
ejectedParcelType_
|
||||
(
|
||||
this->coeffDict().lookupOrDefault("ejectedParcelType", -1)
|
||||
),
|
||||
massParcelPatch_(0),
|
||||
diameterParcelPatch_(0),
|
||||
UFilmPatch_(0),
|
||||
rhoFilmPatch_(0),
|
||||
deltaFilmPatch_(owner.mesh().boundary().size()),
|
||||
nParcelsTransferred_(0),
|
||||
nParcelsInjected_(0)
|
||||
{}
|
||||
@ -74,10 +81,12 @@ Foam::SurfaceFilmModel<CloudType>::SurfaceFilmModel
|
||||
:
|
||||
SubModelBase<CloudType>(sfm),
|
||||
g_(sfm.g_),
|
||||
ejectedParcelType_(sfm.ejectedParcelType_),
|
||||
massParcelPatch_(sfm.massParcelPatch_),
|
||||
diameterParcelPatch_(sfm.diameterParcelPatch_),
|
||||
UFilmPatch_(sfm.UFilmPatch_),
|
||||
rhoFilmPatch_(sfm.rhoFilmPatch_),
|
||||
deltaFilmPatch_(sfm.deltaFilmPatch_),
|
||||
nParcelsTransferred_(sfm.nParcelsTransferred_),
|
||||
nParcelsInjected_(sfm.nParcelsInjected_)
|
||||
{}
|
||||
@ -95,16 +104,18 @@ Foam::SurfaceFilmModel<CloudType>::~SurfaceFilmModel()
|
||||
template<class CloudType>
|
||||
bool Foam::SurfaceFilmModel<CloudType>::transferParcel
|
||||
(
|
||||
const parcelType& p,
|
||||
const label patchI
|
||||
parcelType& p,
|
||||
const polyPatch& pp,
|
||||
bool& keepParticle
|
||||
)
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"bool Foam::SurfaceFilmModel<CloudType>::transferParcel"
|
||||
"("
|
||||
"const parcelType&, "
|
||||
"const label"
|
||||
"parcelType&, "
|
||||
"const label, "
|
||||
"const bool&"
|
||||
")"
|
||||
);
|
||||
|
||||
@ -145,7 +156,7 @@ void Foam::SurfaceFilmModel<CloudType>::inject(TrackData& td)
|
||||
|
||||
const label filmPatchI = filmPatches[i];
|
||||
const mapDistribute& distMap = wpp.map();
|
||||
cacheFilmFields(filmPatchI, distMap, filmModel);
|
||||
cacheFilmFields(filmPatchI, primaryPatchI, distMap, filmModel);
|
||||
|
||||
forAll(injectorCellsPatch, j)
|
||||
{
|
||||
@ -196,6 +207,7 @@ template<class CloudType>
|
||||
void Foam::SurfaceFilmModel<CloudType>::cacheFilmFields
|
||||
(
|
||||
const label filmPatchI,
|
||||
const label primaryPatchI,
|
||||
const mapDistribute& distMap,
|
||||
const surfaceFilmModels::surfaceFilmModel& filmModel
|
||||
)
|
||||
@ -212,6 +224,10 @@ void Foam::SurfaceFilmModel<CloudType>::cacheFilmFields
|
||||
|
||||
rhoFilmPatch_ = filmModel.rho().boundaryField()[filmPatchI];
|
||||
distMap.distribute(rhoFilmPatch_);
|
||||
|
||||
deltaFilmPatch_[primaryPatchI] =
|
||||
filmModel.delta().boundaryField()[filmPatchI];
|
||||
distMap.distribute(deltaFilmPatch_[primaryPatchI]);
|
||||
}
|
||||
|
||||
|
||||
@ -229,6 +245,11 @@ void Foam::SurfaceFilmModel<CloudType>::setParcelProperties
|
||||
p.rho() = rhoFilmPatch_[filmFaceI];
|
||||
|
||||
p.nParticle() = massParcelPatch_[filmFaceI]/p.rho()/vol;
|
||||
|
||||
if (ejectedParcelType_ >= 0)
|
||||
{
|
||||
p.typeId() = ejectedParcelType_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -73,6 +73,11 @@ protected:
|
||||
//- Gravitational acceleration constant
|
||||
const dimensionedVector& g_;
|
||||
|
||||
//- Ejected parcel type label - id assigned to identify parcel for
|
||||
// post-processing. If not specified, defaults to originating cloud
|
||||
// type
|
||||
label ejectedParcelType_;
|
||||
|
||||
|
||||
// Cached injector fields per film patch
|
||||
|
||||
@ -88,6 +93,9 @@ protected:
|
||||
//- Film density / patch face
|
||||
scalarList rhoFilmPatch_;
|
||||
|
||||
//- Film height of all film patches / patch face
|
||||
scalarListList deltaFilmPatch_;
|
||||
|
||||
|
||||
// Counters
|
||||
|
||||
@ -104,6 +112,7 @@ protected:
|
||||
virtual void cacheFilmFields
|
||||
(
|
||||
const label filmPatchI,
|
||||
const label primaryPatchI,
|
||||
const mapDistribute& distMap,
|
||||
const surfaceFilmModels::surfaceFilmModel& filmModel
|
||||
);
|
||||
@ -206,8 +215,9 @@ public:
|
||||
// Returns true if parcel is to be transferred
|
||||
virtual bool transferParcel
|
||||
(
|
||||
const parcelType& p,
|
||||
const label patchI
|
||||
parcelType& p,
|
||||
const polyPatch& pp,
|
||||
bool& keepParticle
|
||||
);
|
||||
|
||||
//- Inject parcels into the cloud
|
||||
|
||||
@ -25,6 +25,460 @@ License
|
||||
|
||||
#include "ThermoSurfaceFilm.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "mathematicalConstants.H"
|
||||
#include "Pstream.H"
|
||||
|
||||
using namespace Foam::constant::mathematical;
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
template<class CloudType>
|
||||
Foam::wordList Foam::ThermoSurfaceFilm<CloudType>::interactionTypeNames_
|
||||
(
|
||||
IStringStream
|
||||
(
|
||||
"(absorb bounce splashBai)"
|
||||
)()
|
||||
);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class CloudType>
|
||||
typename Foam::ThermoSurfaceFilm<CloudType>::interactionType
|
||||
Foam::ThermoSurfaceFilm<CloudType>::interactionTypeEnum(const word& it) const
|
||||
{
|
||||
forAll(interactionTypeNames_, i)
|
||||
{
|
||||
if (interactionTypeNames_[i] == it)
|
||||
{
|
||||
return interactionType(i);
|
||||
}
|
||||
}
|
||||
|
||||
FatalErrorIn
|
||||
(
|
||||
"ThermoSurfaceFilm<CloudType>::interactionType "
|
||||
"ThermoSurfaceFilm<CloudType>::interactionTypeEnum"
|
||||
"("
|
||||
"const word& it"
|
||||
") const"
|
||||
) << "Unknown interaction type " << it
|
||||
<< ". Valid interaction types include: " << interactionTypeNames_
|
||||
<< abort(FatalError);
|
||||
|
||||
return interactionType(0);
|
||||
}
|
||||
|
||||
|
||||
template<class CloudType>
|
||||
Foam::word Foam::ThermoSurfaceFilm<CloudType>::interactionTypeStr
|
||||
(
|
||||
const interactionType& it
|
||||
) const
|
||||
{
|
||||
if (it >= interactionTypeNames_.size())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"ThermoSurfaceFilm<CloudType>::interactionType "
|
||||
"ThermoSurfaceFilm<CloudType>::interactionTypeStr"
|
||||
"("
|
||||
"const interactionType& it"
|
||||
") const"
|
||||
) << "Unknown interaction type enumeration" << abort(FatalError);
|
||||
}
|
||||
|
||||
return interactionTypeNames_[it];
|
||||
}
|
||||
|
||||
|
||||
template<class CloudType>
|
||||
Foam::vector Foam::ThermoSurfaceFilm<CloudType>::tangentVector
|
||||
(
|
||||
const vector& v
|
||||
) const
|
||||
{
|
||||
vector tangent = vector::zero;
|
||||
scalar magTangent = 0.0;
|
||||
|
||||
while (magTangent < SMALL)
|
||||
{
|
||||
vector vTest = rndGen_.sample01<vector>();
|
||||
tangent = vTest - (vTest & v)*v;
|
||||
magTangent = mag(tangent);
|
||||
}
|
||||
|
||||
return tangent/magTangent;
|
||||
}
|
||||
|
||||
|
||||
template<class CloudType>
|
||||
Foam::vector Foam::ThermoSurfaceFilm<CloudType>::splashDirection
|
||||
(
|
||||
const vector& tanVec1,
|
||||
const vector& tanVec2,
|
||||
const vector& nf
|
||||
) const
|
||||
{
|
||||
// azimuthal angle [rad]
|
||||
const scalar phiSi = twoPi*rndGen_.sample01<scalar>();
|
||||
|
||||
// ejection angle [rad]
|
||||
const scalar thetaSi = pi/180.0*(rndGen_.sample01<scalar>()*(50 - 5) + 5);
|
||||
|
||||
// direction vector of new parcel
|
||||
const scalar alpha = sin(thetaSi);
|
||||
const scalar dcorr = cos(thetaSi);
|
||||
const vector normal = alpha*(tanVec1*cos(phiSi) + tanVec2*sin(phiSi));
|
||||
vector dirVec = dcorr*nf;
|
||||
dirVec += normal;
|
||||
|
||||
return dirVec/mag(dirVec);
|
||||
}
|
||||
|
||||
|
||||
template<class CloudType>
|
||||
void Foam::ThermoSurfaceFilm<CloudType>::absorbInteraction
|
||||
(
|
||||
surfaceFilmModels::surfaceFilmModel& filmModel,
|
||||
const parcelType& p,
|
||||
const polyPatch& pp,
|
||||
const label faceI,
|
||||
const scalar mass,
|
||||
bool& keepParticle
|
||||
)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "Parcel " << p.origId() << " absorbInteraction" << endl;
|
||||
}
|
||||
|
||||
// Patch face normal
|
||||
const vector& nf = pp.faceNormals()[faceI];
|
||||
|
||||
// Patch velocity
|
||||
const vector& Up = this->owner().U().boundaryField()[pp.index()][faceI];
|
||||
|
||||
// Relative parcel velocity
|
||||
const vector Urel = p.U() - Up;
|
||||
|
||||
// Parcel normal velocity
|
||||
const vector Un = nf*(Urel & nf);
|
||||
|
||||
// Parcel tangential velocity
|
||||
const vector Ut = Urel - Un;
|
||||
|
||||
filmModel.addSources
|
||||
(
|
||||
pp.index(),
|
||||
faceI,
|
||||
mass, // mass
|
||||
mass*Ut, // tangential momentum
|
||||
mass*mag(Un), // impingement pressure
|
||||
mass*p.hs() // energy
|
||||
);
|
||||
|
||||
this->nParcelsTransferred()++;
|
||||
|
||||
keepParticle = false;
|
||||
}
|
||||
|
||||
|
||||
template<class CloudType>
|
||||
void Foam::ThermoSurfaceFilm<CloudType>::bounceInteraction
|
||||
(
|
||||
parcelType& p,
|
||||
const polyPatch& pp,
|
||||
const label faceI,
|
||||
bool& keepParticle
|
||||
) const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "Parcel " << p.origId() << " bounceInteraction" << endl;
|
||||
}
|
||||
|
||||
// Patch face normal
|
||||
const vector& nf = pp.faceNormals()[faceI];
|
||||
|
||||
// Patch velocity
|
||||
const vector& Up = this->owner().U().boundaryField()[pp.index()][faceI];
|
||||
|
||||
// Relative parcel velocity
|
||||
const vector Urel = p.U() - Up;
|
||||
|
||||
// Flip parcel normal velocity component
|
||||
p.U() -= 2.0*nf*(Urel & nf);
|
||||
|
||||
keepParticle = true;
|
||||
}
|
||||
|
||||
|
||||
template<class CloudType>
|
||||
void Foam::ThermoSurfaceFilm<CloudType>::drySplashInteraction
|
||||
(
|
||||
surfaceFilmModels::surfaceFilmModel& filmModel,
|
||||
const parcelType& p,
|
||||
const polyPatch& pp,
|
||||
const label faceI,
|
||||
bool& keepParticle
|
||||
)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "Parcel " << p.origId() << " drySplashInteraction" << endl;
|
||||
}
|
||||
|
||||
const liquid& liq = thermo_.liquids().properties()[0];
|
||||
|
||||
// Patch face velocity and normal
|
||||
const vector& Up = this->owner().U().boundaryField()[pp.index()][faceI];
|
||||
const vector& nf = pp.faceNormals()[faceI];
|
||||
|
||||
// local pressure
|
||||
const scalar pc = thermo_.thermo().p()[p.cell()];
|
||||
|
||||
// Retrieve parcel properties
|
||||
const scalar m = p.mass()*p.nParticle();
|
||||
const scalar rho = p.rho();
|
||||
const scalar d = p.d();
|
||||
const scalar sigma = liq.sigma(pc, p.T());
|
||||
const scalar mu = liq.mu(pc, p.T());
|
||||
const vector Urel = p.U() - Up;
|
||||
const vector Un = nf*(Urel & nf);
|
||||
|
||||
// Laplace number
|
||||
const scalar La = rho*sigma*d/sqr(mu);
|
||||
|
||||
// Weber number
|
||||
const scalar We = rho*magSqr(Un)*d/sigma;
|
||||
|
||||
// Critical Weber number
|
||||
const scalar Wec = Adry_*pow(La, -0.183);
|
||||
|
||||
if (We < Wec) // adhesion - assume absorb
|
||||
{
|
||||
absorbInteraction(filmModel, p, pp, faceI, m, keepParticle);
|
||||
}
|
||||
else // splash
|
||||
{
|
||||
// ratio of incident mass to splashing mass
|
||||
const scalar mRatio = 0.2 + 0.6*rndGen_.sample01<scalar>();
|
||||
splashInteraction
|
||||
(filmModel, p, pp, faceI, mRatio, We, Wec, sigma, keepParticle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class CloudType>
|
||||
void Foam::ThermoSurfaceFilm<CloudType>::wetSplashInteraction
|
||||
(
|
||||
surfaceFilmModels::surfaceFilmModel& filmModel,
|
||||
parcelType& p,
|
||||
const polyPatch& pp,
|
||||
const label faceI,
|
||||
bool& keepParticle
|
||||
)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "Parcel " << p.origId() << " wetSplashInteraction" << endl;
|
||||
}
|
||||
|
||||
const liquid& liq = thermo_.liquids().properties()[0];
|
||||
|
||||
// Patch face velocity and normal
|
||||
const vector& Up = this->owner().U().boundaryField()[pp.index()][faceI];
|
||||
const vector& nf = pp.faceNormals()[faceI];
|
||||
|
||||
// local pressure
|
||||
const scalar pc = thermo_.thermo().p()[p.cell()];
|
||||
|
||||
// Retrieve parcel properties
|
||||
const scalar m = p.mass()*p.nParticle();
|
||||
const scalar rho = p.rho();
|
||||
const scalar d = p.d();
|
||||
vector& U = p.U();
|
||||
const scalar sigma = liq.sigma(pc, p.T());
|
||||
const scalar mu = liq.mu(pc, p.T());
|
||||
const vector Urel = p.U() - Up;
|
||||
const vector Un = nf*(Urel & nf);
|
||||
const vector Ut = Urel - Un;
|
||||
|
||||
// Laplace number
|
||||
const scalar La = rho*sigma*d/sqr(mu);
|
||||
|
||||
// Weber number
|
||||
const scalar We = rho*magSqr(Un)*d/sigma;
|
||||
|
||||
// Critical Weber number
|
||||
const scalar Wec = Awet_*pow(La, -0.183);
|
||||
|
||||
if (We < 1) // adhesion - assume absorb
|
||||
{
|
||||
absorbInteraction(filmModel, p, pp, faceI, m, keepParticle);
|
||||
}
|
||||
else if ((We >= 1) && (We < 20)) // bounce
|
||||
{
|
||||
// incident angle of impingement
|
||||
const scalar theta = pi/2 - acos(U/mag(U) & nf);
|
||||
|
||||
// restitution coefficient
|
||||
const scalar epsilon = 0.993 - theta*(1.76 - theta*(1.56 - theta*0.49));
|
||||
|
||||
// update parcel velocity
|
||||
U = -epsilon*(Un) + 5/7*(Ut);
|
||||
|
||||
keepParticle = true;
|
||||
}
|
||||
else if ((We >= 20) && (We < Wec)) // spread - assume absorb
|
||||
{
|
||||
absorbInteraction(filmModel, p, pp, faceI, m, keepParticle);
|
||||
}
|
||||
else // splash
|
||||
{
|
||||
// ratio of incident mass to splashing mass
|
||||
// splash mass can be > incident mass due to film entrainment
|
||||
const scalar mRatio = 0.2 + 0.9*rndGen_.sample01<scalar>();
|
||||
splashInteraction
|
||||
(filmModel, p, pp, faceI, mRatio, We, Wec, sigma, keepParticle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class CloudType>
|
||||
void Foam::ThermoSurfaceFilm<CloudType>::splashInteraction
|
||||
(
|
||||
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
|
||||
)
|
||||
{
|
||||
// Patch face velocity and normal
|
||||
const fvMesh& mesh = this->owner().mesh();
|
||||
const vector& Up = this->owner().U().boundaryField()[pp.index()][faceI];
|
||||
const vector& nf = pp.faceNormals()[faceI];
|
||||
|
||||
// Determine direction vectors tangential to patch normal
|
||||
const vector tanVec1 = tangentVector(nf);
|
||||
const vector tanVec2 = nf^tanVec1;
|
||||
|
||||
// Retrieve parcel properties
|
||||
const scalar np = p.nParticle();
|
||||
const scalar m = p.mass()*np;
|
||||
const scalar d = p.d();
|
||||
const vector Urel = p.U() - Up;
|
||||
const vector Un = nf*(Urel & nf);
|
||||
const vector Ut = Urel - Un;
|
||||
const vector& posC = mesh.C()[p.cell()];
|
||||
const vector& posCf = mesh.Cf().boundaryField()[pp.index()][faceI];
|
||||
|
||||
// total mass of (all) splashed parcels
|
||||
const scalar mSplash = m*mRatio;
|
||||
|
||||
// number of splashed particles per incoming particle
|
||||
const scalar Ns = 5.0*(We/Wec - 1.0);
|
||||
|
||||
// average diameter of splashed particles
|
||||
const scalar dBarSplash = 1/cbrt(6.0)*cbrt(mRatio/Ns)*d + ROOTVSMALL;
|
||||
|
||||
// cumulative diameter splash distribution
|
||||
const scalar dMin = 0.01*d;
|
||||
const scalar dMax = d;
|
||||
const scalar K = exp(-dMin/dBarSplash) - exp(-dMax/dBarSplash);
|
||||
|
||||
// surface energy of secondary parcels [J]
|
||||
scalar ESigmaSec = 0;
|
||||
|
||||
// sample splash distribution to detrmine secondary parcel diameters
|
||||
scalarList dNew(parcelsPerSplash_);
|
||||
forAll(dNew, i)
|
||||
{
|
||||
const scalar y = rndGen_.sample01<scalar>();
|
||||
dNew[i] = -dBarSplash*log(exp(-dMin/dBarSplash) - y*K);
|
||||
ESigmaSec += sigma*p.areaS(dNew[i]);
|
||||
}
|
||||
|
||||
// incident kinetic energy [J]
|
||||
const scalar EKIn = 0.5*m*magSqr(Urel);
|
||||
|
||||
// incident surface energy [J]
|
||||
const scalar ESigmaIn = sigma*p.areaS(d);
|
||||
|
||||
// dissipative energy
|
||||
const scalar Ed = max(0.8*EKIn, Wec/12*pi*sigma*sqr(d));
|
||||
|
||||
// total energy [J]
|
||||
const scalar EKs = EKIn + ESigmaIn - ESigmaSec - Ed;
|
||||
|
||||
// switch to absorb if insufficient energy for splash
|
||||
if (EKs <= 0)
|
||||
{
|
||||
absorbInteraction(filmModel, p, pp, faceI, m, keepParticle);
|
||||
return;
|
||||
}
|
||||
|
||||
// helper variables to calculate magUns0
|
||||
const scalar logD = log(d);
|
||||
const scalar coeff2 = log(dNew[0]) - logD + ROOTVSMALL;
|
||||
scalar coeff1 = 0.0;
|
||||
forAll(dNew, i)
|
||||
{
|
||||
coeff1 += sqr(log(dNew[i]) - logD);
|
||||
}
|
||||
|
||||
// magnitude of the normal velocity of the first splashed parcel
|
||||
const scalar magUns0 =
|
||||
sqrt(2.0*parcelsPerSplash_*EKs/mSplash/(1 + coeff1/sqr(coeff2)));
|
||||
|
||||
// Set splashed parcel properties
|
||||
forAll(dNew, i)
|
||||
{
|
||||
const vector dirVec = splashDirection(tanVec1, tanVec2, -nf);
|
||||
|
||||
// Create a new parcel by copying source parcel
|
||||
parcelType* pPtr = new parcelType(p);
|
||||
|
||||
pPtr->origId() = this->owner().getNewParticleID();
|
||||
|
||||
pPtr->origProc() = Pstream::myProcNo();
|
||||
|
||||
if (splashParcelType_ >= 0)
|
||||
{
|
||||
pPtr->typeId() = splashParcelType_;
|
||||
}
|
||||
|
||||
// perturb new parcels towards the owner cell centre
|
||||
pPtr->position() += 0.5*rndGen_.sample01<scalar>()*(posC - posCf);
|
||||
|
||||
pPtr->nParticle() = mRatio*np*pow3(d)/pow3(dNew[i])/parcelsPerSplash_;
|
||||
|
||||
pPtr->d() = dNew[i];
|
||||
|
||||
pPtr->U() = dirVec*(mag(Cf_*Ut) + magUns0*(log(dNew[i]) - logD)/coeff2);
|
||||
|
||||
// Apply correction to velocity for 2-D cases
|
||||
meshTools::constrainDirection(mesh, mesh.solutionD(), pPtr->U());
|
||||
|
||||
// Add the new parcel
|
||||
this->owner().addParticle(pPtr);
|
||||
|
||||
nParcelsSplashed_++;
|
||||
}
|
||||
|
||||
// transfer remaining part of parcel to film 0 - splashMass can be -ve
|
||||
// if entraining from the film
|
||||
const scalar mDash = m - mSplash;
|
||||
absorbInteraction(filmModel, p, pp, faceI, mDash, keepParticle);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
@ -37,9 +491,37 @@ Foam::ThermoSurfaceFilm<CloudType>::ThermoSurfaceFilm
|
||||
)
|
||||
:
|
||||
SurfaceFilmModel<CloudType>(dict, owner, g, typeName),
|
||||
rndGen_(owner.rndGen()),
|
||||
thermo_(owner.db().objectRegistry::lookupObject<SLGThermo>("SLGThermo")),
|
||||
TFilmPatch_(0),
|
||||
CpFilmPatch_(0)
|
||||
{}
|
||||
CpFilmPatch_(0),
|
||||
interactionType_
|
||||
(
|
||||
interactionTypeEnum(this->coeffDict().lookup("interactionType"))
|
||||
),
|
||||
deltaWet_(0.0),
|
||||
splashParcelType_(0),
|
||||
parcelsPerSplash_(0),
|
||||
Adry_(0.0),
|
||||
Awet_(0.0),
|
||||
Cf_(0.0),
|
||||
nParcelsSplashed_(0)
|
||||
{
|
||||
Info<< " Applying " << interactionTypeStr(interactionType_)
|
||||
<< " interaction model" << endl;
|
||||
|
||||
if (interactionType_ == itSplashBai)
|
||||
{
|
||||
this->coeffDict().lookup("deltaWet") >> deltaWet_;
|
||||
splashParcelType_ =
|
||||
this->coeffDict().lookupOrDefault("splashParcelType", -1);
|
||||
parcelsPerSplash_ =
|
||||
this->coeffDict().lookupOrDefault("parcelsPerSplash", 2);
|
||||
this->coeffDict().lookup("Adry") >> Adry_;
|
||||
this->coeffDict().lookup("Awet") >> Awet_;
|
||||
this->coeffDict().lookup("Cf") >> Cf_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class CloudType>
|
||||
@ -49,8 +531,18 @@ Foam::ThermoSurfaceFilm<CloudType>::ThermoSurfaceFilm
|
||||
)
|
||||
:
|
||||
SurfaceFilmModel<CloudType>(sfm),
|
||||
rndGen_(sfm.rndGen_),
|
||||
thermo_(sfm.thermo_),
|
||||
TFilmPatch_(sfm.TFilmPatch_),
|
||||
CpFilmPatch_(sfm.CpFilmPatch_)
|
||||
CpFilmPatch_(sfm.CpFilmPatch_),
|
||||
interactionType_(sfm.interactionType_),
|
||||
deltaWet_(sfm.deltaWet_),
|
||||
splashParcelType_(sfm.splashParcelType_),
|
||||
parcelsPerSplash_(sfm.parcelsPerSplash_),
|
||||
Adry_(sfm.Adry_),
|
||||
Awet_(sfm.Awet_),
|
||||
Cf_(sfm.Cf_),
|
||||
nParcelsSplashed_(sfm.nParcelsSplashed_)
|
||||
{}
|
||||
|
||||
|
||||
@ -66,8 +558,9 @@ Foam::ThermoSurfaceFilm<CloudType>::~ThermoSurfaceFilm()
|
||||
template<class CloudType>
|
||||
bool Foam::ThermoSurfaceFilm<CloudType>::transferParcel
|
||||
(
|
||||
const parcelType& p,
|
||||
const label patchI
|
||||
parcelType& p,
|
||||
const polyPatch& pp,
|
||||
bool& keepParticle
|
||||
)
|
||||
{
|
||||
// Retrieve the film model from the owner database
|
||||
@ -81,49 +574,61 @@ bool Foam::ThermoSurfaceFilm<CloudType>::transferParcel
|
||||
)
|
||||
);
|
||||
|
||||
const label patchI = pp.index();
|
||||
|
||||
if (filmModel.isFilmPatch(patchI))
|
||||
{
|
||||
const polyPatch& pp = this->owner().mesh().boundaryMesh()[patchI];
|
||||
|
||||
const label faceI = pp.whichFace(p.face());
|
||||
|
||||
// Patch face normal
|
||||
const vector& nf = pp.faceNormals()[faceI];
|
||||
|
||||
// Relative parcel velocity
|
||||
const vector Urel =
|
||||
p.U() - this->owner().U().boundaryField()[patchI][faceI];
|
||||
|
||||
// Parcel mass
|
||||
const scalar m = p.nParticle()*p.mass();
|
||||
|
||||
// Add the particle properties as sources to the film model
|
||||
filmModel.addSources
|
||||
(
|
||||
patchI,
|
||||
faceI,
|
||||
m, // mass
|
||||
m*(Urel - nf*(Urel & nf)), // tangential momentum
|
||||
m*mag(Urel & nf), // impingement pressure
|
||||
m*p.hs() // energy
|
||||
);
|
||||
|
||||
if (debug)
|
||||
switch (interactionType_)
|
||||
{
|
||||
Info<< "ThermoSurfaceFilm<CloudType>::transferParcel:" << nl
|
||||
<< " Effective increase in film height = "
|
||||
<< p.nParticle()*p.volume()/mag(pp.faceAreas()[faceI]) << endl;
|
||||
case itBounce:
|
||||
{
|
||||
bounceInteraction(p, pp, faceI, keepParticle);
|
||||
|
||||
break;
|
||||
}
|
||||
case itAbsorb:
|
||||
{
|
||||
const scalar m = p.nParticle()*p.mass();
|
||||
absorbInteraction(filmModel, p, pp, faceI, m, keepParticle);
|
||||
|
||||
break;
|
||||
}
|
||||
case itSplashBai:
|
||||
{
|
||||
bool dry = this->deltaFilmPatch_[patchI][faceI] < deltaWet_;
|
||||
|
||||
if (dry)
|
||||
{
|
||||
drySplashInteraction(filmModel, p, pp, faceI, keepParticle);
|
||||
}
|
||||
else
|
||||
{
|
||||
wetSplashInteraction(filmModel, p, pp, faceI, keepParticle);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"bool ThermoSurfaceFilm<CloudType>::transferParcel"
|
||||
"("
|
||||
"const parcelType&, "
|
||||
"const label"
|
||||
")"
|
||||
) << "Unknown interaction type enumeration"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
this->nParcelsTransferred()++;
|
||||
|
||||
// Flag to remove parcel p from owner cloud
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// do not transfer parcel
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -131,6 +636,7 @@ template<class CloudType>
|
||||
void Foam::ThermoSurfaceFilm<CloudType>::cacheFilmFields
|
||||
(
|
||||
const label filmPatchI,
|
||||
const label primaryPatchI,
|
||||
const mapDistribute& distMap,
|
||||
const surfaceFilmModels::surfaceFilmModel& filmModel
|
||||
)
|
||||
@ -138,6 +644,7 @@ void Foam::ThermoSurfaceFilm<CloudType>::cacheFilmFields
|
||||
SurfaceFilmModel<CloudType>::cacheFilmFields
|
||||
(
|
||||
filmPatchI,
|
||||
primaryPatchI,
|
||||
distMap,
|
||||
filmModel
|
||||
);
|
||||
@ -168,10 +675,12 @@ void Foam::ThermoSurfaceFilm<CloudType>::setParcelProperties
|
||||
template<class CloudType>
|
||||
void Foam::ThermoSurfaceFilm<CloudType>::info(Ostream& os) const
|
||||
{
|
||||
os << " Parcels transferred to film = "
|
||||
os << " Parcels absorbed into film = "
|
||||
<< returnReduce(this->nParcelsTransferred(), sumOp<label>()) << nl
|
||||
<< " Number of film parcels added = "
|
||||
<< returnReduce(this->nParcelsInjected(), sumOp<label>()) << nl;
|
||||
<< " New film detached parcels = "
|
||||
<< returnReduce(this->nParcelsInjected(), sumOp<label>()) << nl
|
||||
<< " New film splash parcels = "
|
||||
<< returnReduce(nParcelsSplashed_, sumOp<label>()) << nl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -27,6 +27,19 @@ Class
|
||||
Description
|
||||
Thermo parcel surface film model.
|
||||
|
||||
Responsible for:
|
||||
- injecting parcelss from the film model into the cloud, e.g. for dripping
|
||||
- parcel interaction with the film, e.g absorb, bounce, splash
|
||||
|
||||
Splash model references:
|
||||
|
||||
Bai and Gosman, `Mathematical modelling of wall films formed by
|
||||
impinging sprays', SAE 960626, 1996
|
||||
|
||||
Bai et al, `Modelling off gasoline spray impingement', Atom. Sprays,
|
||||
vol 12, pp 1-27, 2002
|
||||
|
||||
|
||||
SourceFiles
|
||||
ThermoSurfaceFilm.C
|
||||
ThermoSurfaceFilmI.H
|
||||
@ -52,6 +65,31 @@ class ThermoSurfaceFilm
|
||||
:
|
||||
public SurfaceFilmModel<CloudType>
|
||||
{
|
||||
public:
|
||||
|
||||
// Public data
|
||||
|
||||
// Interaction type enumerations
|
||||
enum interactionType
|
||||
{
|
||||
itAbsorb,
|
||||
itBounce,
|
||||
itSplashBai
|
||||
};
|
||||
|
||||
//- Word descriptions of interaction type names
|
||||
static wordList interactionTypeNames_;
|
||||
|
||||
|
||||
// Public Member Functions
|
||||
|
||||
// Return interaction type enum from word
|
||||
interactionType interactionTypeEnum(const word& it) const;
|
||||
|
||||
// Return word from interaction type enum
|
||||
word interactionTypeStr(const interactionType& it) const;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
@ -59,6 +97,12 @@ protected:
|
||||
//- Convenience typedef to the cloud's parcel type
|
||||
typedef typename CloudType::parcelType parcelType;
|
||||
|
||||
//- Reference to the cloud random number generator
|
||||
cachedRandom& rndGen_;
|
||||
|
||||
//- Reference to the cloud thermo package
|
||||
const SLGThermo& thermo_;
|
||||
|
||||
|
||||
// Cached injector fields per film patch
|
||||
|
||||
@ -69,24 +113,132 @@ protected:
|
||||
scalarList CpFilmPatch_;
|
||||
|
||||
|
||||
// Protected functions
|
||||
// Interaction model data
|
||||
|
||||
//- Cache the film fields in preparation for injection
|
||||
virtual void cacheFilmFields
|
||||
(
|
||||
const label filmPatchI,
|
||||
const mapDistribute& distMap,
|
||||
const surfaceFilmModels::surfaceFilmModel& filmModel
|
||||
);
|
||||
//- Interaction type enumeration
|
||||
interactionType interactionType_;
|
||||
|
||||
//- Set the individual parcel properties
|
||||
virtual void setParcelProperties
|
||||
//- Film thickness beyond which patch is assumed to be wet
|
||||
scalar deltaWet_;
|
||||
|
||||
//- Splash parcel type label - id assigned to identify parcel for
|
||||
// post-processing. If not specified, defaults to originating cloud
|
||||
// type
|
||||
label splashParcelType_;
|
||||
|
||||
//- Number of new parcels resulting from splash event
|
||||
label parcelsPerSplash_;
|
||||
|
||||
|
||||
// Surface roughness coefficient typically in the range 1300 - 5200
|
||||
// and decreases with increasing surface roughness
|
||||
|
||||
//- Dry surface roughness coefficient
|
||||
// = 2630 for dry interaction (ref. Bai)
|
||||
scalar Adry_;
|
||||
|
||||
//- Wet surface roughness coefficient
|
||||
// = 1320 for wet interaction (ref. Bai)
|
||||
scalar Awet_;
|
||||
|
||||
|
||||
//- Skin friction typically in the range 0.6 < Cf < 0.8
|
||||
scalar Cf_;
|
||||
|
||||
//- Counter for number of new splash parcels
|
||||
label nParcelsSplashed_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Return a vector tangential to input vector, v
|
||||
vector tangentVector(const vector& v) const;
|
||||
|
||||
//- Return splashed parcel direction
|
||||
vector splashDirection
|
||||
(
|
||||
parcelType& p,
|
||||
const label filmFaceI
|
||||
const vector& tanVec1,
|
||||
const vector& tanVec2,
|
||||
const vector& nf
|
||||
) const;
|
||||
|
||||
|
||||
// Interaction models
|
||||
|
||||
//- Absorb parcel into film
|
||||
void absorbInteraction
|
||||
(
|
||||
surfaceFilmModels::surfaceFilmModel& filmModel,
|
||||
const parcelType& p,
|
||||
const polyPatch& pp,
|
||||
const label faceI,
|
||||
const scalar mass,
|
||||
bool& keepParticle
|
||||
);
|
||||
|
||||
//- Bounce parcel (flip parcel normal velocity)
|
||||
void bounceInteraction
|
||||
(
|
||||
parcelType& p,
|
||||
const polyPatch& pp,
|
||||
const label faceI,
|
||||
bool& keepParticle
|
||||
) const;
|
||||
|
||||
//- Parcel interaction with dry surface
|
||||
void drySplashInteraction
|
||||
(
|
||||
surfaceFilmModels::surfaceFilmModel& filmModel,
|
||||
const parcelType& p,
|
||||
const polyPatch& pp,
|
||||
const label faceI,
|
||||
bool& keepParticle
|
||||
);
|
||||
|
||||
//- Parcel interaction with wetted surface
|
||||
void wetSplashInteraction
|
||||
(
|
||||
surfaceFilmModels::surfaceFilmModel& filmModel,
|
||||
parcelType& p,
|
||||
const polyPatch& pp,
|
||||
const label faceI,
|
||||
bool& keepParticle
|
||||
);
|
||||
|
||||
//- Bai parcel splash interaction model
|
||||
void splashInteraction
|
||||
(
|
||||
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
|
||||
);
|
||||
|
||||
|
||||
// Injection from sheet (ejection) helper functions
|
||||
|
||||
//- Cache the film fields in preparation for injection
|
||||
virtual void cacheFilmFields
|
||||
(
|
||||
const label filmPatchI,
|
||||
const label primaryPatchI,
|
||||
const mapDistribute& distMap,
|
||||
const surfaceFilmModels::surfaceFilmModel& filmModel
|
||||
);
|
||||
|
||||
//- Set the individual parcel properties
|
||||
virtual void setParcelProperties
|
||||
(
|
||||
parcelType& p,
|
||||
const label filmFaceI
|
||||
) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
@ -128,8 +280,9 @@ public:
|
||||
// Returns true if parcel is to be transferred
|
||||
virtual bool transferParcel
|
||||
(
|
||||
const parcelType& p,
|
||||
const label patchI
|
||||
parcelType& p,
|
||||
const polyPatch& pp,
|
||||
bool& keepParticle
|
||||
);
|
||||
|
||||
|
||||
|
||||
@ -136,9 +136,17 @@ void Foam::surfaceFilmModels::noFilm::addSources
|
||||
}
|
||||
|
||||
|
||||
const Foam::volScalarField& Foam::surfaceFilmModels::noFilm::delta() const
|
||||
{
|
||||
FatalErrorIn("const volScalarField& noFilm::delta() const")
|
||||
<< "delta field not available for " << type() << abort(FatalError);
|
||||
|
||||
return volScalarField::null();
|
||||
}
|
||||
|
||||
const Foam::volVectorField& Foam::surfaceFilmModels::noFilm::U() const
|
||||
{
|
||||
FatalErrorIn("const volScalarField& noFilm::U() const")
|
||||
FatalErrorIn("const volVectorField& noFilm::U() const")
|
||||
<< "U field not available for " << type() << abort(FatalError);
|
||||
|
||||
return volVectorField::null();
|
||||
@ -147,7 +155,7 @@ const Foam::volVectorField& Foam::surfaceFilmModels::noFilm::U() const
|
||||
|
||||
const Foam::volVectorField& Foam::surfaceFilmModels::noFilm::Us() const
|
||||
{
|
||||
FatalErrorIn("const volScalarField& noFilm::Us() const")
|
||||
FatalErrorIn("const volVectorField& noFilm::Us() const")
|
||||
<< "Us field not available for " << type() << abort(FatalError);
|
||||
|
||||
return volVectorField::null();
|
||||
@ -156,7 +164,7 @@ const Foam::volVectorField& Foam::surfaceFilmModels::noFilm::Us() const
|
||||
|
||||
const Foam::volVectorField& Foam::surfaceFilmModels::noFilm::Uw() const
|
||||
{
|
||||
FatalErrorIn("const volScalarField& noFilm::Uw() const")
|
||||
FatalErrorIn("const volVectorField& noFilm::Uw() const")
|
||||
<< "Uw field not available for " << type() << abort(FatalError);
|
||||
|
||||
return volVectorField::null();
|
||||
|
||||
@ -126,6 +126,9 @@ public:
|
||||
|
||||
// Fields
|
||||
|
||||
//- Return the film thickness [m]
|
||||
virtual const volScalarField& delta() const;
|
||||
|
||||
//- Return the film velocity [m/s]
|
||||
virtual const volVectorField& U() const;
|
||||
|
||||
|
||||
@ -220,6 +220,9 @@ public:
|
||||
|
||||
// Fields
|
||||
|
||||
//- Return the film thickness [m]
|
||||
virtual const volScalarField& delta() const = 0;
|
||||
|
||||
//- Return the film velocity [m/s]
|
||||
virtual const volVectorField& U() const = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user