StandardChemistryModel.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-2020 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 "StandardChemistryModel.H"
27 #include "multiComponentMixture.H"
28 #include "UniformField.H"
30 
31 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
32 
33 template<class ReactionThermo, class ThermoType>
35 (
36  const ReactionThermo& thermo
37 )
38 :
40  ODESystem(),
41  Y_(this->thermo().composition().Y()),
42  specieThermos_
43  (
44  dynamic_cast<const multiComponentMixture<ThermoType>&>
45  (this->thermo()).specieThermos()
46  ),
47  reactions_
48  (
49  dynamic_cast<const multiComponentMixture<ThermoType>&>
50  (
51  this->thermo()
52  ).species(),
53  specieThermos_,
54  this->mesh(),
55  *this
56  ),
57 
58  nSpecie_(Y_.size()),
59  nReaction_(reactions_.size()),
60  Treact_
61  (
62  BasicChemistryModel<ReactionThermo>::template lookupOrDefault<scalar>
63  (
64  "Treact",
65  0
66  )
67  ),
68  RR_(nSpecie_),
69  c_(nSpecie_),
70  dcdt_(nSpecie_)
71 {
72  // Create the fields for the chemistry sources
73  forAll(RR_, fieldi)
74  {
75  RR_.set
76  (
77  fieldi,
79  (
80  IOobject
81  (
82  "RR." + Y_[fieldi].name(),
83  this->mesh().time().timeName(),
84  this->mesh(),
85  IOobject::NO_READ,
86  IOobject::NO_WRITE
87  ),
88  thermo.T().mesh(),
90  )
91  );
92  }
93 
94  Info<< "StandardChemistryModel: Number of species = " << nSpecie_
95  << " and reactions = " << nReaction_ << endl;
96 }
97 
98 
99 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
100 
101 template<class ReactionThermo, class ThermoType>
104 {}
105 
106 
107 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
108 
109 template<class ReactionThermo, class ThermoType>
111 (
112  const scalar p,
113  const scalar T,
114  const scalarField& c,
115  const label li,
116  scalarField& dcdt
117 ) const
118 {
119 
120  dcdt = Zero;
121 
122  forAll(reactions_, i)
123  {
124  const Reaction<ThermoType>& R = reactions_[i];
125 
126  R.omega(p, T, c, li, dcdt);
127  }
128 }
129 
130 
131 template<class ReactionThermo, class ThermoType>
133 (
134  const label index,
135  const scalar p,
136  const scalar T,
137  const scalarField& c,
138  const label li,
139  scalar& pf,
140  scalar& cf,
141  label& lRef,
142  scalar& pr,
143  scalar& cr,
144  label& rRef
145 ) const
146 {
147  const Reaction<ThermoType>& R = reactions_[index];
148  scalar w = R.omega(p, T, c, li, pf, cf, lRef, pr, cr, rRef);
149  return(w);
150 }
151 
152 
153 template<class ReactionThermo, class ThermoType>
155 (
156  const scalar time,
157  const scalarField& c,
158  const label li,
159  scalarField& dcdt
160 ) const
161 {
162  const scalar T = c[nSpecie_];
163  const scalar p = c[nSpecie_ + 1];
164 
165  forAll(c_, i)
166  {
167  c_[i] = max(c[i], 0);
168  }
169 
170  omega(p, T, c_, li, dcdt);
171 
172  // Constant pressure
173  // dT/dt = ...
174  scalar rho = 0;
175  scalar cSum = 0;
176  for (label i = 0; i < nSpecie_; i++)
177  {
178  const scalar W = specieThermos_[i].W();
179  cSum += c_[i];
180  rho += W*c_[i];
181  }
182  scalar cp = 0;
183  for (label i=0; i<nSpecie_; i++)
184  {
185  cp += c_[i]*specieThermos_[i].cp(p, T);
186  }
187  cp /= rho;
188 
189  scalar dT = 0;
190  for (label i = 0; i < nSpecie_; i++)
191  {
192  const scalar hi = specieThermos_[i].ha(p, T);
193  dT += hi*dcdt[i];
194  }
195  dT /= rho*cp;
196 
197  dcdt[nSpecie_] = -dT;
198 
199  // dp/dt = ...
200  dcdt[nSpecie_ + 1] = 0;
201 }
202 
203 
204 template<class ReactionThermo, class ThermoType>
206 (
207  const scalar t,
208  const scalarField& c,
209  const label li,
210  scalarField& dcdt,
212 ) const
213 {
214  const scalar T = c[nSpecie_];
215  const scalar p = c[nSpecie_ + 1];
216 
217  forAll(c_, i)
218  {
219  c_[i] = max(c[i], 0);
220  }
221 
222  J = Zero;
223  dcdt = Zero;
224 
225  // To compute the species derivatives of the temperature term,
226  // the enthalpies of the individual species is needed
227  scalarField hi(nSpecie_);
228  scalarField cpi(nSpecie_);
229  for (label i = 0; i < nSpecie_; i++)
230  {
231  hi[i] = specieThermos_[i].ha(p, T);
232  cpi[i] = specieThermos_[i].cp(p, T);
233  }
234  scalar omegaI = 0;
235  List<label> dummy;
236  forAll(reactions_, ri)
237  {
238  const Reaction<ThermoType>& R = reactions_[ri];
239  scalar kfwd, kbwd;
240  R.dwdc(p, T, c_, li, J, dcdt, omegaI, kfwd, kbwd, false, dummy);
241  R.dwdT(p, T, c_, li, omegaI, kfwd, kbwd, J, false, dummy, nSpecie_);
242  }
243 
244  // The species derivatives of the temperature term are partially computed
245  // while computing dwdc, they are completed hereunder:
246  scalar cpMean = 0;
247  scalar dcpdTMean = 0;
248  for (label i=0; i<nSpecie_; i++)
249  {
250  cpMean += c_[i]*cpi[i]; // J/(m^3 K)
251  dcpdTMean += c_[i]*specieThermos_[i].dcpdT(p, T);
252  }
253  scalar dTdt = 0.0;
254  for (label i=0; i<nSpecie_; i++)
255  {
256  dTdt += hi[i]*dcdt[i]; // J/(m^3 s)
257  }
258  dTdt /= -cpMean; // K/s
259 
260  for (label i = 0; i < nSpecie_; i++)
261  {
262  J(nSpecie_, i) = 0;
263  for (label j = 0; j < nSpecie_; j++)
264  {
265  J(nSpecie_, i) += hi[j]*J(j, i);
266  }
267  J(nSpecie_, i) += cpi[i]*dTdt; // J/(mol s)
268  J(nSpecie_, i) /= -cpMean; // K/s/(mol/m3)
269  }
270 
271  // ddT of dTdt
272  J(nSpecie_, nSpecie_) = 0;
273  for (label i = 0; i < nSpecie_; i++)
274  {
275  J(nSpecie_, nSpecie_) += cpi[i]*dcdt[i] + hi[i]*J(i, nSpecie_);
276  }
277  J(nSpecie_, nSpecie_) += dTdt*dcpdTMean;
278  J(nSpecie_, nSpecie_) /= -cpMean;
279  J(nSpecie_, nSpecie_) += dTdt/T;
280 }
281 
282 
283 template<class ReactionThermo, class ThermoType>
286 {
288  (
290  (
291  "tc",
292  this->mesh(),
293  dimensionedScalar(dimTime, small),
294  extrapolatedCalculatedFvPatchScalarField::typeName
295  )
296  );
297 
298  scalarField& tc = ttc.ref();
299 
300  tmp<volScalarField> trho(this->thermo().rho());
301  const scalarField& rho = trho();
302 
303  const scalarField& T = this->thermo().T();
304  const scalarField& p = this->thermo().p();
305 
306  const label nReaction = reactions_.size();
307 
308  scalar pf, cf, pr, cr;
309  label lRef, rRef;
310 
311  if (this->chemistry_)
312  {
313  forAll(rho, celli)
314  {
315  const scalar rhoi = rho[celli];
316  const scalar Ti = T[celli];
317  const scalar pi = p[celli];
318 
319  scalar cSum = 0;
320 
321  for (label i=0; i<nSpecie_; i++)
322  {
323  c_[i] = rhoi*Y_[i][celli]/specieThermos_[i].W();
324  cSum += c_[i];
325  }
326 
327  forAll(reactions_, i)
328  {
329  const Reaction<ThermoType>& R = reactions_[i];
330 
331  R.omega(pi, Ti, c_, celli, pf, cf, lRef, pr, cr, rRef);
332 
333  forAll(R.rhs(), s)
334  {
335  tc[celli] += R.rhs()[s].stoichCoeff*pf*cf;
336  }
337  }
338 
339  tc[celli] = nReaction*cSum/tc[celli];
340  }
341  }
342 
343  ttc.ref().correctBoundaryConditions();
344 
345  return ttc;
346 }
347 
348 
349 template<class ReactionThermo, class ThermoType>
352 {
353  tmp<volScalarField> tQdot
354  (
356  (
357  "Qdot",
358  this->mesh_,
360  )
361  );
362 
363  if (this->chemistry_)
364  {
365  scalarField& Qdot = tQdot.ref();
366 
367  forAll(Y_, i)
368  {
369  forAll(Qdot, celli)
370  {
371  const scalar hi = specieThermos_[i].Hf();
372  Qdot[celli] -= hi*RR_[i][celli];
373  }
374  }
375  }
376 
377  return tQdot;
378 }
379 
380 
381 template<class ReactionThermo, class ThermoType>
384 (
385  const label ri,
386  const label si
387 ) const
388 {
390  (
392  (
393  "RR",
394  this->mesh(),
396  )
397  );
398 
400 
401  tmp<volScalarField> trho(this->thermo().rho());
402  const scalarField& rho = trho();
403 
404  const scalarField& T = this->thermo().T();
405  const scalarField& p = this->thermo().p();
406 
407  scalar pf, cf, pr, cr;
408  label lRef, rRef;
409 
410  forAll(rho, celli)
411  {
412  const scalar rhoi = rho[celli];
413  const scalar Ti = T[celli];
414  const scalar pi = p[celli];
415 
416  for (label i=0; i<nSpecie_; i++)
417  {
418  const scalar Yi = Y_[i][celli];
419  c_[i] = rhoi*Yi/specieThermos_[i].W();
420  }
421 
422  const Reaction<ThermoType>& R = reactions_[ri];
423  const scalar omegai = R.omega
424  (
425  pi, Ti, c_, celli, pf, cf, lRef, pr, cr, rRef
426  );
427 
428  forAll(R.lhs(), s)
429  {
430  if (si == R.lhs()[s].index)
431  {
432  RR[celli] -= R.lhs()[s].stoichCoeff*omegai;
433  }
434  }
435 
436  forAll(R.rhs(), s)
437  {
438  if (si == R.rhs()[s].index)
439  {
440  RR[celli] += R.rhs()[s].stoichCoeff*omegai;
441  }
442  }
443 
444  RR[celli] *= specieThermos_[si].W();
445  }
446 
447  return tRR;
448 }
449 
450 
451 template<class ReactionThermo, class ThermoType>
453 {
454  if (!this->chemistry_)
455  {
456  return;
457  }
458 
459  tmp<volScalarField> trho(this->thermo().rho());
460  const scalarField& rho = trho();
461 
462  const scalarField& T = this->thermo().T();
463  const scalarField& p = this->thermo().p();
464 
465  forAll(rho, celli)
466  {
467  const scalar rhoi = rho[celli];
468  const scalar Ti = T[celli];
469  const scalar pi = p[celli];
470 
471  for (label i=0; i<nSpecie_; i++)
472  {
473  const scalar Yi = Y_[i][celli];
474  c_[i] = rhoi*Yi/specieThermos_[i].W();
475  }
476 
477  omega(pi, Ti, c_, celli, dcdt_);
478 
479  for (label i=0; i<nSpecie_; i++)
480  {
481  RR_[i][celli] = dcdt_[i]*specieThermos_[i].W();
482  }
483  }
484 }
485 
486 
487 template<class ReactionThermo, class ThermoType>
488 template<class DeltaTType>
490 (
491  const DeltaTType& deltaT
492 )
493 {
495 
496  scalar deltaTMin = great;
497 
498  if (!this->chemistry_)
499  {
500  return deltaTMin;
501  }
502 
503  tmp<volScalarField> trho(this->thermo().rho());
504  const scalarField& rho = trho();
505 
506  const scalarField& T = this->thermo().T();
507  const scalarField& p = this->thermo().p();
508 
509  scalarField c0(nSpecie_);
510 
511  forAll(rho, celli)
512  {
513  scalar Ti = T[celli];
514 
515  if (Ti > Treact_)
516  {
517  const scalar rhoi = rho[celli];
518  scalar pi = p[celli];
519 
520  for (label i=0; i<nSpecie_; i++)
521  {
522  c_[i] = rhoi*Y_[i][celli]/specieThermos_[i].W();
523  c0[i] = c_[i];
524  }
525 
526  // Initialise time progress
527  scalar timeLeft = deltaT[celli];
528 
529  // Calculate the chemical source terms
530  while (timeLeft > small)
531  {
532  scalar dt = timeLeft;
533  this->solve(pi, Ti, c_, celli, dt, this->deltaTChem_[celli]);
534  timeLeft -= dt;
535  }
536 
537  deltaTMin = min(this->deltaTChem_[celli], deltaTMin);
538 
539  this->deltaTChem_[celli] =
540  min(this->deltaTChem_[celli], this->deltaTChemMax_);
541 
542  for (label i=0; i<nSpecie_; i++)
543  {
544  RR_[i][celli] =
545  (c_[i] - c0[i])*specieThermos_[i].W()/deltaT[celli];
546  }
547  }
548  else
549  {
550  for (label i=0; i<nSpecie_; i++)
551  {
552  RR_[i][celli] = 0;
553  }
554  }
555  }
556 
557  return deltaTMin;
558 }
559 
560 
561 template<class ReactionThermo, class ThermoType>
563 (
564  const scalar deltaT
565 )
566 {
567  // Don't allow the time-step to change more than a factor of 2
568  return min
569  (
571  2*deltaT
572  );
573 }
574 
575 
576 template<class ReactionThermo, class ThermoType>
578 (
579  const scalarField& deltaT
580 )
581 {
582  return this->solve<scalarField>(deltaT);
583 }
584 
585 
586 // ************************************************************************* //
A class representing the concept of a uniform field which stores only the single value and providing ...
Definition: UniformField.H:47
StandardChemistryModel(const ReactionThermo &thermo)
Construct from thermo.
#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
Basic chemistry model templated on thermodynamics.
virtual tmp< volScalarField > Qdot() const
Return the heat release rate [kg/m/s^3].
Abstract base class for the systems of ordinary differential equations.
Definition: ODESystem.H:46
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
basicSpecieMixture & composition
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:174
void dwdc(const scalar p, const scalar T, const scalarField &c, const label li, 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:482
virtual void jacobian(const scalar t, const scalarField &c, const label li, scalarField &dcdt, scalarSquareMatrix &J) const
Calculate the Jacobian of the system.
virtual void omega(const scalar p, const scalar T, const scalarField &c, const label li, scalarField &dcdt) const
dc/dt = omega, rate of change in concentration, for each species
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
bool cp(const fileName &src, const fileName &dst, const bool followLink=true)
Copy, recursively if necessary, the source to the destination.
Definition: POSIX.C:753
tmp< volScalarField > trho
const List< specieCoeffs > & lhs() const
Return the components of the left hand side.
Definition: ReactionI.H:57
rhoEqn solve()
rhoReactionThermo & thermo
Definition: createFields.H:28
Extends base chemistry model by adding a thermo package, and ODE functions. Introduces chemistry equa...
scalar Qdot
Definition: solveChemistry.H:2
void omega(const scalar p, const scalar T, const scalarField &c, const label li, scalarField &dcdt) const
Net reaction rate for individual species.
Definition: Reaction.C:334
const dimensionSet dimVolume(pow3(dimLength))
Definition: dimensionSets.H:58
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))
virtual void calculate()
Calculates the reaction rates.
dynamicFvMesh & mesh
autoPtr< BasicCompressibleMomentumTransportModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const typename BasicCompressibleMomentumTransportModel::transportModel &transport)
Foam::multiComponentMixture.
word timeName
Definition: getTimeIndex.H:3
static const zero Zero
Definition: zero.H:97
virtual scalar omegaI(label iReaction, const scalar p, const scalar T, const scalarField &c, const label li, scalar &pf, scalar &cf, label &lRef, scalar &pr, scalar &cr, label &rRef) const
Return the reaction rate for iReaction and the reference.
virtual ~StandardChemistryModel()
Destructor.
Info<< "Predicted p max-min : "<< max(p).value()<< " "<< min(p).value()<< endl;rho==max(rho0+psi *p, rhoMin);# 1 "/home/ubuntu/OpenFOAM-8/applications/solvers/multiphase/cavitatingFoam/alphavPsi.H" 1{ alphav=max(min((rho - rholSat)/(rhovSat - rholSat), scalar(1)), scalar(0));alphal=1.0 - alphav;Info<< "max-min alphav: "<< max(alphav).value()<< " "<< min(alphav).value()<< endl;psiModel-> correct()
Definition: pEqn.H:68
virtual void derivatives(const scalar t, const scalarField &c, const label li, scalarField &dcdt) const
Calculate the derivatives in dydx.
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
const dimensionSet dimEnergy
virtual tmp< volScalarField::Internal > calculateRR(const label reactionI, const label speciei) const
Return reaction rate of the speciei in reactionI.
virtual tmp< volScalarField > tc() const
Return the chemical time scale.
#define R(A, B, C, D, E, F, K, M)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
const scalarList W(::W(thermo))
PtrList< volScalarField > & Y
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:51
messageStream Info
const scalar RR
Universal gas constant (default in [J/kmol/K])
const List< specieCoeffs > & rhs() const
Return the components of the right hand side.
Definition: ReactionI.H:64
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:49
void dwdT(const scalar p, const scalar T, const scalarField &c, const label li, 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:646
A class for managing temporary objects.
Definition: PtrList.H:53
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:92