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-2022 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 
29 // * * * * * * * * * * * * * * * * Static Data * * * * * * * * * * * * * * * //
30 
31 template<class ReactionThermo>
33 
34 template<class ReactionThermo>
36 
37 
38 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
39 
40 template<class ReactionThermo>
42 (
43  const HashPtrTable<ReactionThermo>& thermoDatabase
44 )
45 {
46  typename ReactionThermo::thermoType rhsThermo
47  (
48  rhs()[0].stoichCoeff
49  *(*thermoDatabase[species()[rhs()[0].index]]).W()
50  *(*thermoDatabase[species()[rhs()[0].index]])
51  );
52 
53  for (label i=1; i<rhs().size(); ++i)
54  {
55  rhsThermo +=
56  rhs()[i].stoichCoeff
57  *(*thermoDatabase[species()[rhs()[i].index]]).W()
58  *(*thermoDatabase[species()[rhs()[i].index]]);
59  }
60 
61  typename ReactionThermo::thermoType lhsThermo
62  (
63  lhs()[0].stoichCoeff
64  *(*thermoDatabase[species()[lhs()[0].index]]).W()
65  *(*thermoDatabase[species()[lhs()[0].index]])
66  );
67 
68  for (label i=1; i<lhs().size(); ++i)
69  {
70  lhsThermo +=
71  lhs()[i].stoichCoeff
72  *(*thermoDatabase[species()[lhs()[i].index]]).W()
73  *(*thermoDatabase[species()[lhs()[i].index]]);
74  }
75 
76  // Check for mass imbalance in the reaction
77  // A value of 1 corresponds to an error of 1 H atom in the reaction,
78  // i.e. 1 kg/kmol
79  if (mag(lhsThermo.Y() - rhsThermo.Y()) > 0.1)
80  {
82  << "Mass imbalance for reaction " << name() << ": "
83  << mag(lhsThermo.Y() - rhsThermo.Y()) << " kg/kmol"
84  << exit(FatalError);
85  }
86 
87  ReactionThermo::thermoType::operator=(lhsThermo == rhsThermo);
88 }
89 
90 
91 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
92 
93 template<class ReactionThermo>
95 (
96  const speciesTable& species,
97  const List<specieCoeffs>& lhs,
98  const List<specieCoeffs>& rhs,
99  const HashPtrTable<ReactionThermo>& thermoDatabase
100 )
101 :
102  reaction(species, lhs, rhs),
103  ReactionThermo::thermoType(*thermoDatabase[species[0]]),
104  Tlow_(TlowDefault),
105  Thigh_(ThighDefault)
106 {
107  setThermo(thermoDatabase);
108 }
109 
110 
111 template<class ReactionThermo>
113 (
114  const Reaction<ReactionThermo>& r,
115  const speciesTable& species
116 )
117 :
118  reaction(r, species),
119  ReactionThermo::thermoType(r),
120  Tlow_(r.Tlow()),
121  Thigh_(r.Thigh())
122 {}
123 
124 
125 template<class ReactionThermo>
127 (
128  const speciesTable& species,
129  const HashPtrTable<ReactionThermo>& thermoDatabase,
130  const dictionary& dict
131 )
132 :
133  reaction(species, dict),
134  ReactionThermo::thermoType(*thermoDatabase[species[0]]),
135  Tlow_(dict.lookupOrDefault<scalar>("Tlow", TlowDefault)),
136  Thigh_(dict.lookupOrDefault<scalar>("Thigh", ThighDefault))
137 {
138  setThermo(thermoDatabase);
139 }
140 
141 
142 // * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
143 
144 template<class ReactionThermo>
147 (
148  const speciesTable& species,
149  const HashPtrTable<ReactionThermo>& thermoDatabase,
150  const dictionary& dict
151 )
152 {
153  const word& reactionTypeName = dict.lookup("type");
154 
155  typename dictionaryConstructorTable::iterator cstrIter =
156  dictionaryConstructorTablePtr_->find(reactionTypeName);
157 
158  // Backwards compatibility check. Reaction names used to have "Reaction"
159  // (Reaction<ReactionThermo>::typeName_()) appended. This was removed as it
160  // is unnecessary given the context in which the reaction is specified. If
161  // this reaction name was not found, search also for the old name.
162  if (cstrIter == dictionaryConstructorTablePtr_->end())
163  {
164  cstrIter = dictionaryConstructorTablePtr_->find
165  (
166  reactionTypeName.removeTrailing(typeName_())
167  );
168  }
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 template<class ReactionThermo>
190 (
191  const speciesTable& species,
192  const HashPtrTable<ReactionThermo>& thermoDatabase,
193  const objectRegistry& ob,
194  const dictionary& dict
195 )
196 {
197  // If the objectRegistry constructor table is empty
198  // use the dictionary constructor table only
199  if (!objectRegistryConstructorTablePtr_)
200  {
201  return New(species, thermoDatabase, dict);
202  }
203 
204  const word& reactionTypeName = dict.lookup("type");
205 
206  typename objectRegistryConstructorTable::iterator cstrIter =
207  objectRegistryConstructorTablePtr_->find(reactionTypeName);
208 
209  // Backwards compatibility check. See above.
210  if (cstrIter == objectRegistryConstructorTablePtr_->end())
211  {
212  cstrIter = objectRegistryConstructorTablePtr_->find
213  (
214  reactionTypeName.removeTrailing(typeName_())
215  );
216  }
217 
218  if (cstrIter == objectRegistryConstructorTablePtr_->end())
219  {
220  typename dictionaryConstructorTable::iterator cstrIter =
221  dictionaryConstructorTablePtr_->find(reactionTypeName);
222 
223  // Backwards compatibility check. See above.
224  if (cstrIter == dictionaryConstructorTablePtr_->end())
225  {
226  cstrIter = dictionaryConstructorTablePtr_->find
227  (
228  reactionTypeName.removeTrailing(typeName_())
229  );
230  }
231 
232  if (cstrIter == dictionaryConstructorTablePtr_->end())
233  {
235  << "Unknown reaction type "
236  << reactionTypeName << nl << nl
237  << "Valid reaction types are :" << nl
238  << dictionaryConstructorTablePtr_->sortedToc()
239  << objectRegistryConstructorTablePtr_->sortedToc()
240  << exit(FatalError);
241  }
242 
244  (
245  cstrIter()(species, thermoDatabase, dict)
246  );
247  }
248 
250  (
251  cstrIter()(species, thermoDatabase, ob, dict)
252  );
253 }
254 
255 
256 template<class ReactionThermo>
259 (
260  const speciesTable& species,
261  const PtrList<ReactionThermo>& speciesThermo,
262  const dictionary& dict
263 )
264 {
265  HashPtrTable<ReactionThermo> thermoDatabase;
266  forAll(speciesThermo, i)
267  {
268  thermoDatabase.insert
269  (
270  speciesThermo[i].name(),
271  speciesThermo[i].clone().ptr()
272  );
273  }
274 
275  return New(species, thermoDatabase, dict);
276 }
277 
278 
279 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
280 
281 template<class ReactionThermo>
283 {
284  reaction::write(os);
285 }
286 
287 
288 template<class ReactionThermo>
290 (
291  const scalar p,
292  const scalar T,
293  const scalarField& c,
294  const label li,
295  scalar& Cf,
296  scalar& Cr
297 ) const
298 {
299  Cf = Cr = 1;
300 
301  forAll(lhs(), i)
302  {
303  const label si = lhs()[i].index;
304  const specieExponent& el = lhs()[i].exponent;
305  Cf *= c[si] >= small || el >= 1 ? pow(max(c[si], 0), el) : 0;
306  }
307 
308  forAll(rhs(), i)
309  {
310  const label si = rhs()[i].index;
311  const specieExponent& er = rhs()[i].exponent;
312  Cr *= c[si] >= small || er >= 1 ? pow(max(c[si], 0), er) : 0;
313  }
314 }
315 
316 
317 template<class ReactionThermo>
319 (
320  const scalar p,
321  const scalar T,
322  const scalarField& c,
323  const label li,
324  scalar& omegaf,
325  scalar& omegar
326 ) const
327 {
328  const scalar clippedT = min(max(T, this->Tlow()), this->Thigh());
329 
330  // Rate constants
331  const scalar kf = this->kf(p, clippedT, c, li);
332  const scalar kr = this->kr(kf, p, clippedT, c, li);
333 
334  // Concentration products
335  scalar Cf, Cr;
336  this->C(p, T, c, li, Cf, Cr);
337 
338  omegaf = kf*Cf;
339  omegar = kr*Cr;
340 
341  return omegaf - omegar;
342 }
343 
344 
345 template<class ReactionThermo>
347 (
348  const scalar p,
349  const scalar T,
350  const scalarField& c,
351  const label li,
352  scalarField& dNdtByV,
353  const bool reduced,
354  const List<label>& c2s,
355  const label Nsi0
356 ) const
357 {
358  scalar omegaf, omegar;
359  const scalar omega = this->omega(p, T, c, li, omegaf, omegar);
360 
361  forAll(lhs(), i)
362  {
363  const label si = reduced ? c2s[lhs()[i].index] : lhs()[i].index;
364  const scalar sl = lhs()[i].stoichCoeff;
365  dNdtByV[Nsi0 + si] -= sl*omega;
366  }
367  forAll(rhs(), i)
368  {
369  const label si = reduced ? c2s[rhs()[i].index] : rhs()[i].index;
370  const scalar sr = rhs()[i].stoichCoeff;
371  dNdtByV[Nsi0 + si] += sr*omega;
372  }
373 }
374 
375 
376 template<class ReactionThermo>
378 (
379  const scalar p,
380  const scalar T,
381  const scalarField& c,
382  const label li,
383  scalarField& dNdtByV,
384  scalarSquareMatrix& ddNdtByVdcTp,
385  const bool reduced,
386  const List<label>& c2s,
387  const label Nsi0,
388  const label Tsi,
389  scalarField& cTpWork0,
390  scalarField& cTpWork1
391 ) const
392 {
393  // Rate constants
394  const scalar kf = this->kf(p, T, c, li);
395  const scalar kr = this->kr(kf, p, T, c, li);
396 
397  // Concentration products
398  scalar Cf, Cr;
399  this->C(p, T, c, li, Cf, Cr);
400 
401  // Overall reaction rate
402  const scalar omega = kf*Cf - kr*Cr;
403 
404  // Specie reaction rates
405  forAll(lhs(), i)
406  {
407  const label si = reduced ? c2s[lhs()[i].index] : lhs()[i].index;
408  const scalar sl = lhs()[i].stoichCoeff;
409  dNdtByV[Nsi0 + si] -= sl*omega;
410  }
411  forAll(rhs(), i)
412  {
413  const label si = reduced ? c2s[rhs()[i].index] : rhs()[i].index;
414  const scalar sr = rhs()[i].stoichCoeff;
415  dNdtByV[Nsi0 + si] += sr*omega;
416  }
417 
418  // Jacobian contributions from the derivative of the concentration products
419  // w.r.t. concentration
420  {
421  forAll(lhs(), j)
422  {
423  const label sj = reduced ? c2s[lhs()[j].index] : lhs()[j].index;
424 
425  scalar dCfdcj = 1;
426  forAll(lhs(), i)
427  {
428  const label si = lhs()[i].index;
429  const specieExponent& el = lhs()[i].exponent;
430  if (i == j)
431  {
432  dCfdcj *=
433  c[si] >= small || el >= 1
434  ? el*pow(max(c[si], 0), el - specieExponent(label(1)))
435  : 0;
436  }
437  else
438  {
439  dCfdcj *=
440  c[si] >= small || el >= 1
441  ? pow(max(c[si], 0), el)
442  : 0;
443  }
444  }
445 
446  forAll(lhs(), i)
447  {
448  const label si = reduced ? c2s[lhs()[i].index] : lhs()[i].index;
449  const scalar sl = lhs()[i].stoichCoeff;
450  ddNdtByVdcTp(Nsi0 + si, Nsi0 + sj) -= sl*kf*dCfdcj;
451  }
452  forAll(rhs(), i)
453  {
454  const label si = reduced ? c2s[rhs()[i].index] : rhs()[i].index;
455  const scalar sr = rhs()[i].stoichCoeff;
456  ddNdtByVdcTp(Nsi0 + si, Nsi0 + sj) += sr*kf*dCfdcj;
457  }
458  }
459 
460  forAll(rhs(), j)
461  {
462  const label sj = reduced ? c2s[rhs()[j].index] : rhs()[j].index;
463 
464  scalar dCrcj = 1;
465  forAll(rhs(), i)
466  {
467  const label si = rhs()[i].index;
468  const specieExponent& er = rhs()[i].exponent;
469  if (i == j)
470  {
471  dCrcj *=
472  c[si] >= small || er >= 1
473  ? er*pow(max(c[si], 0), er - specieExponent(label(1)))
474  : 0;
475  }
476  else
477  {
478  dCrcj *=
479  c[si] >= small || er >= 1
480  ? pow(max(c[si], 0), er)
481  : 0;
482  }
483  }
484 
485  forAll(lhs(), i)
486  {
487  const label si = reduced ? c2s[lhs()[i].index] : lhs()[i].index;
488  const scalar sl = lhs()[i].stoichCoeff;
489  ddNdtByVdcTp(Nsi0 + si, Nsi0 + sj) += sl*kr*dCrcj;
490  }
491  forAll(rhs(), i)
492  {
493  const label si = reduced ? c2s[rhs()[i].index] : rhs()[i].index;
494  const scalar sr = rhs()[i].stoichCoeff;
495  ddNdtByVdcTp(Nsi0 + si, Nsi0 + sj) -= sr*kr*dCrcj;
496  }
497  }
498  }
499 
500  // Jacobian contributions from the derivative of the rate constants
501  // w.r.t. temperature
502  {
503  const scalar dkfdT = this->dkfdT(p, T, c, li);
504  const scalar dkrdT = this->dkrdT(p, T, c, li, dkfdT, kr);
505 
506  const scalar dwdT = dkfdT*Cf - dkrdT*Cr;
507  forAll(lhs(), i)
508  {
509  const label si = reduced ? c2s[lhs()[i].index] : lhs()[i].index;
510  const scalar sl = lhs()[i].stoichCoeff;
511  ddNdtByVdcTp(Nsi0 + si, Tsi) -= sl*dwdT;
512  }
513  forAll(rhs(), i)
514  {
515  const label si = reduced ? c2s[rhs()[i].index] : rhs()[i].index;
516  const scalar sr = rhs()[i].stoichCoeff;
517  ddNdtByVdcTp(Nsi0 + si, Tsi) += sr*dwdT;
518  }
519  }
520 
521  // Jacobian contributions from the derivative of the rate constants
522  // w.r.t. concentration
523  if (hasDkdc())
524  {
525  scalarField& dkfdc = cTpWork0;
526  scalarField& dkrdc = cTpWork1;
527 
528  this->dkfdc(p, T, c, li, dkfdc);
529  this->dkrdc(p, T, c, li, dkfdc, kr, dkrdc);
530 
531  forAll(c, j)
532  {
533  const label sj = reduced ? c2s[j] : j;
534 
535  if (sj == -1) continue;
536 
537  const scalar dwdc = dkfdc[j]*Cf - dkrdc[j]*Cr;
538  forAll(lhs(), i)
539  {
540  const label si = reduced ? c2s[lhs()[i].index] : lhs()[i].index;
541  const scalar sl = lhs()[i].stoichCoeff;
542  ddNdtByVdcTp(Nsi0 + si, Nsi0 + sj) -= sl*dwdc;
543  }
544  forAll(rhs(), i)
545  {
546  const label si = reduced ? c2s[rhs()[i].index] : rhs()[i].index;
547  const scalar sr = rhs()[i].stoichCoeff;
548  ddNdtByVdcTp(Nsi0 + si, Nsi0 + sj) += sr*dwdc;
549  }
550  }
551  }
552 }
553 
554 
555 // ************************************************************************* //
dictionary dict
Graphite solid properties.
Definition: C.H:48
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
void dNdtByV(const scalar p, const scalar T, const scalarField &c, const label li, scalarField &dNdtByV, const bool reduced, const List< label > &c2s, const label Nsi0) const
The net reaction rate for each species involved.
Definition: Reaction.C:347
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
FvWallInfoData< WallInfo, label > label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
autoPtr< CompressibleMomentumTransportModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const viscosity &viscosity)
scalar omega(const scalar p, const scalar T, const scalarField &c, const label li, scalar &omegaf, scalar &omegar) const
Net reaction rate.
Definition: Reaction.C:319
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:156
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
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
combustionModel & reaction
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
virtual void write(Ostream &) const
Write.
Definition: Reaction.C:282
A HashTable specialisation for hashing pointers.
Definition: HashPtrTable.H:50
Simple extension of ReactionThermo to handle reaction kinetics in addition to the equilibrium thermod...
Definition: Reaction.H:55
static scalar TlowDefault
Default temperature limits of applicability of reaction rates.
Definition: Reaction.H:79
bool insert(const Key &, const T * &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
scalar Tlow() const
Return the lower temperature limit for the reaction.
Definition: ReactionI.H:31
T clone(const T &t)
Definition: List.H:54
A class for handling words, derived from string.
Definition: word.H:59
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
scalar Thigh() const
Return the upper temperature limit for the reaction.
Definition: ReactionI.H:38
static scalar ThighDefault
Definition: Reaction.H:79
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:54
static const char nl
Definition: Ostream.H:260
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
void ddNdtByVdcTp(const scalar p, const scalar T, const scalarField &c, const label li, scalarField &dNdtByV, scalarSquareMatrix &ddNdtByVdcTp, const bool reduced, const List< label > &c2s, const label csi0, const label Tsi, scalarField &cTpWork0, scalarField &cTpWork1) const
Derivative of the net reaction rate for each species involved.
Definition: Reaction.C:378
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:95
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
void C(const scalar p, const scalar T, const scalarField &c, const label li, scalar &Cf, scalar &Cr) const
Concentration powers.
Definition: Reaction.C:290
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.
Definition: Reaction.C:147
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: List.H:70
const scalarList W(::W(thermo))
dimensioned< scalar > mag(const dimensioned< Type > &)
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:52
Registry of regIOobjects.
bool removeTrailing(const char)
Remove trailing character returning true if string changed.
Definition: string.C:176
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:864