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
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

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>
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
{

View File

@ -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;
}

View File

@ -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_;
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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
);

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
{
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();

View File

@ -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;

View File

@ -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;