36 template<
class ParcelType>
37 template<
class TrackCloudType>
40 TrackCloudType& cloud,
60 typedef typename TrackCloudType::thermoCloudType thermoCloudType;
64 typedef typename TrackCloudType::reactingCloudType reactingCloudType;
74 scalar Tvap = phaseChange.
Tvap(X);
81 const scalar TMax = phaseChange.
TMax(td.pc(), X);
82 const scalar Tdash =
min(T, TMax);
83 const scalar Tsdash =
min(Ts, TMax);
85 const typename TrackCloudType::parcelType& p =
86 static_cast<const typename TrackCloudType::parcelType&
>(*this);
87 typename TrackCloudType::parcelType::trackingData& ttd =
88 static_cast<typename TrackCloudType::parcelType::trackingData&
>(td);
109 dMassPC =
min(mass*YPhase*Y, dMassPC);
111 const scalar dMassTot =
sum(dMassPC);
120 const scalar dh = phaseChange.
dh(cid, i, td.pc(), Tdash);
121 Sh -= dMassPC[i]*dh/dt;
126 if (cloud.heatTransfer().BirdCorrection())
129 const scalar Wc = td.rhoc()*
RR*td.Tc()/td.pc();
135 const scalar
Cp = composition.
carrier().Cp(cid, td.pc(), Tsdash);
136 const scalar
W = composition.
carrier().Wi(cid);
137 const scalar Ni = dMassPC[i]/(this->areaS(d)*dt*
W);
140 composition.
liquids().properties()[i].D(td.pc(), Tsdash, Wc);
149 Cs[cid] += Ni*d/(2.0*Dab);
155 template<
class ParcelType>
163 scalar mass1 = mass0 -
sum(dMass);
166 if (mass1 > rootVSmall)
170 Y[i] = (Y[i]*mass0 - dMass[i])/mass1;
180 template<
class ParcelType>
192 template<
class ParcelType>
207 template<
class ParcelType>
208 template<
class TrackCloudType>
211 TrackCloudType& cloud,
215 ParcelType::setCellValues(cloud, td);
217 td.pc() = td.pInterp().interpolate
220 this->currentTetIndices()
223 if (td.pc() < cloud.constProps().pMin())
228 <<
"Limiting observed pressure in cell " << this->
cell()
229 <<
" to " << cloud.constProps().pMin() <<
nl <<
endl;
232 td.pc() = cloud.constProps().pMin();
237 template<
class ParcelType>
238 template<
class TrackCloudType>
241 TrackCloudType& cloud,
246 scalar addedMass = 0.0;
247 scalar maxMassI = 0.0;
248 forAll(cloud.rhoTrans(), i)
250 scalar dm = cloud.rhoTrans(i)[this->
cell()];
251 maxMassI =
max(maxMassI,
mag(dm));
255 if (maxMassI < rootVSmall)
260 const scalar massCell = this->massCell(td);
262 td.rhoc() += addedMass/cloud.pMesh().cellVolumes()[this->
cell()];
264 const scalar massCellNew = massCell + addedMass;
265 td.Uc() = (td.Uc()*massCell + cloud.UTransRef()[this->
cell()])/massCellNew;
268 forAll(cloud.rhoTrans(), i)
270 scalar Y = cloud.rhoTrans(i)[this->
cell()]/addedMass;
271 CpEff += Y*cloud.composition().carrier().Cp(i, td.pc(), td.Tc());
274 const scalar Cpc = td.CpInterp().psi()[this->
cell()];
275 td.Cpc() = (massCell*Cpc + addedMass*CpEff)/massCellNew;
277 td.Tc() += cloud.hsTransRef()[this->
cell()]/(td.Cpc()*massCellNew);
279 if (td.Tc() < cloud.constProps().TMin())
284 <<
"Limiting observed temperature in cell " << this->
cell()
285 <<
" to " << cloud.constProps().TMin() <<
nl <<
endl;
288 td.Tc() = cloud.constProps().TMin();
293 template<
class ParcelType>
294 template<
class TrackCloudType>
297 TrackCloudType& cloud,
308 if (!cloud.heatTransfer().BirdCorrection() || (
sum(Cs) < small))
320 Xinf[i] = carrier.
Y(i)[this->
cell()]/carrier.
Wi(i);
325 const scalar Xsff = 1.0 -
min(
sum(Cs)*
RR*this->T_/td.pc(), 1.0);
328 const scalar CsTot = td.pc()/(
RR*this->T_);
339 const scalar Csi = Cs[i] + Xsff*Xinf[i]*CsTot;
341 Xs[i] = (2.0*Csi + Xinf[i]*CsTot)/3.0;
342 Ys[i] = Xs[i]*carrier.
Wi(i);
352 scalar sumYiSqrtW = 0;
353 scalar sumYiCbrtW = 0;
357 const scalar
W = carrier.
Wi(i);
358 const scalar sqrtW =
sqrt(W);
359 const scalar cbrtW =
cbrt(W);
362 mus += Ys[i]*sqrtW*carrier.
mu(i, td.pc(),
T);
363 kappas += Ys[i]*cbrtW*carrier.
kappa(i, td.pc(),
T);
364 Cps += Xs[i]*carrier.
Cp(i, td.pc(),
T);
366 sumYiSqrtW += Ys[i]*sqrtW;
367 sumYiCbrtW += Ys[i]*cbrtW;
370 Cps =
max(Cps, rootVSmall);
372 rhos *= td.pc()/(
RR*
T);
373 rhos =
max(rhos, rootVSmall);
376 mus =
max(mus, rootVSmall);
378 kappas /= sumYiCbrtW;
379 kappas =
max(kappas, rootVSmall);
381 Prs = Cps*mus/kappas;
385 template<
class ParcelType>
386 template<
class TrackCloudType>
389 TrackCloudType& cloud,
394 typedef typename TrackCloudType::thermoCloudType thermoCloudType;
402 const scalar np0 = this->nParticle_;
403 const scalar d0 = this->d_;
404 const vector& U0 = this->U_;
405 const scalar
T0 = this->T_;
406 const scalar mass0 = this->mass();
410 scalar Ts, rhos, mus, Prs, kappas;
411 this->calcSurfaceValues(cloud, td, T0, Ts, rhos, mus, Prs, kappas);
412 scalar Res = this->
Re(rhos, U0, td.Uc(), d0, mus);
434 scalar dhsTrans = 0.0;
483 scalar mass1 = updateMassFraction(mass0, dMass, Y_);
485 this->Cp_ = composition.
Cp(0, Y_, td.pc(),
T0);
488 if (cloud.constProps().constantVolume())
490 this->rho_ = mass1/this->volume();
494 this->d_ =
cbrt(mass1/this->rho_*6.0/
pi);
498 if (np0*mass1 < cloud.constProps().minParcelMass())
500 td.keepParticle =
false;
502 if (cloud.solution().coupled())
504 scalar dm = np0*mass0;
509 scalar dmi = dm*Y_[i];
511 scalar hs = composition.
carrier().Hs(gid, td.pc(),
T0);
513 cloud.rhoTrans(gid)[this->
cell()] += dmi;
514 cloud.hsTransRef()[this->
cell()] += dmi*hs;
516 cloud.UTransRef()[this->
cell()] += dm*U0;
518 cloud.phaseChange().addToPhaseChangeMass(np0*mass1);
525 correctSurfaceValues(cloud, td, Ts, Cs, rhos, mus, Prs, kappas);
526 Res = this->
Re(rhos, U0, td.Uc(), this->d(), mus);
537 this->calcHeatTransfer
551 this->Cp_ = composition.
Cp(0, Y_, td.pc(),
T0);
559 this->calcVelocity(cloud, td, dt, Res, mus, mass1, Su, dUTrans, Spu);
565 if (cloud.solution().coupled())
570 scalar dm = np0*dMass[i];
572 scalar hs = composition.
carrier().Hs(gid, td.pc(),
T0);
574 cloud.rhoTrans(gid)[this->
cell()] += dm;
575 cloud.UTransRef()[this->
cell()] += dm*U0;
576 cloud.hsTransRef()[this->
cell()] += dm*hs;
580 cloud.UTransRef()[this->
cell()] += np0*dUTrans;
581 cloud.UCoeffRef()[this->
cell()] += np0*Spu;
584 cloud.hsTransRef()[this->
cell()] += np0*dhsTrans;
585 cloud.hsCoeffRef()[this->
cell()] += np0*Sph;
588 if (cloud.radiation())
590 const scalar ap = this->areaP();
591 const scalar T4 =
pow4(T0);
592 cloud.radAreaP()[this->
cell()] += dt*np0*ap;
593 cloud.radT4()[this->
cell()] += dt*np0*T4;
594 cloud.radAreaPT4()[this->
cell()] += dt*np0*ap*T4;
virtual scalar TMax(const scalar p, const scalarField &X) const
Return maximum/limiting temperature.
#define forAll(list, i)
Loop across all elements in list.
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
Templated phase change model class.
virtual scalar kappa(const label speciei, const scalar p, const scalar T) const =0
Thermal conductivity [W/m/K].
void calcPhaseChange(TrackCloudType &cloud, trackingData &td, const scalar dt, const scalar Re, const scalar Pr, const scalar Ts, const scalar nus, const scalar d, const scalar T, const scalar mass, const label idPhase, const scalar YPhase, const scalarField &YComponents, scalarField &dMassPC, scalar &Sh, scalar &N, scalar &NCpW, scalarField &Cs)
Calculate Phase change.
basicSpecieMixture & composition
scalar updateMassFraction(const scalar mass0, const scalarField &dMass, scalarField &Y) const
Update mass fraction.
void size(const label)
Override size to be inconsistent with allocated storage.
scalarField Y_
Mass fractions of mixture [].
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
ReactingParcel(const polyMesh &mesh, const barycentric &coordinates, const label celli, const label tetFacei, const label tetPti)
Construct from mesh, coordinates and topology.
twoPhaseChangeModel & phaseChange
virtual scalar Wi(const label speciei) const =0
Molecular weight of the given specie [kg/kmol].
label localToCarrierId(const label phaseI, const label id, const bool allowNotFound=false) const
Return carrier id of component given local id.
void addToPhaseChangeMass(const scalar dMass)
Add to phase change mass.
virtual scalar Cp(const label phaseI, const scalarField &Y, const scalar p, const scalar T) const
Return specific heat capacity for the phase phaseI.
Specialisation of basicMixture for a mixture consisting of a number for molecular species...
void cellValueSourceCorrection(TrackCloudType &cloud, trackingData &td, const scalar dt)
Correct cell values using latest transfer information.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
ParcelType::trackingData trackingData
Use base tracking data.
const dimensionedScalar RR
Universal gas constant: default SI units: [J/kmol/K].
virtual scalar Cp(const label speciei, const scalar p, const scalar T) const =0
Heat capacity at constant pressure [J/kg/K].
virtual scalar mu(const label speciei, const scalar p, const scalar T) const =0
Dynamic viscosity [kg/m/s].
dimensionedScalar cbrt(const dimensionedScalar &ds)
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
void correctSurfaceValues(TrackCloudType &cloud, trackingData &td, const scalar T, const scalarField &Cs, scalar &rhos, scalar &mus, scalar &Prs, scalar &kappas)
Correct surface values due to emitted species.
virtual void calculate(const typename CloudType::parcelType &p, const typename CloudType::parcelType::trackingData &td, const scalar dt, const scalar Re, const scalar Pr, const scalar d, const scalar nu, const scalar T, const scalar Ts, const scalar pc, const scalar Tc, const scalarField &X, scalarField &dMassPC) const =0
Update model.
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
virtual scalar dh(const label idc, const label idl, const scalar p, const scalar T) const
Return the enthalpy per unit mass.
#define WarningInFunction
Report a warning using Foam::Warning.
A cell is defined as a list of faces with extra functionality.
const scalarList W(::W(thermo))
dimensionedScalar pow4(const dimensionedScalar &ds)
scalar Cp(const scalar p, const scalar T) const
void setCellValues(TrackCloudType &cloud, trackingData &td)
Set cell values.
dimensioned< scalar > mag(const dimensioned< Type > &)
Mesh consisting of general polyhedral cells.
const tmp< volScalarField::Internal > & Su
Reacting parcel class with one/two-way coupling with the continuous phase.
scalar mass0_
Initial mass [kg].
PtrList< volScalarField > & Y()
Return the mass-fraction fields.
Templated reacting parcel composition model class Consists of carrier species (via thermo package)...
virtual scalar Tvap(const scalarField &X) const
Return vapourisation temperature.
scalarField Re(const UList< complex > &cf)
const basicSpecieMixture & carrier() const
Return the carrier components (wrapper function)
void calc(TrackCloudType &cloud, trackingData &td, const scalar dt)
Update parcel properties over the time interval.
const speciesTable & species() const
Return the table of species.
const liquidMixtureProperties & liquids() const
Return the global (additional) liquids.