1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "ReactingParcel.H"
29 // * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * //
31 template<class ParcelType>
32 template<class TrackData>
33 void Foam::ReactingParcel<ParcelType>::setCellValues
40 ThermoParcel<ParcelType>::setCellValues(td, dt, cellI);
42 pc_ = td.pInterp().interpolate(this->position(), cellI);
43 if (pc_ < td.constProps().pMin())
47 "void Foam::ReactingParcel<ParcelType>::setCellValues"
53 ) << "Limiting observed pressure in cell " << cellI << " to "
54 << td.constProps().pMin() << nl << endl;
56 pc_ = td.constProps().pMin();
61 template<class ParcelType>
62 template<class TrackData>
63 void Foam::ReactingParcel<ParcelType>::cellValueSourceCorrection
70 scalar massCell = this->massCell(cellI);
72 scalar addedMass = 0.0;
73 forAll(td.cloud().rhoTrans(), i)
75 addedMass += td.cloud().rhoTrans(i)[cellI];
78 this->rhoc_ += addedMass/td.cloud().pMesh().cellVolumes()[cellI];
80 scalar massCellNew = massCell + addedMass;
81 this->Uc_ += td.cloud().UTrans()[cellI]/massCellNew;
84 if (addedMass > ROOTVSMALL)
86 forAll(td.cloud().rhoTrans(), i)
88 scalar Y = td.cloud().rhoTrans(i)[cellI]/addedMass;
90 Y*td.cloud().mcCarrierThermo().speciesData()[i].Cp(this->Tc_);
93 const scalar cpc = td.cpInterp().psi()[cellI];
94 this->cpc_ = (massCell*cpc + addedMass*cpEff)/massCellNew;
96 this->Tc_ += td.cloud().hsTrans()[cellI]/(this->cpc_*massCellNew);
100 template<class ParcelType>
101 Foam::scalar Foam::ReactingParcel<ParcelType>::updateMassFraction
104 const scalarField& dMass,
108 scalar mass1 = mass0 - sum(dMass);
110 // only update the mass fractions if the new particle mass is finite
111 if (mass1 > ROOTVSMALL)
115 Y[i] = (Y[i]*mass0 - dMass[i])/mass1;
123 template<class ParcelType>
124 template<class TrackData>
125 void Foam::ReactingParcel<ParcelType>::calc
132 // Define local properties at beginning of time step
133 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
134 const scalar np0 = this->nParticle_;
135 const scalar d0 = this->d_;
136 const vector& U0 = this->U_;
137 const scalar rho0 = this->rho_;
138 const scalar T0 = this->T_;
139 const scalar cp0 = this->cp_;
140 const scalar mass0 = this->mass();
142 // Explicit momentum source for particle
143 vector Su = vector::zero;
145 // Momentum transfer from the particle to the carrier phase
146 vector dUTrans = vector::zero;
148 // Explicit enthalpy source for particle
151 // Sensible enthalpy transfer from the particle to the carrier phase
152 scalar dhsTrans = 0.0;
158 // Mass transfer due to phase change
159 scalarField dMassPC(Y_.size(), 0.0);
161 // Calc mass and enthalpy transfer due to phase change
179 // Update particle component mass and mass fractions
180 scalar mass1 = updateMassFraction(mass0, dMassPC, Y_);
186 // Calculate new particle temperature
188 calcHeatTransfer(td, dt, cellI, d0, U0, rho0, T0, cp0, Sh, dhsTrans);
194 // Calculate new particle velocity
195 vector U1 = calcVelocity(td, dt, cellI, d0, U0, rho0, mass0, Su, dUTrans);
197 dUTrans += 0.5*(mass0 - mass1)*(U0 + U1);
199 // Accumulate carrier phase source terms
200 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
201 if (td.cloud().coupled())
203 // Transfer mass lost from particle to carrier mass source
206 label gid = td.cloud().composition().localToGlobalCarrierId(0, i);
207 td.cloud().rhoTrans(gid)[cellI] += np0*dMassPC[i];
208 td.cloud().hcTrans()[cellI] +=
211 *td.cloud().mcCarrierThermo().speciesData()[gid].H(T0);
214 // Update momentum transfer
215 td.cloud().UTrans()[cellI] += np0*dUTrans;
217 // Update sensible enthalpy transfer
218 td.cloud().hsTrans()[cellI] += np0*dhsTrans;
222 // Remove the particle when mass falls below minimum threshold
223 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
224 if (mass1 < td.constProps().minParticleMass())
226 td.keepParticle = false;
228 if (td.cloud().coupled())
230 // Absorb parcel into carrier phase
234 td.cloud().composition().localToGlobalCarrierId(0, i);
235 td.cloud().rhoTrans(gid)[cellI] += np0*mass1*Y_[i];
237 td.cloud().UTrans()[cellI] += np0*mass1*U1;
238 td.cloud().hcTrans()[cellI] +=
239 np0*mass1*td.cloud().composition().H(0, Y_, pc_, T1);
244 // Set new particle properties
245 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
249 this->cp_ = td.cloud().composition().cp(0, Y_, pc_, T1);
253 // Update particle density or diameter
254 if (td.constProps().constantVolume())
256 this->rho_ = mass1/this->volume();
260 this->d_ = cbrt(mass1/this->rho_*6.0/mathematicalConstant::pi);
266 template<class ParcelType>
267 template<class TrackData>
268 void Foam::ReactingParcel<ParcelType>::calcPhaseChange
279 const scalarField& YComponents,
280 scalarField& dMassPC,
287 !td.cloud().phaseChange().active()
288 || T < td.constProps().Tvap()
295 // Calculate mass transfer due to phase change
296 td.cloud().phaseChange().calculate
301 min(T, td.constProps().Tbp()), // Limit to boiling temperature
304 this->muc_/(this->rhoc_ + ROOTVSMALL),
309 // Limit phase change mass by availability of each specie
310 dMassPC = min(mass*YPhase*YComponents, dMassPC);
312 scalar dMassTot = sum(dMassPC);
314 // Add to cumulative phase change mass
315 td.cloud().addToMassPhaseChange(this->nParticle_*dMassTot);
317 // Enthalphy transfer to carrier phase
319 forAll(YComponents, i)
321 id = td.cloud().composition().localToGlobalCarrierId(idPhase, i);
322 const scalar hv = td.cloud().mcCarrierThermo().speciesData()[id].H(T);
324 id = td.cloud().composition().globalIds(idPhase)[i];
326 td.cloud().composition().liquids().properties()[id].h(pc_, T);
328 Sh += dMassPC[i]*(hl - hv)/dt;
333 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
335 template <class ParcelType>
336 Foam::ReactingParcel<ParcelType>::ReactingParcel
338 const ReactingParcel<ParcelType>& p
341 ThermoParcel<ParcelType>(p),
348 // * * * * * * * * * * * * * * IOStream operators * * * * * * * * * * * * * //
350 #include "ReactingParcelIO.C"
352 // ************************************************************************* //