ReactingHeterogeneousParcel.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2018-2019 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
29 #include "mathematicalConstants.H"
30 
31 using namespace Foam::constant::mathematical;
32 
33 
34 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
35 
36 template<class ParcelType>
37 template<class TrackCloudType>
39 (
40  TrackCloudType& cloud,
41  trackingData& td,
42  const scalar p,
43  const scalar T,
44  const label idS
45 ) const
46 {
47  return cloud.composition().Cp(idS, this->Y_, p, T);
48 }
49 
50 
51 template<class ParcelType>
52 template<class TrackCloudType>
54 (
55  TrackCloudType& cloud,
56  trackingData& td,
57  const scalar p,
58  const scalar T,
59  const label idS
60 ) const
61 {
62  return cloud.composition().Hs(idS, this->Y_, p, T);
63 }
64 
65 
66 template<class ParcelType>
67 template<class TrackCloudType>
69 (
70  TrackCloudType& cloud,
71  trackingData& td,
72  const scalar p,
73  const scalar T,
74  const label idS
75 ) const
76 {
77  return cloud.composition().L(idS, this->Y_, p, T);
78 }
79 
80 
81 // * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * //
82 
83 template<class ParcelType>
84 template<class TrackCloudType>
86 (
87  TrackCloudType& cloud,
88  trackingData& td,
89  const scalar dt
90 )
91 {
92  typedef typename TrackCloudType::reactingCloudType reactingCloudType;
93 
95  cloud.composition();
96 
97  // Define local properties at beginning of timestep
98  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99 
100  const scalar np0 = this->nParticle_;
101  const scalar d0 = this->d_;
102  const vector& U0 = this->U_;
103  const scalar T0 = this->T_;
104  const scalar mass0 = this->mass();
105 
106  const scalar pc = td.pc();
107 
108  const label idS = composition.idSolid();
109 
110  // Calc surface values
111  scalar Ts, rhos, mus, Prs, kappas;
112  this->calcSurfaceValues(cloud, td, T0, Ts, rhos, mus, Prs, kappas);
113  scalar Res = this->Re(rhos, U0, td.Uc(), d0, mus);
114 
115  // Sources
116  //~~~~~~~~
117 
118  // Explicit momentum source for particle
119  vector Su = Zero;
120 
121  // Linearised momentum source coefficient
122  scalar Spu = 0.0;
123 
124  // Momentum transfer from the particle to the carrier phase
125  vector dUTrans = Zero;
126 
127  // Explicit enthalpy source for particle
128  scalar Sh = 0.0;
129 
130  // Linearised enthalpy source coefficient
131  scalar Sph = 0.0;
132 
133  // Sensible enthalpy transfer from the particle to the carrier phase
134  scalar dhsTrans = 0.0;
135 
136  // Molar flux of species emitted from the particle (kmol/m^2/s)
137  scalar Ne = 0.0;
138 
139  // Surface concentrations of emitted species
140  scalarField Cs(composition.carrier().species().size(), 0.0);
141 
142  // Sum Ni*Cpi*Wi of emission species
143  scalar NCpW = 0.0;
144 
145 
146  // Heterogeneous reactions
147  // ~~~~~~~~~~~~~~~~~
148 
149  // Change in carrier phase composition due to surface reactions
150  scalarField dMassSRSolid(this->Y_.size(), 0.0);
151  scalarField dMassSRCarrier(composition.carrier().species().size(), 0.0);
152 
153  // Calc mass and enthalpy transfer due to reactions
154  calcHeterogeneousReactions
155  (
156  cloud,
157  td,
158  dt,
159  Res,
160  mus/rhos,
161  d0,
162  T0,
163  mass0,
164  canCombust_,
165  Ne,
166  NCpW,
167  this->Y_,
168  F_,
169  dMassSRSolid,
170  dMassSRCarrier,
171  Sh,
172  dhsTrans
173  );
174 
175  // 2. Update the parcel properties due to change in mass
176  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
177 
178  scalarField dMassSolid(dMassSRSolid);
179 
180  scalar mass1 = mass0 - sum(dMassSolid);
181 
182  // Remove the particle when mass falls below minimum threshold
183  if (np0*mass1 < cloud.constProps().minParcelMass())
184  {
185  td.keepParticle = false;
186 
187  return;
188  }
189 
190  // Only solid is used to update mass fractions
191  (void)this->updateMassFraction(mass0, dMassSolid, this->Y_);
192 
193 
194  // Update particle density or diameter
195  if (cloud.constProps().constantVolume())
196  {
197  this->rho_ = mass1/this->volume();
198  }
199  else
200  {
201  this->d_ = cbrt(mass1/this->rho_*6.0/pi);
202  }
203 
204  // Correct surface values due to emitted species
205  this->correctSurfaceValues(cloud, td, Ts, Cs, rhos, mus, Prs, kappas);
206  Res = this->Re(rhos, U0, td.Uc(), this->d_, mus);
207 
208 
209  // 3. Compute heat- and momentum transfers
210  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
211 
212  // Heat transfer
213  // ~~~~~~~~~~~~~
214 
215  // Calculate new particle temperature
216  this->T_ =
217  this->calcHeatTransfer
218  (
219  cloud,
220  td,
221  dt,
222  Res,
223  Prs,
224  kappas,
225  NCpW,
226  Sh,
227  dhsTrans,
228  Sph
229  );
230 
231  //DebugVar(np0);
232 
233  this->Cp_ = CpEff(cloud, td, pc, this->T_, idS);
234 
235  // Motion
236  // ~~~~~~
237 
238  // Calculate new particle velocity
239  this->U_ =
240  this->calcVelocity(cloud, td, dt, Res, mus, mass1, Su, dUTrans, Spu);
241 
242 
243  // 4. Accumulate carrier phase source terms
244  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
245 
246  if (cloud.solution().coupled())
247  {
248  // No mapping between solid components and carrier phase
249  /*
250  forAll(this->Y_, i)
251  {
252  scalar dm = np0*dMassSolid[i];
253  label gid = composition.localToCarrierId(SLD, i);
254  scalar hs = composition.carrier().Hs(gid, pc, T0);
255  cloud.rhoTrans(gid)[this->cell()] += dm;
256  cloud.UTrans()[this->cell()] += dm*U0;
257  cloud.hsTrans()[this->cell()] += dm*hs;
258  }
259  */
260 
261  forAll(dMassSRCarrier, i)
262  {
263  scalar dm = np0*dMassSRCarrier[i];
264  scalar hs = composition.carrier().Hs(i, pc, T0);
265  cloud.rhoTrans(i)[this->cell()] += dm;
266  cloud.UTrans()[this->cell()] += dm*U0;
267  cloud.hsTrans()[this->cell()] += dm*hs;
268  }
269 
270  // Update momentum transfer
271  cloud.UTrans()[this->cell()] += np0*dUTrans;
272  cloud.UCoeff()[this->cell()] += np0*Spu;
273 
274  // Update sensible enthalpy transfer
275  cloud.hsTrans()[this->cell()] += np0*dhsTrans;
276  cloud.hsCoeff()[this->cell()] += np0*Sph;
277 
278  // Update radiation fields
279  if (cloud.radiation())
280  {
281  const scalar ap = this->areaP();
282  const scalar T4 = pow4(T0);
283  cloud.radAreaP()[this->cell()] += dt*np0*ap;
284  cloud.radT4()[this->cell()] += dt*np0*T4;
285  cloud.radAreaPT4()[this->cell()] += dt*np0*ap*T4;
286  }
287  }
288 }
289 
290 
291 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
292 
293 template<class ParcelType>
294 template<class TrackCloudType>
296 (
297  TrackCloudType& cloud,
298  trackingData& td,
299  const scalar dt,
300  const scalar Re,
301  const scalar nu,
302  const scalar d,
303  const scalar T,
304  const scalar mass,
305  const label canCombust,
306  const scalar Ne,
307  scalar& NCpW,
308  const scalarField& YSolid,
309  scalarField& F,
310  scalarField& dMassSRSolid,
311  scalarField& dMassSRCarrier,
312  scalar& Sh,
313  scalar& dhsTrans
314 ) const
315 {
316  // Check that model is active
317  if (!cloud.heterogeneousReaction().active())
318  {
319  return;
320  }
321 
322  // Initialise demand-driven constants
323  (void)cloud.constProps().hRetentionCoeff();
324  (void)cloud.constProps().TMax();
325 
326  // Check that model is active
327  if (canCombust != 1)
328  {
329  return;
330  }
331 
332  // Update reactions
333  const scalar hReaction = cloud.heterogeneousReaction().calculate
334  (
335  dt,
336  Re,
337  nu,
338  this->cell(),
339  d,
340  T,
341  td.Tc(),
342  td.pc(),
343  td.rhoc(),
344  mass,
345  YSolid,
346  F,
347  Ne,
348  NCpW,
349  dMassSRSolid,
350  dMassSRCarrier
351  );
352 
353  cloud.heterogeneousReaction().addToSurfaceReactionMass
354  (
355  this->nParticle_*sum(dMassSRSolid)
356  );
357 
358  const scalar xsi = min(T/cloud.constProps().TMax(), 1.0);
359  const scalar coeff =
360  (1.0 - xsi*xsi)*cloud.constProps().hRetentionCoeff();
361 
362  Sh += coeff*hReaction/dt;
363 
364  dhsTrans += (1.0 - coeff)*hReaction;
365 }
366 
367 
368 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
369 
370 template<class ParcelType>
372 (
374 )
375 :
376  ParcelType(p),
377  F_(p.F_),
378  canCombust_(p.canCombust_)
379 {}
380 
381 
382 template<class ParcelType>
384 (
385  const ReactingHeterogeneousParcel<ParcelType>& p,
386  const polyMesh& mesh
387 )
388 :
389  ParcelType(p, mesh),
390  F_(p.F_),
391  canCombust_(p.canCombust_)
392 {}
393 
394 
395 // * * * * * * * * * * * * * * IOStream operators * * * * * * * * * * * * * //
396 
398 
399 // ************************************************************************* //
mathematicalConstants.H
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
F
volVectorField F(fluid.F())
Foam::fieldTypes::volume
const wordList volume
Standard volume field types (scalar, vector, tensor, etc)
Foam::ReactingHeterogeneousParcel::trackingData
ParcelType::trackingData trackingData
Use base tracking data.
Definition: ReactingHeterogeneousParcel.H:109
composition
basicSpecieMixture & composition
Definition: createFieldRefs.H:6
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
nu
volScalarField & nu
Definition: readMechanicalProperties.H:176
Su
zeroField Su
Definition: alphaSuSp.H:1
Foam::ReactingHeterogeneousParcel
Reacting heterogeneous Parcel.
Definition: ReactingHeterogeneousParcel.H:52
Foam::CompositionModel
Templated reacting parcel composition model class Consists of carrier species (via thermo package),...
Definition: ReactingCloud.H:58
Foam::pow4
dimensionedScalar pow4(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:100
Foam::Field< scalar >
ReactingHeterogeneousParcelIO.C
Foam::T
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
Definition: FieldFieldFunctions.C:58
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::ReactingHeterogeneousParcel::ReactingHeterogeneousParcel
ReactingHeterogeneousParcel(const polyMesh &mesh, const barycentric &coordinates, const label celli, const label tetFacei, const label tetPti)
Construct from mesh, position and topology.
Definition: ReactingHeterogeneousParcelI.H:65
Foam::cloud
A cloud is a registry collection of lagrangian particles.
Definition: cloud.H:57
Foam::constant::mathematical
Mathematical constants.
Foam::constant::mathematical::pi
constexpr scalar pi(M_PI)
Foam::Vector< scalar >
Foam::ReactingHeterogeneousParcel::calcHeterogeneousReactions
void calcHeterogeneousReactions(TrackCloudType &cloud, trackingData &td, const scalar dt, const scalar Res, const scalar nu, const scalar d, const scalar T, const scalar mass, const label canCombust, const scalar N, scalar &NCpW, const scalarField &YSolid, scalarField &F, scalarField &dMassSRSolid, scalarField &dMassSRCarrier, scalar &Sh, scalar &dhsTrans) const
Calculate surface reactions.
Definition: ReactingHeterogeneousParcel.C:296
Foam::Re
scalarField Re(const UList< complex > &cf)
Extract real component.
Definition: complexField.C:159
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
Cs
const scalarField & Cs
Definition: solveBulkSurfactant.H:10
Foam::cbrt
dimensionedScalar cbrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:155
T0
scalar T0
Definition: createFields.H:22
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:54
Foam::ReactingHeterogeneousParcel::calc
void calc(TrackCloudType &cloud, trackingData &td, const scalar dt)
Update parcel properties over the time interval.
Definition: ReactingHeterogeneousParcel.C:86
ReactingHeterogeneousParcel.H