Reaction.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
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
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "Reaction.H"
27 
28 // * * * * * * * * * * * * * * * * Static Data * * * * * * * * * * * * * * * //
29 
30 template<class ReactionThermo>
32 
33 template<class ReactionThermo>
35 
36 template<class ReactionThermo>
38 
39 
40 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41 
42 template<class ReactionThermo>
44 {
45  return nUnNamedReactions++;
46 }
47 
48 
49 template<class ReactionThermo>
51 (
52  const HashPtrTable<ReactionThermo>& thermoDatabase
53 )
54 {
55  typename ReactionThermo::thermoType rhsThermo
56  (
57  rhs_[0].stoichCoeff
58  *(*thermoDatabase[species_[rhs_[0].index]]).W()
59  *(*thermoDatabase[species_[rhs_[0].index]])
60  );
61 
62  for (label i=1; i<rhs_.size(); ++i)
63  {
64  rhsThermo +=
65  rhs_[i].stoichCoeff
66  *(*thermoDatabase[species_[rhs_[i].index]]).W()
67  *(*thermoDatabase[species_[rhs_[i].index]]);
68  }
69 
70  typename ReactionThermo::thermoType lhsThermo
71  (
72  lhs_[0].stoichCoeff
73  *(*thermoDatabase[species_[lhs_[0].index]]).W()
74  *(*thermoDatabase[species_[lhs_[0].index]])
75  );
76 
77  for (label i=1; i<lhs_.size(); ++i)
78  {
79  lhsThermo +=
80  lhs_[i].stoichCoeff
81  *(*thermoDatabase[species_[lhs_[i].index]]).W()
82  *(*thermoDatabase[species_[lhs_[i].index]]);
83  }
84 
85  ReactionThermo::thermoType::operator=(lhsThermo == rhsThermo);
86 }
87 
88 
89 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
90 
91 template<class ReactionThermo>
93 (
94  const speciesTable& species,
95  const List<specieCoeffs>& lhs,
96  const List<specieCoeffs>& rhs,
97  const HashPtrTable<ReactionThermo>& thermoDatabase
98 )
99 :
100  ReactionThermo::thermoType(*thermoDatabase[species[0]]),
101  name_("un-named-reaction-" + Foam::name(getNewReactionID())),
102  species_(species),
103  Tlow_(TlowDefault),
104  Thigh_(ThighDefault),
105  lhs_(lhs),
106  rhs_(rhs)
107 {
108  setThermo(thermoDatabase);
109 }
110 
111 
112 template<class ReactionThermo>
114 (
115  const Reaction<ReactionThermo>& r,
116  const speciesTable& species
117 )
118 :
119  ReactionThermo::thermoType(r),
120  name_(r.name() + "Copy"),
121  species_(species),
122  Tlow_(r.Tlow()),
123  Thigh_(r.Thigh()),
124  lhs_(r.lhs_),
125  rhs_(r.rhs_)
126 {}
127 
128 
129 template<class ReactionThermo>
131 (
132  const speciesTable& species,
133  const HashPtrTable<ReactionThermo>& thermoDatabase,
134  const dictionary& dict
135 )
136 :
137  ReactionThermo::thermoType(*thermoDatabase[species[0]]),
138  name_(dict.dictName()),
139  species_(species),
140  Tlow_(dict.lookupOrDefault<scalar>("Tlow", TlowDefault)),
141  Thigh_(dict.lookupOrDefault<scalar>("Thigh", ThighDefault))
142 {
143  specieCoeffs::setLRhs
144  (
145  IStringStream(dict.lookup("reaction"))(),
146  species_,
147  lhs_,
148  rhs_
149  );
150  setThermo(thermoDatabase);
151 }
152 
153 
154 // * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
155 
156 template<class ReactionThermo>
159 (
160  const speciesTable& species,
161  const HashPtrTable<ReactionThermo>& thermoDatabase,
162  const dictionary& dict
163 )
164 {
165  const word& reactionTypeName = dict.lookup("type");
166 
167  typename dictionaryConstructorTable::iterator cstrIter
168  = dictionaryConstructorTablePtr_->find(reactionTypeName);
169 
170  if (cstrIter == dictionaryConstructorTablePtr_->end())
171  {
173  << "Unknown reaction type "
174  << reactionTypeName << nl << nl
175  << "Valid reaction types are :" << nl
176  << dictionaryConstructorTablePtr_->sortedToc()
177  << exit(FatalError);
178  }
179 
181  (
182  cstrIter()(species, thermoDatabase, dict)
183  );
184 }
185 
186 
187 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
188 
189 template<class ReactionThermo>
191 {
193  writeEntry
194  (
195  os,
196  "reaction",
197  specieCoeffs::reactionStr(reaction, species_, lhs_, rhs_)
198  );
199 }
200 
201 
202 template<class ReactionThermo>
204 (
205  const scalar p,
206  const scalar T,
207  const scalarField& c,
208  scalarField& d
209 ) const
210 {
211 }
212 
213 
214 template<class ReactionThermo>
216 (
217  const scalar p,
218  const scalar T,
219  const scalarField& c,
220  scalarField& f
221 ) const
222 {
223 }
224 
225 
226 template<class ReactionThermo>
228 (
229  const scalar p,
230  const scalar T,
231  const scalarField& c,
232  scalarField& dcdt
233 ) const
234 {
235  scalar pf, cf, pr, cr;
236  label lRef, rRef;
237 
238  scalar omegaI = omega
239  (
240  p, T, c, pf, cf, lRef, pr, cr, rRef
241  );
242 
243  forAll(lhs_, i)
244  {
245  const label si = lhs_[i].index;
246  const scalar sl = lhs_[i].stoichCoeff;
247  dcdt[si] -= sl*omegaI;
248  }
249  forAll(rhs_, i)
250  {
251  const label si = rhs_[i].index;
252  const scalar sr = rhs_[i].stoichCoeff;
253  dcdt[si] += sr*omegaI;
254  }
255 }
256 
257 
258 template<class ReactionThermo>
260 (
261  const scalar p,
262  const scalar T,
263  const scalarField& c,
264  scalar& pf,
265  scalar& cf,
266  label& lRef,
267  scalar& pr,
268  scalar& cr,
269  label& rRef
270 ) const
271 {
272 
273  scalar clippedT = min(max(T, this->Tlow()), this->Thigh());
274 
275  const scalar kf = this->kf(p, clippedT, c);
276  const scalar kr = this->kr(kf, p, clippedT, c);
277 
278  pf = 1;
279  pr = 1;
280 
281  const label Nl = lhs_.size();
282  const label Nr = rhs_.size();
283 
284  label slRef = 0;
285  lRef = lhs_[slRef].index;
286 
287  pf = kf;
288  for (label s = 1; s < Nl; s++)
289  {
290  const label si = lhs_[s].index;
291 
292  if (c[si] < c[lRef])
293  {
294  const scalar exp = lhs_[slRef].exponent;
295  pf *= pow(max(c[lRef], 0), exp);
296  lRef = si;
297  slRef = s;
298  }
299  else
300  {
301  const scalar exp = lhs_[s].exponent;
302  pf *= pow(max(c[si], 0), exp);
303  }
304  }
305  cf = max(c[lRef], 0);
306 
307  {
308  const scalar exp = lhs_[slRef].exponent;
309  if (exp < 1)
310  {
311  if (cf > small)
312  {
313  pf *= pow(cf, exp - 1);
314  }
315  else
316  {
317  pf = 0;
318  }
319  }
320  else
321  {
322  pf *= pow(cf, exp - 1);
323  }
324  }
325 
326  label srRef = 0;
327  rRef = rhs_[srRef].index;
328 
329  // Find the matrix element and element position for the rhs
330  pr = kr;
331  for (label s = 1; s < Nr; s++)
332  {
333  const label si = rhs_[s].index;
334  if (c[si] < c[rRef])
335  {
336  const scalar exp = rhs_[srRef].exponent;
337  pr *= pow(max(c[rRef], 0), exp);
338  rRef = si;
339  srRef = s;
340  }
341  else
342  {
343  const scalar exp = rhs_[s].exponent;
344  pr *= pow(max(c[si], 0), exp);
345  }
346  }
347  cr = max(c[rRef], 0);
348 
349  {
350  const scalar exp = rhs_[srRef].exponent;
351  if (exp < 1)
352  {
353  if (cr > small)
354  {
355  pr *= pow(cr, exp - 1);
356  }
357  else
358  {
359  pr = 0;
360  }
361  }
362  else
363  {
364  pr *= pow(cr, exp - 1);
365  }
366  }
367 
368  return pf*cf - pr*cr;
369 }
370 
371 
372 template<class ReactionThermo>
374 (
375  const scalar p,
376  const scalar T,
377  const scalarField& c,
379  scalarField& dcdt,
380  scalar& omegaI,
381  scalar& kfwd,
382  scalar& kbwd,
383  const bool reduced,
384  const List<label>& c2s
385 ) const
386 {
387  scalar pf, cf, pr, cr;
388  label lRef, rRef;
389 
390  omegaI = omega(p, T, c, pf, cf, lRef, pr, cr, rRef);
391 
392  forAll(lhs_, i)
393  {
394  const label si = reduced ? c2s[lhs_[i].index] : lhs_[i].index;
395  const scalar sl = lhs_[i].stoichCoeff;
396  dcdt[si] -= sl*omegaI;
397  }
398  forAll(rhs_, i)
399  {
400  const label si = reduced ? c2s[rhs_[i].index] : rhs_[i].index;
401  const scalar sr = rhs_[i].stoichCoeff;
402  dcdt[si] += sr*omegaI;
403  }
404 
405  kfwd = this->kf(p, T, c);
406  kbwd = this->kr(kfwd, p, T, c);
407 
408  forAll(lhs_, j)
409  {
410  const label sj = reduced ? c2s[lhs_[j].index] : lhs_[j].index;
411  scalar kf = kfwd;
412  forAll(lhs_, i)
413  {
414  const label si = lhs_[i].index;
415  const scalar el = lhs_[i].exponent;
416  if (i == j)
417  {
418  if (el < 1)
419  {
420  if (c[si] > SMALL)
421  {
422  kf *= el*pow(c[si] + VSMALL, el - 1);
423  }
424  else
425  {
426  kf = 0;
427  }
428  }
429  else
430  {
431  kf *= el*pow(c[si], el - 1);
432  }
433  }
434  else
435  {
436  kf *= pow(c[si], el);
437  }
438  }
439 
440  forAll(lhs_, i)
441  {
442  const label si = reduced ? c2s[lhs_[i].index] : lhs_[i].index;
443  const scalar sl = lhs_[i].stoichCoeff;
444  J(si, sj) -= sl*kf;
445  }
446  forAll(rhs_, i)
447  {
448  const label si = reduced ? c2s[rhs_[i].index] : rhs_[i].index;
449  const scalar sr = rhs_[i].stoichCoeff;
450  J(si, sj) += sr*kf;
451  }
452  }
453 
454  forAll(rhs_, j)
455  {
456  const label sj = reduced ? c2s[rhs_[j].index] : rhs_[j].index;
457  scalar kr = kbwd;
458  forAll(rhs_, i)
459  {
460  const label si = rhs_[i].index;
461  const scalar er = rhs_[i].exponent;
462  if (i == j)
463  {
464  if (er < 1)
465  {
466  if (c[si] > SMALL)
467  {
468  kr *= er*pow(c[si] + VSMALL, er - 1);
469  }
470  else
471  {
472  kr = 0;
473  }
474  }
475  else
476  {
477  kr *= er*pow(c[si], er - 1);
478  }
479  }
480  else
481  {
482  kr *= pow(c[si], er);
483  }
484  }
485 
486  forAll(lhs_, i)
487  {
488  const label si = reduced ? c2s[lhs_[i].index] : lhs_[i].index;
489  const scalar sl = lhs_[i].stoichCoeff;
490  J(si, sj) += sl*kr;
491  }
492  forAll(rhs_, i)
493  {
494  const label si = reduced ? c2s[rhs_[i].index] : rhs_[i].index;
495  const scalar sr = rhs_[i].stoichCoeff;
496  J(si, sj) -= sr*kr;
497  }
498  }
499 
500  // When third-body species are involved, additional terms are added
501  // beta function returns an empty list when third-body are not involved
502  const List<Tuple2<label, scalar>>& beta = this->beta();
503  if (notNull(beta))
504  {
505  // This temporary array needs to be cached for efficiency
506  scalarField dcidc(beta.size());
507  this->dcidc(p, T, c, dcidc);
508 
509  forAll(beta, j)
510  {
511  label sj = beta[j].first();
512  sj = reduced ? c2s[sj] : sj;
513  if (sj != -1)
514  {
515  forAll(lhs_, i)
516  {
517  const label si =
518  reduced ? c2s[lhs_[i].index] : lhs_[i].index;
519  const scalar sl = lhs_[i].stoichCoeff;
520  J(si, sj) -= sl*dcidc[j]*omegaI;
521  }
522  forAll(rhs_, i)
523  {
524  const label si =
525  reduced ? c2s[rhs_[i].index] : rhs_[i].index;
526  const scalar sr = rhs_[i].stoichCoeff;
527  J(si, sj) += sr*dcidc[j]*omegaI;
528  }
529  }
530  }
531  }
532 }
533 
534 
535 template<class ReactionThermo>
537 (
538  const scalar p,
539  const scalar T,
540  const scalarField& c,
541  const scalar omegaI,
542  const scalar kfwd,
543  const scalar kbwd,
545  const bool reduced,
546  const List<label>& c2s,
547  const label indexT
548 ) const
549 {
550  scalar kf = kfwd;
551  scalar kr = kbwd;
552 
553  scalar dkfdT = this->dkfdT(p, T, c);
554  scalar dkrdT = this->dkrdT(p, T, c, dkfdT, kr);
555 
556  scalar sumExp = 0.0;
557  forAll(lhs_, i)
558  {
559  const label si = lhs_[i].index;
560  const scalar el = lhs_[i].exponent;
561  const scalar cExp = pow(c[si], el);
562  dkfdT *= cExp;
563  kf *= cExp;
564  sumExp += el;
565  }
566  kf *= -sumExp/T;
567 
568  sumExp = 0.0;
569  forAll(rhs_, i)
570  {
571  const label si = rhs_[i].index;
572  const scalar er = rhs_[i].exponent;
573  const scalar cExp = pow(c[si], er);
574  dkrdT *= cExp;
575  kr *= cExp;
576  sumExp += er;
577  }
578  kr *= -sumExp/T;
579 
580  // dqidT includes the third-body (or pressure dependent) effect
581  scalar dqidT = dkfdT - dkrdT + kf - kr;
582 
583  // For reactions including third-body efficiencies or pressure dependent
584  // reaction, an additional term is needed
585  scalar dcidT = this->dcidT(p, T, c);
586  dcidT *= omegaI;
587 
588  // J(i, indexT) = sum_reactions nu_i dqdT
589  forAll(lhs_, i)
590  {
591  const label si = reduced ? c2s[lhs_[i].index] : lhs_[i].index;
592  const scalar sl = lhs_[i].stoichCoeff;
593  J(si, indexT) -= sl*(dqidT + dcidT);
594  }
595  forAll(rhs_, i)
596  {
597  const label si = reduced ? c2s[rhs_[i].index] : rhs_[i].index;
598  const scalar sr = rhs_[i].stoichCoeff;
599  J(si, indexT) += sr*(dqidT + dcidT);
600  }
601 }
602 
603 
604 template<class ReactionThermo>
606 {
607  return species_;
608 }
609 
610 
611 // ************************************************************************* //
void ddot(const scalar p, const scalar T, const scalarField &c, scalarField &d) const
Forward reaction rate.
Definition: Reaction.C:204
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:158
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
const word & name() const
Return the name of the reaction.
Definition: ReactionI.H:36
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
void dwdT(const scalar p, const scalar T, const scalarField &c, const scalar omegaI, const scalar kfwd, const scalar kbwd, scalarSquareMatrix &J, const bool reduced, const List< label > &c2s, const label indexT) const
Derivative of the net reaction rate for each species involved.
Definition: Reaction.C:537
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:163
void fdot(const scalar p, const scalar T, const scalarField &c, scalarField &f) const
Backward reaction rate.
Definition: Reaction.C:216
virtual void write(Ostream &) const
Write.
Definition: Reaction.C:190
static const scalar SMALL
Definition: scalar.H:112
A HashTable specialization for hashing pointers.
Definition: HashPtrTable.H:50
void omega(const scalar p, const scalar T, const scalarField &c, scalarField &dcdt) const
Net reaction rate for individual species.
Definition: Reaction.C:228
T & first()
Return the first element of the list.
Definition: UListI.H:114
Simple extension of ReactionThermo to handle reaction kinetics in addition to the equilibrium thermod...
Definition: Reaction.H:56
scalar Tlow() const
Return the lower temperature limit for the reaction.
Definition: ReactionI.H:43
static scalar TlowDefault
Default temperature limits of applicability of reaction rates.
Definition: Reaction.H:80
const word dictName() const
Return the local dictionary name (final part of scoped name)
Definition: dictionary.H:123
const speciesTable & species() const
Return the specie list.
Definition: Reaction.C:605
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
dimensionedScalar exp(const dimensionedScalar &ds)
A class for handling words, derived from string.
Definition: word.H:59
CombustionModel< rhoReactionThermo > & reaction
void dwdc(const scalar p, const scalar T, const scalarField &c, scalarSquareMatrix &J, scalarField &dcdt, scalar &omegaI, scalar &kfwd, scalar &kbwd, const bool reduced, const List< label > &c2s) const
Derivative of the net reaction rate for each species involved.
Definition: Reaction.C:374
static scalar ThighDefault
Definition: Reaction.H:80
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
static const char nl
Definition: Ostream.H:265
void writeEntry(Ostream &os, const HashTable< T, Key, Hash > &ht)
Definition: HashTableIO.C:96
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
const volScalarField & T
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
scalar Thigh() const
Return the upper temperature limit for the reaction.
Definition: ReactionI.H:50
bool notNull(const T &t)
Return true if t is not a reference to the nullObject of type T.
Definition: nullObjectI.H:52
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Reaction(const speciesTable &species, const List< specieCoeffs > &lhs, const List< specieCoeffs > &rhs, const HashPtrTable< ReactionThermo > &thermoDatabase)
Construct from components.
Definition: Reaction.C:93
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
static const scalar VSMALL
Definition: scalar.H:114
A wordList with hashed indices for faster lookup by name.
static autoPtr< Reaction< ReactionThermo > > New(const speciesTable &species, const HashPtrTable< ReactionThermo > &thermoDatabase, const dictionary &dict)
Return a pointer to new patchField created on freestore from dict.
Definition: Reaction.C:159
Input from memory buffer stream.
Definition: IStringStream.H:49
const scalarList W(::W(thermo))
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:52
static label nUnNamedReactions
Number of un-named reactions.
Definition: Reaction.H:77
Output to memory buffer stream.
Definition: OStringStream.H:49
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:583