ENH: Adding volumeFraction to allow PairCollision models to take

account of nParticles to expand the effective parcel size for
collision.
This commit is contained in:
graham
2010-05-18 15:54:31 +01:00
parent 7fa1ff7938
commit 09188eb8c6
9 changed files with 107 additions and 29 deletions

View File

@ -213,7 +213,7 @@ void Foam::PairCollision<CloudType>::wallInteraction()
const point& pos = p.position(); const point& pos = p.position();
scalar r = p.d()/2; scalar r = wallModel_->pREff(p);
// real wallFace interactions // real wallFace interactions

View File

@ -54,7 +54,7 @@ class PairModel
{ {
// Private data // Private data
//- The cloud dictionary //- The CollisionModel dictionary
const dictionary& dict_; const dictionary& dict_;
//- Reference to the owner cloud class //- Reference to the owner cloud class

View File

@ -45,13 +45,15 @@ void Foam::PairSpringSliderDashpot<CloudType>::findMinMaxProperties
// Finding minimum diameter to avoid excessive arithmetic // Finding minimum diameter to avoid excessive arithmetic
RMin = min(p.d(), RMin); scalar dEff = p.d()*cbrt(p.nParticle()*volumeFactor_);
RMin = min(dEff, RMin);
rhoMax = max(p.rho(), rhoMax); rhoMax = max(p.rho(), rhoMax);
UMagMax = max UMagMax = max
( (
mag(p.U()) + mag(p.omega())*p.d()/2, mag(p.U()) + mag(p.omega())*dEff/2,
UMagMax UMagMax
); );
} }
@ -91,7 +93,8 @@ Foam::PairSpringSliderDashpot<CloudType>::PairSpringSliderDashpot
( (
this->coeffDict().lookup("collisionResolutionSteps") this->coeffDict().lookup("collisionResolutionSteps")
) )
) ),
volumeFactor_(this->dict().lookupOrDefault("volumeFactor", 1.0))
{ {
scalar nu = this->owner().constProps().poissonsRatio(); scalar nu = this->owner().constProps().poissonsRatio();
@ -155,7 +158,11 @@ void Foam::PairSpringSliderDashpot<CloudType>::evaluatePair
{ {
vector r_AB = (pA.position() - pB.position()); vector r_AB = (pA.position() - pB.position());
scalar normalOverlapMag = 0.5*(pA.d() + pB.d()) - mag(r_AB); scalar dAEff = pA.d()*cbrt(pA.nParticle()*volumeFactor_);
scalar dBEff = pB.d()*cbrt(pB.nParticle()*volumeFactor_);
scalar normalOverlapMag = 0.5*(dAEff + dBEff) - mag(r_AB);
if (normalOverlapMag > 0) if (normalOverlapMag > 0)
{ {
@ -166,7 +173,7 @@ void Foam::PairSpringSliderDashpot<CloudType>::evaluatePair
vector U_AB = pA.U() - pB.U(); vector U_AB = pA.U() - pB.U();
// Effective radius // Effective radius
scalar R = 0.5*pA.d()*pB.d()/(pA.d() + pB.d()); scalar R = 0.5*dAEff*dBEff/(dAEff + dBEff);
// Effective mass // Effective mass
scalar M = pA.mass()*pB.mass()/(pA.mass() + pB.mass()); scalar M = pA.mass()*pB.mass()/(pA.mass() + pB.mass());
@ -185,8 +192,8 @@ void Foam::PairSpringSliderDashpot<CloudType>::evaluatePair
vector USlip_AB = vector USlip_AB =
U_AB - (U_AB & rHat_AB)*rHat_AB U_AB - (U_AB & rHat_AB)*rHat_AB
+ (pA.omega() ^ (pA.d()/2*-rHat_AB)) + (pA.omega() ^ (dAEff/2*-rHat_AB))
- (pB.omega() ^ (pB.d()/2*rHat_AB)); - (pB.omega() ^ (dBEff/2*rHat_AB));
scalar deltaT = this->owner().mesh().time().deltaTValue(); scalar deltaT = this->owner().mesh().time().deltaTValue();
@ -241,8 +248,8 @@ void Foam::PairSpringSliderDashpot<CloudType>::evaluatePair
pA.f() += fT_AB; pA.f() += fT_AB;
pB.f() += -fT_AB; pB.f() += -fT_AB;
pA.torque() += (pA.d()/2*-rHat_AB) ^ fT_AB; pA.torque() += (dAEff/2*-rHat_AB) ^ fT_AB;
pB.torque() += (pB.d()/2*rHat_AB) ^ -fT_AB; pB.torque() += (dBEff/2*rHat_AB) ^ -fT_AB;
} }
} }
} }

View File

@ -74,6 +74,24 @@ class PairSpringSliderDashpot
// harmonic approximation of the collision period // harmonic approximation of the collision period
scalar collisionResolutionSteps_; scalar collisionResolutionSteps_;
//- Volume factor for determining the equivalent size of a
// parcel where nParticles is not 1. The equivalent size of
// the parcel is
// parcelEquivVolume = volumeFactor*nParticles*p.volume()
// so
// parcelEquivD = cbrt(volumeFactor*nParticles)*p.d()
// + When volumeFactor = 1, the particles are compressed
// together so that the equivalent volume of the parcel is
// the sum of the constituent particles
// + When volumeFactor = 3*sqrt(2)/pi, the particles are
// close packed, but uncompressed.
// + When volumeFactor > 3*sqrt(2)/pi, the particles loosely
// grouped.
// 3*sqrt(2)/pi = 1.350474 is the volume factor for close
// packing, i.e pi/(3*sqrt(2)) is the maximum close packing
// factor
scalar volumeFactor_;
// Private Member Functions // Private Member Functions
@ -104,6 +122,12 @@ public:
// Member Functions // Member Functions
//- Return the volumeFactor
inline scalar volumeFactor() const
{
return volumeFactor_;
}
//- Whether the PairModel has a timestep limit that will //- Whether the PairModel has a timestep limit that will
// require subCycling // require subCycling
virtual bool controlsTimestep() const; virtual bool controlsTimestep() const;

View File

@ -54,7 +54,7 @@ class WallModel
{ {
// Private data // Private data
//- The cloud dictionary //- The CollisionModel dictionary
const dictionary& dict_; const dictionary& dict_;
//- Reference to the owner cloud class //- Reference to the owner cloud class
@ -120,6 +120,9 @@ public:
// Member Functions // Member Functions
//- Return the effective radius for a particle for the model
virtual scalar pREff(const typename CloudType::parcelType& p) const = 0;
//- Whether the WallModel has a timestep limit that will //- Whether the WallModel has a timestep limit that will
// require subCycling // require subCycling
virtual bool controlsTimestep() const = 0; virtual bool controlsTimestep() const = 0;

View File

@ -44,13 +44,16 @@ void Foam::WallSpringSliderDashpot<CloudType>::findMinMaxProperties
const typename CloudType::parcelType& p = iter(); const typename CloudType::parcelType& p = iter();
// Finding minimum diameter to avoid excessive arithmetic // Finding minimum diameter to avoid excessive arithmetic
rMin = min(p.d(), rMin);
scalar dEff = p.d()*cbrt(p.nParticle()*volumeFactor_);
rMin = min(dEff, rMin);
rhoMax = max(p.rho(), rhoMax); rhoMax = max(p.rho(), rhoMax);
UMagMax = max UMagMax = max
( (
mag(p.U()) + mag(p.omega())*p.d()/2, mag(p.U()) + mag(p.omega())*dEff/2,
UMagMax UMagMax
); );
} }
@ -69,18 +72,17 @@ void Foam::WallSpringSliderDashpot<CloudType>::evaluateWall
const WallSiteData<vector>& data, const WallSiteData<vector>& data,
scalar pNu, scalar pNu,
scalar pE, scalar pE,
scalar pREff,
scalar Estar, scalar Estar,
scalar kN, scalar kN,
scalar Gstar scalar Gstar
) const ) const
{ {
scalar pR = p.d()/2;
vector r_PW = p.position() - site; vector r_PW = p.position() - site;
vector U_PW = p.U() - data.wallData(); vector U_PW = p.U() - data.wallData();
scalar normalOverlapMag = pR - mag(r_PW); scalar normalOverlapMag = pREff - mag(r_PW);
vector rHat_PW = r_PW/(mag(r_PW) + VSMALL); vector rHat_PW = r_PW/(mag(r_PW) + VSMALL);
@ -94,7 +96,7 @@ void Foam::WallSpringSliderDashpot<CloudType>::evaluateWall
vector USlip_PW = vector USlip_PW =
U_PW - (U_PW & rHat_PW)*rHat_PW U_PW - (U_PW & rHat_PW)*rHat_PW
+ (p.omega() ^ (pR*-rHat_PW)); + (p.omega() ^ (pREff*-rHat_PW));
scalar deltaT = this->owner().mesh().time().deltaTValue(); scalar deltaT = this->owner().mesh().time().deltaTValue();
@ -108,7 +110,7 @@ void Foam::WallSpringSliderDashpot<CloudType>::evaluateWall
if (tangentialOverlapMag > VSMALL) if (tangentialOverlapMag > VSMALL)
{ {
scalar kT = 8.0*sqrt(pR*normalOverlapMag)*Gstar; scalar kT = 8.0*sqrt(pREff*normalOverlapMag)*Gstar;
scalar etaT = etaN; scalar etaT = etaN;
@ -134,7 +136,7 @@ void Foam::WallSpringSliderDashpot<CloudType>::evaluateWall
p.f() += fT_PW; p.f() += fT_PW;
p.torque() += (pR*-rHat_PW) ^ fT_PW; p.torque() += (pREff*-rHat_PW) ^ fT_PW;
} }
} }
@ -160,7 +162,8 @@ Foam::WallSpringSliderDashpot<CloudType>::WallSpringSliderDashpot
( (
this->coeffDict().lookup("collisionResolutionSteps") this->coeffDict().lookup("collisionResolutionSteps")
) )
) ),
volumeFactor_(this->dict().lookupOrDefault("volumeFactor", 1.0))
{} {}
@ -173,6 +176,15 @@ Foam::WallSpringSliderDashpot<CloudType>::~WallSpringSliderDashpot()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class CloudType>
Foam::scalar Foam::WallSpringSliderDashpot<CloudType>::pREff
(
const typename CloudType::parcelType& p
) const
{
return p.d()/2*cbrt(p.nParticle()*volumeFactor_);
}
template<class CloudType> template<class CloudType>
bool Foam::WallSpringSliderDashpot<CloudType>::controlsTimestep() const bool Foam::WallSpringSliderDashpot<CloudType>::controlsTimestep() const
{ {
@ -225,9 +237,11 @@ void Foam::WallSpringSliderDashpot<CloudType>::evaluateWall
scalar pE = this->owner().constProps().youngsModulus(); scalar pE = this->owner().constProps().youngsModulus();
scalar pREff = this->pREff(p);
scalar Estar = 1/((1 - sqr(pNu))/pE + (1 - sqr(nu_))/E_); scalar Estar = 1/((1 - sqr(pNu))/pE + (1 - sqr(nu_))/E_);
scalar kN = (4.0/3.0)*sqrt(p.d()/2)*Estar; scalar kN = (4.0/3.0)*sqrt(pREff)*Estar;
scalar GStar = 1/(2*((2 + pNu - sqr(pNu))/pE + (2 + nu_ - sqr(nu_))/E_)); scalar GStar = 1/(2*((2 + pNu - sqr(pNu))/pE + (2 + nu_ - sqr(nu_))/E_));
@ -240,6 +254,7 @@ void Foam::WallSpringSliderDashpot<CloudType>::evaluateWall
flatSiteData[siteI], flatSiteData[siteI],
pNu, pNu,
pE, pE,
pREff,
Estar, Estar,
kN, kN,
GStar GStar
@ -257,6 +272,7 @@ void Foam::WallSpringSliderDashpot<CloudType>::evaluateWall
sharpSiteData[siteI], sharpSiteData[siteI],
pNu, pNu,
pE, pE,
pREff,
Estar, Estar,
kN, kN,
GStar GStar

View File

@ -69,6 +69,24 @@ class WallSpringSliderDashpot
// harmonic approximation of the collision period // harmonic approximation of the collision period
scalar collisionResolutionSteps_; scalar collisionResolutionSteps_;
//- Volume factor for determining the equivalent size of a
// parcel where nParticles is not 1. The equivalent size of
// the parcel is
// parcelEquivVolume = volumeFactor*nParticles*p.volume()
// so
// parcelEquivD = cbrt(volumeFactor*nParticles)*p.d()
// + When volumeFactor = 1, the particles are compressed
// together so that the equivalent volume of the parcel is
// the sum of the constituent particles
// + When volumeFactor = 3*sqrt(2)/pi, the particles are
// close packed, but uncompressed.
// + When volumeFactor > 3*sqrt(2)/pi, the particles loosely
// grouped.
// 3*sqrt(2)/pi = 1.350474 is the volume factor for close
// packing, i.e pi/(3*sqrt(2)) is the maximum close packing
// factor
scalar volumeFactor_;
// Private Member Functions // Private Member Functions
@ -89,6 +107,7 @@ class WallSpringSliderDashpot
const WallSiteData<vector>& data, const WallSiteData<vector>& data,
scalar pNu, scalar pNu,
scalar pE, scalar pE,
scalar pREff,
scalar Estar, scalar Estar,
scalar kN, scalar kN,
scalar Gstar scalar Gstar
@ -113,6 +132,15 @@ public:
// Member Functions // Member Functions
//- Return the volumeFactor
inline scalar volumeFactor() const
{
return volumeFactor_;
}
//- Return the effective radius for a particle for the model
virtual scalar pREff(const typename CloudType::parcelType& p) const;
//- Whether the WallModel has a timestep limit that will //- Whether the WallModel has a timestep limit that will
// require subCycling // require subCycling
virtual bool controlsTimestep() const; virtual bool controlsTimestep() const;

View File

@ -217,7 +217,7 @@ Foam::scalar Foam::InjectionModel<CloudType>::setNumberOfParticles
} }
case pbFixed: case pbFixed:
{ {
nP = nParticlesFixed_; nP = nParticleFixed_;
break; break;
} }
default: default:
@ -290,7 +290,7 @@ Foam::InjectionModel<CloudType>::InjectionModel(CloudType& owner)
nInjections_(0), nInjections_(0),
parcelsAddedTotal_(0), parcelsAddedTotal_(0),
parcelBasis_(pbNumber), parcelBasis_(pbNumber),
nParticlesFixed_(0.0), nParticleFixed_(0.0),
time0_(0.0), time0_(0.0),
timeStep0_(0.0) timeStep0_(0.0)
{ {
@ -316,7 +316,7 @@ Foam::InjectionModel<CloudType>::InjectionModel
nInjections_(0), nInjections_(0),
parcelsAddedTotal_(0), parcelsAddedTotal_(0),
parcelBasis_(pbNumber), parcelBasis_(pbNumber),
nParticlesFixed_(0.0), nParticleFixed_(0.0),
time0_(owner.db().time().value()), time0_(owner.db().time().value()),
timeStep0_(0.0) timeStep0_(0.0)
{ {
@ -340,11 +340,11 @@ Foam::InjectionModel<CloudType>::InjectionModel
{ {
parcelBasis_ = pbFixed; parcelBasis_ = pbFixed;
Info<< " Choosing nParticles to be a fixed value, massTotal " Info<< " Choosing nParticle to be a fixed value, massTotal "
<< "variable now does not determine anything." << "variable now does not determine anything."
<< endl; << endl;
nParticlesFixed_ = readScalar(coeffDict_.lookup("nParticles")); nParticleFixed_ = readScalar(coeffDict_.lookup("nParticle"));
} }
else else
{ {

View File

@ -138,9 +138,9 @@ protected:
//- Parcel basis enumeration //- Parcel basis enumeration
parcelBasis parcelBasis_; parcelBasis parcelBasis_;
//- nParticles to assign to parcels when the 'fixed' basis //- nParticle to assign to parcels when the 'fixed' basis
// is selected // is selected
scalar nParticlesFixed_; scalar nParticleFixed_;
//- Continuous phase time at start of injection time step [s] //- Continuous phase time at start of injection time step [s]
scalar time0_; scalar time0_;