35 template<
class CloudType>
38 typename CloudType::parcelType::trackingData& td,
50 occupancy[iter().cell()]++;
62 pInCell(iter().
cell(), occupancy[iter().
cell()]++) = &iter();
65 for (
label celli=0; celli<this->owner().mesh().nCells(); celli++)
69 if (pInCelli.
size() >= 2)
78 scalar m1 = p1.nParticle()*p1.mass();
79 scalar m2 = p2.nParticle()*p2.mass();
81 bool massChanged = collideParcels(dt, p1, p2, m1, m2);
88 p1.setCellValues(this->owner(), td);
89 p1.rho() = liquids.
rho(td.pc(), p1.T(), X);
90 p1.Cp() = liquids.
Cp(td.pc(), p1.T(), X);
91 p1.sigma() = liquids.
sigma(td.pc(), p1.T(), X);
92 p1.mu() = liquids.
mu(td.pc(), p1.T(), X);
93 p1.d() =
cbrt(6.0*m1/(p1.nParticle()*p1.rho()*
pi));
99 p2.setCellValues(this->owner(), td);
100 p2.rho() = liquids.
rho(td.pc(), p2.T(), X);
101 p2.Cp() = liquids.
Cp(td.pc(), p2.T(), X);
102 p2.sigma() = liquids.
sigma(td.pc(), p2.T(), X);
103 p2.mu() = liquids.
mu(td.pc(), p2.T(), X);
104 p2.d() =
cbrt(6.0*m2/(p2.nParticle()*p2.rho()*
pi));
116 scalar mass = p.nParticle()*p.mass();
118 if (mass < this->owner().constProps().minParcelMass())
120 this->owner().deleteParticle(p);
126 template<
class CloudType>
137 if ((m1 < rootVSmall) || (m2 < rootVSmall))
142 const scalar Vc = this->owner().mesh().V()[p1.cell()];
143 const scalar d1 = p1.d();
144 const scalar d2 = p2.d();
146 scalar magUrel =
mag(p1.U() - p2.U());
147 scalar sumD = d1 + d2;
149 scalar nMin =
min(p1.nParticle(), p2.nParticle());
150 scalar nu = nMin*nu0;
151 scalar collProb =
exp(-nu);
152 scalar xx = this->owner().rndGen().template sample01<scalar>();
159 return collideSorted(dt, p1, p2, m1, m2);
163 return collideSorted(dt, p2, p1, m2, m1);
173 template<
class CloudType>
183 const scalar nP1 = p1.nParticle();
184 const scalar nP2 = p2.nParticle();
186 const scalar sigma1 = p1.sigma();
187 const scalar sigma2 = p2.sigma();
189 const scalar d1 = p1.d();
190 const scalar d2 = p2.d();
192 const scalar T1 = p1.T();
193 const scalar T2 = p2.T();
195 const scalar
rho1 = p1.rho();
196 const scalar
rho2 = p2.rho();
198 const vector& U1 = p1.U();
199 const vector& U2 = p2.U();
203 scalar magURel =
mag(URel);
205 scalar
mTot = m1 + m2;
207 scalar gamma = d1/
max(rootVSmall, d2);
208 scalar
f =
pow3(gamma) + 2.7*gamma - 2.4*
sqr(gamma);
211 scalar Tave = (T1*m1 + T2*m2)/mTot;
214 scalar sigmaAve = sigma1;
215 if (
mag(T2 - T1) > small)
217 sigmaAve += (sigma2 - sigma1)*(Tave - T1)/(T2 - T1);
220 scalar Vtot = m1/rho1 + m2/
rho2;
221 scalar rhoAve = mTot/Vtot;
223 scalar dAve =
sqrt(d1*d2);
224 scalar WeColl = 0.5*rhoAve*
sqr(magURel)*dAve/
max(rootVSmall, sigmaAve);
226 scalar coalesceProb =
min(1.0, 2.4*f/
max(rootVSmall, WeColl));
228 scalar prob = this->owner().rndGen().template sample01<scalar>();
231 if (coalescence_ && prob < coalesceProb)
234 scalar nProb = prob*nP2/nP1;
240 scalar dm = nP1*nProb*m2/scalar(nP2);
245 p1.T() = (Tave*mTot - m2*T2)/m1;
247 p1.U() = (m1*U1 + (1.0 - m2/m2Org)*m2*U2)/m1;
249 p1.Y() = (m1Org*p1.Y() + dm*p2.Y())/m1;
251 p2.nParticle() = m2/(rho2*p2.volume());
258 scalar gf =
sqrt(prob) -
sqrt(coalesceProb);
259 scalar denom = 1.0 -
sqrt(coalesceProb);
273 vector mr = m1*U1 + m2*U2;
274 vector v1p = (mr + m2*gf*URel)/mTot;
275 vector v2p = (mr - m1*gf*URel)/mTot;
280 p2.U() = (nP1*v2p + (nP2 - nP1)*U2)/nP2;
284 p1.U() = (nP2*v1p + (nP1 - nP2)*U1)/nP1;
295 template<
class CloudType>
300 const word& modelName
304 coalescence_(this->coeffDict().lookup(
"coalescence"))
308 template<
class CloudType>
321 template<
class CloudType>
ORourkeCollision(const dictionary &dict, CloudType &cloud, const word &modelName=typeName)
Construct from dictionary.
scalar Cp(const scalar p, const scalar T, const scalarField &X) const
Calculate the mixture heat capacity [J/kg/K].
const volScalarField & rho1
#define forAll(list, i)
Loop across all elements in list.
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
fluidReactionThermo & thermo
A list of keyword definitions, which are a keyword followed by any number of values (e...
dimensionedSymmTensor sqr(const dimensionedVector &dv)
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
dimensionedScalar sqrt(const dimensionedScalar &ds)
virtual void collide(typename CloudType::parcelType::trackingData &td, const scalar dt)
Main collision routine.
virtual ~ORourkeCollision()
Destructor.
scalar mu(const scalar p, const scalar T, const scalarField &X) const
Calculate the mixture viscosity [Pa s].
Templated base class for thermodynamic cloud.
scalar rho(const scalar p, const scalar T, const scalarField &X) const
Calculate the mixture density [kg/m^3].
dimensionedScalar exp(const dimensionedScalar &ds)
scalarField X(const scalarField &Y) const
Returns the mole fractions corresponding to the given mass fractions.
A class for handling words, derived from string.
scalar sigma(const scalar p, const scalar T, const scalarField &X) const
Estimate mixture surface tension [N/m].
dimensionedScalar cbrt(const dimensionedScalar &ds)
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
virtual bool collideParcels(const scalar dt, parcelType &p1, parcelType &p2, scalar &m1, scalar &m2)
Collide parcels and return true if mass has changed.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
A packed storage unstructured matrix of objects of type <T> using an offset table for access...
CloudType::parcelType parcelType
Convenience typedef to the cloud's parcel type.
virtual bool collideSorted(const scalar dt, parcelType &p1, parcelType &p2, scalar &m1, scalar &m2)
Collision model by P.J. O'Rourke.
dimensionedScalar pow3(const dimensionedScalar &ds)
const volScalarField & rho2
A cell is defined as a list of faces with extra functionality.
Templated stochastic collision model class.
dimensioned< scalar > mag(const dimensioned< Type > &)
label size() const
Return the number of elements in the UList.
Templated base class for dsmc cloud.
Switch coalescence_
Coalescence activation switch.