Merge branch 'film'

This commit is contained in:
andy
2010-11-19 18:32:32 +00:00
10 changed files with 796 additions and 72 deletions

View File

@ -517,12 +517,18 @@ public:
//- Return the fraction of time-step completed //- Return the fraction of time-step completed
inline scalar stepFraction() const; inline scalar stepFraction() const;
//- Return the originating processor id //- Return const access to the originating processor id
inline label origProc() const; 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; inline label origId() const;
//- Return the particle id on originating processor for manipulation
inline label& origId();
// Track // Track

View File

@ -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> template<class ParticleType>
inline Foam::label Foam::Particle<ParticleType>::origId() const 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> template<class ParticleType>
inline bool Foam::Particle<ParticleType>::softImpact() const inline bool Foam::Particle<ParticleType>::softImpact() const
{ {

View File

@ -426,11 +426,8 @@ bool Foam::KinematicParcel<ParcelType>::hitPatch
td.cloud().postProcessing().postPatch(p, patchI); td.cloud().postProcessing().postPatch(p, patchI);
// Invoke surface film model // 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 // All interactions done
return true; return true;
} }

View File

@ -37,10 +37,12 @@ Foam::SurfaceFilmModel<CloudType>::SurfaceFilmModel(CloudType& owner)
: :
SubModelBase<CloudType>(owner), SubModelBase<CloudType>(owner),
g_(dimensionedVector("zero", dimAcceleration, vector::zero)), g_(dimensionedVector("zero", dimAcceleration, vector::zero)),
ejectedParcelType_(0),
massParcelPatch_(0), massParcelPatch_(0),
diameterParcelPatch_(0), diameterParcelPatch_(0),
UFilmPatch_(0), UFilmPatch_(0),
rhoFilmPatch_(0), rhoFilmPatch_(0),
deltaFilmPatch_(0),
nParcelsTransferred_(0), nParcelsTransferred_(0),
nParcelsInjected_(0) nParcelsInjected_(0)
{} {}
@ -57,10 +59,15 @@ Foam::SurfaceFilmModel<CloudType>::SurfaceFilmModel
: :
SubModelBase<CloudType>(owner, dict, type), SubModelBase<CloudType>(owner, dict, type),
g_(g), g_(g),
ejectedParcelType_
(
this->coeffDict().lookupOrDefault("ejectedParcelType", -1)
),
massParcelPatch_(0), massParcelPatch_(0),
diameterParcelPatch_(0), diameterParcelPatch_(0),
UFilmPatch_(0), UFilmPatch_(0),
rhoFilmPatch_(0), rhoFilmPatch_(0),
deltaFilmPatch_(owner.mesh().boundary().size()),
nParcelsTransferred_(0), nParcelsTransferred_(0),
nParcelsInjected_(0) nParcelsInjected_(0)
{} {}
@ -74,10 +81,12 @@ Foam::SurfaceFilmModel<CloudType>::SurfaceFilmModel
: :
SubModelBase<CloudType>(sfm), SubModelBase<CloudType>(sfm),
g_(sfm.g_), g_(sfm.g_),
ejectedParcelType_(sfm.ejectedParcelType_),
massParcelPatch_(sfm.massParcelPatch_), massParcelPatch_(sfm.massParcelPatch_),
diameterParcelPatch_(sfm.diameterParcelPatch_), diameterParcelPatch_(sfm.diameterParcelPatch_),
UFilmPatch_(sfm.UFilmPatch_), UFilmPatch_(sfm.UFilmPatch_),
rhoFilmPatch_(sfm.rhoFilmPatch_), rhoFilmPatch_(sfm.rhoFilmPatch_),
deltaFilmPatch_(sfm.deltaFilmPatch_),
nParcelsTransferred_(sfm.nParcelsTransferred_), nParcelsTransferred_(sfm.nParcelsTransferred_),
nParcelsInjected_(sfm.nParcelsInjected_) nParcelsInjected_(sfm.nParcelsInjected_)
{} {}
@ -95,16 +104,18 @@ Foam::SurfaceFilmModel<CloudType>::~SurfaceFilmModel()
template<class CloudType> template<class CloudType>
bool Foam::SurfaceFilmModel<CloudType>::transferParcel bool Foam::SurfaceFilmModel<CloudType>::transferParcel
( (
const parcelType& p, parcelType& p,
const label patchI const polyPatch& pp,
bool& keepParticle
) )
{ {
notImplemented notImplemented
( (
"bool Foam::SurfaceFilmModel<CloudType>::transferParcel" "bool Foam::SurfaceFilmModel<CloudType>::transferParcel"
"(" "("
"const parcelType&, " "parcelType&, "
"const label" "const label, "
"const bool&"
")" ")"
); );
@ -145,7 +156,7 @@ void Foam::SurfaceFilmModel<CloudType>::inject(TrackData& td)
const label filmPatchI = filmPatches[i]; const label filmPatchI = filmPatches[i];
const mapDistribute& distMap = wpp.map(); const mapDistribute& distMap = wpp.map();
cacheFilmFields(filmPatchI, distMap, filmModel); cacheFilmFields(filmPatchI, primaryPatchI, distMap, filmModel);
forAll(injectorCellsPatch, j) forAll(injectorCellsPatch, j)
{ {
@ -196,6 +207,7 @@ template<class CloudType>
void Foam::SurfaceFilmModel<CloudType>::cacheFilmFields void Foam::SurfaceFilmModel<CloudType>::cacheFilmFields
( (
const label filmPatchI, const label filmPatchI,
const label primaryPatchI,
const mapDistribute& distMap, const mapDistribute& distMap,
const surfaceFilmModels::surfaceFilmModel& filmModel const surfaceFilmModels::surfaceFilmModel& filmModel
) )
@ -212,6 +224,10 @@ void Foam::SurfaceFilmModel<CloudType>::cacheFilmFields
rhoFilmPatch_ = filmModel.rho().boundaryField()[filmPatchI]; rhoFilmPatch_ = filmModel.rho().boundaryField()[filmPatchI];
distMap.distribute(rhoFilmPatch_); 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.rho() = rhoFilmPatch_[filmFaceI];
p.nParticle() = massParcelPatch_[filmFaceI]/p.rho()/vol; p.nParticle() = massParcelPatch_[filmFaceI]/p.rho()/vol;
if (ejectedParcelType_ >= 0)
{
p.typeId() = ejectedParcelType_;
}
} }

View File

@ -73,6 +73,11 @@ protected:
//- Gravitational acceleration constant //- Gravitational acceleration constant
const dimensionedVector& g_; 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 // Cached injector fields per film patch
@ -88,6 +93,9 @@ protected:
//- Film density / patch face //- Film density / patch face
scalarList rhoFilmPatch_; scalarList rhoFilmPatch_;
//- Film height of all film patches / patch face
scalarListList deltaFilmPatch_;
// Counters // Counters
@ -104,6 +112,7 @@ protected:
virtual void cacheFilmFields virtual void cacheFilmFields
( (
const label filmPatchI, const label filmPatchI,
const label primaryPatchI,
const mapDistribute& distMap, const mapDistribute& distMap,
const surfaceFilmModels::surfaceFilmModel& filmModel const surfaceFilmModels::surfaceFilmModel& filmModel
); );
@ -206,8 +215,9 @@ public:
// Returns true if parcel is to be transferred // Returns true if parcel is to be transferred
virtual bool transferParcel virtual bool transferParcel
( (
const parcelType& p, parcelType& p,
const label patchI const polyPatch& pp,
bool& keepParticle
); );
//- Inject parcels into the cloud //- Inject parcels into the cloud

View File

@ -25,6 +25,460 @@ License
#include "ThermoSurfaceFilm.H" #include "ThermoSurfaceFilm.H"
#include "addToRunTimeSelectionTable.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 * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -37,9 +491,37 @@ Foam::ThermoSurfaceFilm<CloudType>::ThermoSurfaceFilm
) )
: :
SurfaceFilmModel<CloudType>(dict, owner, g, typeName), SurfaceFilmModel<CloudType>(dict, owner, g, typeName),
rndGen_(owner.rndGen()),
thermo_(owner.db().objectRegistry::lookupObject<SLGThermo>("SLGThermo")),
TFilmPatch_(0), 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> template<class CloudType>
@ -49,8 +531,18 @@ Foam::ThermoSurfaceFilm<CloudType>::ThermoSurfaceFilm
) )
: :
SurfaceFilmModel<CloudType>(sfm), SurfaceFilmModel<CloudType>(sfm),
rndGen_(sfm.rndGen_),
thermo_(sfm.thermo_),
TFilmPatch_(sfm.TFilmPatch_), 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> template<class CloudType>
bool Foam::ThermoSurfaceFilm<CloudType>::transferParcel bool Foam::ThermoSurfaceFilm<CloudType>::transferParcel
( (
const parcelType& p, parcelType& p,
const label patchI const polyPatch& pp,
bool& keepParticle
) )
{ {
// Retrieve the film model from the owner database // 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)) if (filmModel.isFilmPatch(patchI))
{ {
const polyPatch& pp = this->owner().mesh().boundaryMesh()[patchI];
const label faceI = pp.whichFace(p.face()); const label faceI = pp.whichFace(p.face());
// Patch face normal switch (interactionType_)
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)
{ {
Info<< "ThermoSurfaceFilm<CloudType>::transferParcel:" << nl case itBounce:
<< " Effective increase in film height = " {
<< p.nParticle()*p.volume()/mag(pp.faceAreas()[faceI]) << endl; 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; return true;
} }
else
{ // do not transfer parcel
return false; return false;
}
} }
@ -131,6 +636,7 @@ template<class CloudType>
void Foam::ThermoSurfaceFilm<CloudType>::cacheFilmFields void Foam::ThermoSurfaceFilm<CloudType>::cacheFilmFields
( (
const label filmPatchI, const label filmPatchI,
const label primaryPatchI,
const mapDistribute& distMap, const mapDistribute& distMap,
const surfaceFilmModels::surfaceFilmModel& filmModel const surfaceFilmModels::surfaceFilmModel& filmModel
) )
@ -138,6 +644,7 @@ void Foam::ThermoSurfaceFilm<CloudType>::cacheFilmFields
SurfaceFilmModel<CloudType>::cacheFilmFields SurfaceFilmModel<CloudType>::cacheFilmFields
( (
filmPatchI, filmPatchI,
primaryPatchI,
distMap, distMap,
filmModel filmModel
); );
@ -168,10 +675,12 @@ void Foam::ThermoSurfaceFilm<CloudType>::setParcelProperties
template<class CloudType> template<class CloudType>
void Foam::ThermoSurfaceFilm<CloudType>::info(Ostream& os) const void Foam::ThermoSurfaceFilm<CloudType>::info(Ostream& os) const
{ {
os << " Parcels transferred to film = " os << " Parcels absorbed into film = "
<< returnReduce(this->nParcelsTransferred(), sumOp<label>()) << nl << returnReduce(this->nParcelsTransferred(), sumOp<label>()) << nl
<< " Number of film parcels added = " << " New film detached parcels = "
<< returnReduce(this->nParcelsInjected(), sumOp<label>()) << nl; << returnReduce(this->nParcelsInjected(), sumOp<label>()) << nl
<< " New film splash parcels = "
<< returnReduce(nParcelsSplashed_, sumOp<label>()) << nl;
} }

View File

@ -27,6 +27,19 @@ Class
Description Description
Thermo parcel surface film model. 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 SourceFiles
ThermoSurfaceFilm.C ThermoSurfaceFilm.C
ThermoSurfaceFilmI.H ThermoSurfaceFilmI.H
@ -52,6 +65,31 @@ class ThermoSurfaceFilm
: :
public SurfaceFilmModel<CloudType> 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:
// Protected data // Protected data
@ -59,6 +97,12 @@ protected:
//- Convenience typedef to the cloud's parcel type //- Convenience typedef to the cloud's parcel type
typedef typename CloudType::parcelType parcelType; 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 // Cached injector fields per film patch
@ -69,24 +113,132 @@ protected:
scalarList CpFilmPatch_; scalarList CpFilmPatch_;
// Protected functions // Interaction model data
//- Cache the film fields in preparation for injection //- Interaction type enumeration
virtual void cacheFilmFields interactionType interactionType_;
(
const label filmPatchI,
const mapDistribute& distMap,
const surfaceFilmModels::surfaceFilmModel& filmModel
);
//- Set the individual parcel properties //- Film thickness beyond which patch is assumed to be wet
virtual void setParcelProperties 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 vector& tanVec1,
const label filmFaceI const vector& tanVec2,
const vector& nf
) const; ) 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: public:
//- Runtime type information //- Runtime type information
@ -128,8 +280,9 @@ public:
// Returns true if parcel is to be transferred // Returns true if parcel is to be transferred
virtual bool transferParcel virtual bool transferParcel
( (
const parcelType& p, parcelType& p,
const label patchI const polyPatch& pp,
bool& keepParticle
); );

View File

@ -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 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); << "U field not available for " << type() << abort(FatalError);
return volVectorField::null(); return volVectorField::null();
@ -147,7 +155,7 @@ const Foam::volVectorField& Foam::surfaceFilmModels::noFilm::U() const
const Foam::volVectorField& Foam::surfaceFilmModels::noFilm::Us() 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); << "Us field not available for " << type() << abort(FatalError);
return volVectorField::null(); return volVectorField::null();
@ -156,7 +164,7 @@ const Foam::volVectorField& Foam::surfaceFilmModels::noFilm::Us() const
const Foam::volVectorField& Foam::surfaceFilmModels::noFilm::Uw() 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); << "Uw field not available for " << type() << abort(FatalError);
return volVectorField::null(); return volVectorField::null();

View File

@ -126,6 +126,9 @@ public:
// Fields // Fields
//- Return the film thickness [m]
virtual const volScalarField& delta() const;
//- Return the film velocity [m/s] //- Return the film velocity [m/s]
virtual const volVectorField& U() const; virtual const volVectorField& U() const;

View File

@ -220,6 +220,9 @@ public:
// Fields // Fields
//- Return the film thickness [m]
virtual const volScalarField& delta() const = 0;
//- Return the film velocity [m/s] //- Return the film velocity [m/s]
virtual const volVectorField& U() const = 0; virtual const volVectorField& U() const = 0;