chemistryModel.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) 2016-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 "chemistryModel.H"
27 #include "UniformField.H"
28 #include "localEulerDdtScheme.H"
29 #include "cpuLoad.H"
30 
31 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
32 
33 template<class ThermoType>
35 (
36  const fluidReactionThermo& thermo
37 )
38 :
39  odeChemistryModel(thermo),
40  log_(this->lookupOrDefault("log", false)),
41  loadBalancing_(this->lookupOrDefault("loadBalancing", false)),
42  jacobianType_
43  (
44  this->found("jacobian")
45  ? jacobianTypeNames_.read(this->lookup("jacobian"))
46  : jacobianType::fast
47  ),
48  mixture_(refCast<const multiComponentMixture<ThermoType>>(this->thermo())),
49  specieThermos_(mixture_.specieThermos()),
50  reactions_(mixture_.species(), specieThermos_, this->mesh(), *this),
51  RR_(nSpecie_),
52  Y_(nSpecie_),
53  c_(nSpecie_),
54  YTpWork_(scalarField(nSpecie_ + 2)),
55  YTpYTpWork_(scalarSquareMatrix(nSpecie_ + 2)),
56  mechRedPtr_
57  (
59  (
60  *this,
61  *this
62  )
63  ),
64  mechRed_(*mechRedPtr_),
65  tabulationPtr_(chemistryTabulationMethod::New(*this, *this)),
66  tabulation_(*tabulationPtr_)
67 {
68  // Create the fields for the chemistry sources
69  forAll(RR_, fieldi)
70  {
71  RR_.set
72  (
73  fieldi,
75  (
76  IOobject
77  (
78  "RR." + Yvf_[fieldi].name(),
79  this->mesh().time().timeName(),
80  this->mesh(),
81  IOobject::NO_READ,
82  IOobject::NO_WRITE
83  ),
84  thermo.T().mesh(),
86  )
87  );
88  }
89 
90  Info<< "chemistryModel: Number of species = " << nSpecie_
91  << " and reactions = " << nReaction() << endl;
92 
93  // When the mechanism reduction method is used, the 'active' flag for every
94  // species should be initialised (by default 'active' is true)
95  if (reduction_)
96  {
97  const basicSpecieMixture& composition = this->thermo().composition();
98 
99  forAll(Yvf_, i)
100  {
102  (
103  Yvf_[i].name(),
104  this->mesh().time().timeName(),
105  this->mesh(),
106  IOobject::NO_READ
107  );
108 
109  // Check if the species file is provided, if not set inactive
110  // and NO_WRITE
111  if (!header.headerOk())
112  {
113  composition.setInactive(i);
114  }
115  }
116  }
117 
118  if (log_)
119  {
120  cpuSolveFile_ = logFile("cpu_solve.out");
121  }
122 }
123 
124 
125 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
126 
127 template<class ThermoType>
129 {}
130 
131 
132 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
133 
134 template<class ThermoType>
136 (
137  const scalar time,
138  const scalarField& YTp,
139  const label li,
140  scalarField& dYTpdt
141 ) const
142 {
143  if (reduction_)
144  {
145  forAll(sToc_, i)
146  {
147  Y_[sToc_[i]] = max(YTp[i], 0);
148  }
149  }
150  else
151  {
152  forAll(Y_, i)
153  {
154  Y_[i] = max(YTp[i], 0);
155  }
156  }
157 
158  const scalar T = YTp[nSpecie_];
159  const scalar p = YTp[nSpecie_ + 1];
160 
161  // Evaluate the mixture density
162  scalar rhoM = 0;
163  for (label i=0; i<Y_.size(); i++)
164  {
165  rhoM += Y_[i]/specieThermos_[i].rho(p, T);
166  }
167  rhoM = 1/rhoM;
168 
169  // Evaluate the concentrations
170  for (label i=0; i<Y_.size(); i ++)
171  {
172  c_[i] = rhoM/specieThermos_[i].W()*Y_[i];
173  }
174 
175  // Evaluate contributions from reactions
176  dYTpdt = Zero;
177  forAll(reactions_, ri)
178  {
179  if (!mechRed_.reactionDisabled(ri))
180  {
181  reactions_[ri].dNdtByV
182  (
183  p,
184  T,
185  c_,
186  li,
187  dYTpdt,
188  reduction_,
189  cTos_,
190  0
191  );
192  }
193  }
194 
195  // Reactions return dNdtByV, so we need to convert the result to dYdt
196  for (label i=0; i<nSpecie_; i++)
197  {
198  const scalar WiByrhoM = specieThermos_[sToc(i)].W()/rhoM;
199  scalar& dYidt = dYTpdt[i];
200  dYidt *= WiByrhoM;
201  }
202 
203  // Evaluate the effect on the thermodynamic system ...
204 
205  // Evaluate the mixture Cp
206  scalar CpM = 0;
207  for (label i=0; i<Y_.size(); i++)
208  {
209  CpM += Y_[i]*specieThermos_[i].Cp(p, T);
210  }
211 
212  // dT/dt
213  scalar& dTdt = dYTpdt[nSpecie_];
214  for (label i=0; i<nSpecie_; i++)
215  {
216  dTdt -= dYTpdt[i]*specieThermos_[sToc(i)].Ha(p, T);
217  }
218  dTdt /= CpM;
219 
220  // dp/dt = 0 (pressure is assumed constant)
221  scalar& dpdt = dYTpdt[nSpecie_ + 1];
222  dpdt = 0;
223 }
224 
225 
226 template<class ThermoType>
228 (
229  const scalar t,
230  const scalarField& YTp,
231  const label li,
232  scalarField& dYTpdt,
234 ) const
235 {
236  if (reduction_)
237  {
238  forAll(sToc_, i)
239  {
240  Y_[sToc_[i]] = max(YTp[i], 0);
241  }
242  }
243  else
244  {
245  forAll(c_, i)
246  {
247  Y_[i] = max(YTp[i], 0);
248  }
249  }
250 
251  const scalar T = YTp[nSpecie_];
252  const scalar p = YTp[nSpecie_ + 1];
253 
254  // Evaluate the specific volumes and mixture density
255  scalarField& v = YTpWork_[0];
256  for (label i=0; i<Y_.size(); i++)
257  {
258  v[i] = 1/specieThermos_[i].rho(p, T);
259  }
260  scalar rhoM = 0;
261  for (label i=0; i<Y_.size(); i++)
262  {
263  rhoM += Y_[i]*v[i];
264  }
265  rhoM = 1/rhoM;
266 
267  // Evaluate the concentrations
268  for (label i=0; i<Y_.size(); i ++)
269  {
270  c_[i] = rhoM/specieThermos_[i].W()*Y_[i];
271  }
272 
273  // Evaluate the derivatives of concentration w.r.t. mass fraction
274  scalarSquareMatrix& dcdY = YTpYTpWork_[0];
275  for (label i=0; i<nSpecie_; i++)
276  {
277  const scalar rhoMByWi = rhoM/specieThermos_[sToc(i)].W();
278  switch (jacobianType_)
279  {
280  case jacobianType::fast:
281  {
282  dcdY(i, i) = rhoMByWi;
283  }
284  break;
285  case jacobianType::exact:
286  for (label j=0; j<nSpecie_; j++)
287  {
288  dcdY(i, j) =
289  rhoMByWi*((i == j) - rhoM*v[sToc(j)]*Y_[sToc(i)]);
290  }
291  break;
292  }
293  }
294 
295  // Evaluate the mixture thermal expansion coefficient
296  scalar alphavM = 0;
297  for (label i=0; i<Y_.size(); i++)
298  {
299  alphavM += Y_[i]*rhoM*v[i]*specieThermos_[i].alphav(p, T);
300  }
301 
302  // Evaluate contributions from reactions
303  dYTpdt = Zero;
304  scalarSquareMatrix& ddNdtByVdcTp = YTpYTpWork_[1];
305  for (label i=0; i<nSpecie_ + 2; i++)
306  {
307  for (label j=0; j<nSpecie_ + 2; j++)
308  {
309  ddNdtByVdcTp[i][j] = 0;
310  }
311  }
312  forAll(reactions_, ri)
313  {
314  if (!mechRed_.reactionDisabled(ri))
315  {
316  reactions_[ri].ddNdtByVdcTp
317  (
318  p,
319  T,
320  c_,
321  li,
322  dYTpdt,
323  ddNdtByVdcTp,
324  reduction_,
325  cTos_,
326  0,
327  nSpecie_,
328  YTpWork_[1],
329  YTpWork_[2]
330  );
331  }
332  }
333 
334  // Reactions return dNdtByV, so we need to convert the result to dYdt
335  for (label i=0; i<nSpecie_; i++)
336  {
337  const scalar WiByrhoM = specieThermos_[sToc(i)].W()/rhoM;
338  scalar& dYidt = dYTpdt[i];
339  dYidt *= WiByrhoM;
340 
341  for (label j=0; j<nSpecie_; j++)
342  {
343  scalar ddNidtByVdYj = 0;
344  switch (jacobianType_)
345  {
346  case jacobianType::fast:
347  {
348  const scalar ddNidtByVdcj = ddNdtByVdcTp(i, j);
349  ddNidtByVdYj = ddNidtByVdcj*dcdY(j, j);
350  }
351  break;
352  case jacobianType::exact:
353  for (label k=0; k<nSpecie_; k++)
354  {
355  const scalar ddNidtByVdck = ddNdtByVdcTp(i, k);
356  ddNidtByVdYj += ddNidtByVdck*dcdY(k, j);
357  }
358  break;
359  }
360 
361  scalar& ddYidtdYj = J(i, j);
362  ddYidtdYj = WiByrhoM*ddNidtByVdYj + rhoM*v[sToc(j)]*dYidt;
363  }
364 
365  scalar ddNidtByVdT = ddNdtByVdcTp(i, nSpecie_);
366  for (label j=0; j<nSpecie_; j++)
367  {
368  const scalar ddNidtByVdcj = ddNdtByVdcTp(i, j);
369  ddNidtByVdT -= ddNidtByVdcj*c_[sToc(j)]*alphavM;
370  }
371 
372  scalar& ddYidtdT = J(i, nSpecie_);
373  ddYidtdT = WiByrhoM*ddNidtByVdT + alphavM*dYidt;
374 
375  scalar& ddYidtdp = J(i, nSpecie_ + 1);
376  ddYidtdp = 0;
377  }
378 
379  // Evaluate the effect on the thermodynamic system ...
380 
381  // Evaluate the mixture Cp and its derivative
382  scalarField& Cp = YTpWork_[3];
383  scalar CpM = 0, dCpMdT = 0;
384  for (label i=0; i<Y_.size(); i++)
385  {
386  Cp[i] = specieThermos_[i].Cp(p, T);
387  CpM += Y_[i]*Cp[i];
388  dCpMdT += Y_[i]*specieThermos_[i].dCpdT(p, T);
389  }
390 
391  // dT/dt
392  scalarField& Ha = YTpWork_[4];
393  scalar& dTdt = dYTpdt[nSpecie_];
394  for (label i=0; i<nSpecie_; i++)
395  {
396  Ha[sToc(i)] = specieThermos_[sToc(i)].Ha(p, T);
397  dTdt -= dYTpdt[i]*Ha[sToc(i)];
398  }
399  dTdt /= CpM;
400 
401  // dp/dt = 0 (pressure is assumed constant)
402  scalar& dpdt = dYTpdt[nSpecie_ + 1];
403  dpdt = 0;
404 
405  // d(dTdt)/dY
406  for (label i=0; i<nSpecie_; i++)
407  {
408  scalar& ddTdtdYi = J(nSpecie_, i);
409  ddTdtdYi = 0;
410  for (label j=0; j<nSpecie_; j++)
411  {
412  const scalar ddYjdtdYi = J(j, i);
413  ddTdtdYi -= ddYjdtdYi*Ha[sToc(j)];
414  }
415  ddTdtdYi -= Cp[sToc(i)]*dTdt;
416  ddTdtdYi /= CpM;
417  }
418 
419  // d(dTdt)/dT
420  scalar& ddTdtdT = J(nSpecie_, nSpecie_);
421  ddTdtdT = 0;
422  for (label i=0; i<nSpecie_; i++)
423  {
424  const scalar dYidt = dYTpdt[i];
425  const scalar ddYidtdT = J(i, nSpecie_);
426  ddTdtdT -= dYidt*Cp[sToc(i)] + ddYidtdT*Ha[sToc(i)];
427  }
428  ddTdtdT -= dTdt*dCpMdT;
429  ddTdtdT /= CpM;
430 
431  // d(dTdt)/dp = 0 (pressure is assumed constant)
432  scalar& ddTdtdp = J(nSpecie_, nSpecie_ + 1);
433  ddTdtdp = 0;
434 
435  // d(dpdt)/dYiTp = 0 (pressure is assumed constant)
436  for (label i=0; i<nSpecie_ + 2; i++)
437  {
438  scalar& ddpdtdYiTp = J(nSpecie_ + 1, i);
439  ddpdtdYiTp = 0;
440  }
441 }
442 
443 
444 template<class ThermoType>
447 {
449  (
451  (
452  "tc",
453  this->mesh(),
454  dimensionedScalar(dimTime, small),
455  extrapolatedCalculatedFvPatchScalarField::typeName
456  )
457  );
458  scalarField& tc = ttc.ref();
459 
460  tmp<volScalarField> trho(this->thermo().rho());
461  const scalarField& rho = trho();
462 
463  const scalarField& T = this->thermo().T();
464  const scalarField& p = this->thermo().p();
465 
466  if (this->chemistry_)
467  {
468  reactionEvaluationScope scope(*this);
469 
470  forAll(rho, celli)
471  {
472  const scalar rhoi = rho[celli];
473  const scalar Ti = T[celli];
474  const scalar pi = p[celli];
475 
476  for (label i=0; i<nSpecie_; i++)
477  {
478  c_[i] = rhoi*Yvf_[i][celli]/specieThermos_[i].W();
479  }
480 
481  // A reaction's rate scale is calculated as it's molar
482  // production rate divided by the total number of moles in the
483  // system.
484  //
485  // The system rate scale is the average of the reactions' rate
486  // scales weighted by the reactions' molar production rates. This
487  // weighting ensures that dominant reactions provide the largest
488  // contribution to the system rate scale.
489  //
490  // The system time scale is then the reciprocal of the system rate
491  // scale.
492  //
493  // Contributions from forward and reverse reaction rates are
494  // handled independently and identically so that reversible
495  // reactions produce the same result as the equivalent pair of
496  // irreversible reactions.
497 
498  scalar sumW = 0, sumWRateByCTot = 0;
499  forAll(reactions_, i)
500  {
501  const Reaction<ThermoType>& R = reactions_[i];
502  scalar omegaf, omegar;
503  R.omega(pi, Ti, c_, celli, omegaf, omegar);
504 
505  scalar wf = 0;
506  forAll(R.rhs(), s)
507  {
508  wf += R.rhs()[s].stoichCoeff*omegaf;
509  }
510  sumW += wf;
511  sumWRateByCTot += sqr(wf);
512 
513  scalar wr = 0;
514  forAll(R.lhs(), s)
515  {
516  wr += R.lhs()[s].stoichCoeff*omegar;
517  }
518  sumW += wr;
519  sumWRateByCTot += sqr(wr);
520  }
521 
522  tc[celli] =
523  sumWRateByCTot == 0 ? vGreat : sumW/sumWRateByCTot*sum(c_);
524  }
525  }
526 
527  ttc.ref().correctBoundaryConditions();
528 
529  return ttc;
530 }
531 
532 
533 template<class ThermoType>
536 {
537  tmp<volScalarField> tQdot
538  (
540  (
541  "Qdot",
542  this->mesh_,
544  )
545  );
546 
547  if (this->chemistry_)
548  {
549  reactionEvaluationScope scope(*this);
550 
551  scalarField& Qdot = tQdot.ref();
552 
553  forAll(Yvf_, i)
554  {
555  forAll(Qdot, celli)
556  {
557  const scalar hi = specieThermos_[i].Hf();
558  Qdot[celli] -= hi*RR_[i][celli];
559  }
560  }
561  }
562 
563  return tQdot;
564 }
565 
566 
567 template<class ThermoType>
570 (
571  const label ri,
572  const label si
573 ) const
574 {
576  (
578  (
579  "RR",
580  this->mesh(),
582  )
583  );
584 
586 
587  tmp<volScalarField> trho(this->thermo().rho());
588  const scalarField& rho = trho();
589 
590  const scalarField& T = this->thermo().T();
591  const scalarField& p = this->thermo().p();
592 
593  reactionEvaluationScope scope(*this);
594 
595  scalar omegaf, omegar;
596 
597  forAll(rho, celli)
598  {
599  const scalar rhoi = rho[celli];
600  const scalar Ti = T[celli];
601  const scalar pi = p[celli];
602 
603  for (label i=0; i<nSpecie_; i++)
604  {
605  const scalar Yi = Yvf_[i][celli];
606  c_[i] = rhoi*Yi/specieThermos_[i].W();
607  }
608 
609  const Reaction<ThermoType>& R = reactions_[ri];
610  const scalar omegaI = R.omega(pi, Ti, c_, celli, omegaf, omegar);
611 
612  forAll(R.lhs(), s)
613  {
614  if (si == R.lhs()[s].index)
615  {
616  RR[celli] -= R.lhs()[s].stoichCoeff*omegaI;
617  }
618  }
619 
620  forAll(R.rhs(), s)
621  {
622  if (si == R.rhs()[s].index)
623  {
624  RR[celli] += R.rhs()[s].stoichCoeff*omegaI;
625  }
626  }
627 
628  RR[celli] *= specieThermos_[si].W();
629  }
630 
631  return tRR;
632 }
633 
634 
635 template<class ThermoType>
637 {
638  if (!this->chemistry_)
639  {
640  return;
641  }
642 
643  tmp<volScalarField> trho(this->thermo().rho());
644  const scalarField& rho = trho();
645 
646  const scalarField& T = this->thermo().T();
647  const scalarField& p = this->thermo().p();
648 
649  scalarField& dNdtByV = YTpWork_[0];
650 
651  reactionEvaluationScope scope(*this);
652 
653  forAll(rho, celli)
654  {
655  const scalar rhoi = rho[celli];
656  const scalar Ti = T[celli];
657  const scalar pi = p[celli];
658 
659  for (label i=0; i<nSpecie_; i++)
660  {
661  const scalar Yi = Yvf_[i][celli];
662  c_[i] = rhoi*Yi/specieThermos_[i].W();
663  }
664 
665  dNdtByV = Zero;
666 
667  forAll(reactions_, ri)
668  {
669  if (!mechRed_.reactionDisabled(ri))
670  {
671  reactions_[ri].dNdtByV
672  (
673  pi,
674  Ti,
675  c_,
676  celli,
677  dNdtByV,
678  reduction_,
679  cTos_,
680  0
681  );
682  }
683  }
684 
685  for (label i=0; i<mechRed_.nActiveSpecies(); i++)
686  {
687  RR_[sToc(i)][celli] = dNdtByV[i]*specieThermos_[sToc(i)].W();
688  }
689  }
690 }
691 
692 
693 template<class ThermoType>
694 template<class DeltaTType>
696 (
697  const DeltaTType& deltaT
698 )
699 {
700  tabulation_.reset();
701 
702  const basicSpecieMixture& composition = this->thermo().composition();
703 
704  optionalCpuLoad& chemistryCpuTime
705  (
706  optionalCpuLoad::New(this->mesh(), "chemistryCpuTime", loadBalancing_)
707  );
708 
709  // CPU time analysis
710  cpuTime solveCpuTime_;
711  scalar totalSolveCpuTime_ = 0;
712 
714 
715  scalar deltaTMin = great;
716 
717  if (!this->chemistry_)
718  {
719  return deltaTMin;
720  }
721 
722  tmp<volScalarField> trhovf(this->thermo().rho());
723  const volScalarField& rhovf = trhovf();
724  tmp<volScalarField> trho0vf(this->thermo().rho0());
725  const volScalarField& rho0vf = trho0vf();
726 
727  const volScalarField& T0vf = this->thermo().T().oldTime();
728  const volScalarField& p0vf = this->thermo().p().oldTime();
729 
730  reactionEvaluationScope scope(*this);
731 
732  scalarField Y0(nSpecie_);
733 
734  // Composition vector (Yi, T, p, deltaT)
735  scalarField phiq(nEqns() + 1);
736  scalarField Rphiq(nEqns() + 1);
737 
738  chemistryCpuTime.reset();
739 
740  forAll(rho0vf, celli)
741  {
742  const scalar rho = rhovf[celli];
743  const scalar rho0 = rho0vf[celli];
744 
745  scalar p = p0vf[celli];
746  scalar T = T0vf[celli];
747 
748  for (label i=0; i<nSpecie_; i++)
749  {
750  Y_[i] = Y0[i] = Yvf_[i].oldTime()[celli];
751  }
752 
753  for (label i=0; i<nSpecie_; i++)
754  {
755  phiq[i] = Yvf_[i].oldTime()[celli];
756  }
757  phiq[nSpecie()] = T;
758  phiq[nSpecie() + 1] = p;
759  phiq[nSpecie() + 2] = deltaT[celli];
760 
761  // Initialise time progress
762  scalar timeLeft = deltaT[celli];
763 
764  // Not sure if this is necessary
765  Rphiq = Zero;
766 
767  // When tabulation is active (short-circuit evaluation for retrieve)
768  // It first tries to retrieve the solution of the system with the
769  // information stored through the tabulation method
770  if (tabulation_.retrieve(phiq, Rphiq))
771  {
772  // Retrieved solution stored in Rphiq
773  for (label i=0; i<nSpecie(); i++)
774  {
775  Y_[i] = Rphiq[i];
776  }
777  T = Rphiq[nSpecie()];
778  p = Rphiq[nSpecie() + 1];
779  }
780  // This position is reached when tabulation is not used OR
781  // if the solution is not retrieved.
782  // In the latter case, it adds the information to the tabulation
783  // (it will either expand the current data or add a new stored point).
784  else
785  {
786  if (reduction_)
787  {
788  // Compute concentrations
789  for (label i=0; i<nSpecie_; i++)
790  {
791  c_[i] = rho0*Y_[i]/specieThermos_[i].W();
792  }
793 
794  // Reduce mechanism change the number of species (only active)
795  mechRed_.reduceMechanism(p, T, c_, cTos_, sToc_, celli);
796 
797  // Set the simplified mass fraction field
798  sY_.setSize(nSpecie_);
799  for (label i=0; i<nSpecie_; i++)
800  {
801  sY_[i] = Y_[sToc(i)];
802  }
803  }
804 
805  if (log_)
806  {
807  // Reset the solve time
808  solveCpuTime_.cpuTimeIncrement();
809  }
810 
811  // Calculate the chemical source terms
812  while (timeLeft > small)
813  {
814  scalar dt = timeLeft;
815  if (reduction_)
816  {
817  // Solve the reduced set of ODE
818  solve
819  (
820  p,
821  T,
822  sY_,
823  celli,
824  dt,
825  deltaTChem_[celli]
826  );
827 
828  for (label i=0; i<mechRed_.nActiveSpecies(); i++)
829  {
830  Y_[sToc_[i]] = sY_[i];
831  }
832  }
833  else
834  {
835  solve(p, T, Y_, celli, dt, deltaTChem_[celli]);
836  }
837  timeLeft -= dt;
838  }
839 
840  if (log_)
841  {
842  totalSolveCpuTime_ += solveCpuTime_.cpuTimeIncrement();
843  }
844 
845  // If tabulation is used, we add the information computed here to
846  // the stored points (either expand or add)
847  if (tabulation_.tabulates())
848  {
849  forAll(Y_, i)
850  {
851  Rphiq[i] = Y_[i];
852  }
853  Rphiq[Rphiq.size()-3] = T;
854  Rphiq[Rphiq.size()-2] = p;
855  Rphiq[Rphiq.size()-1] = deltaT[celli];
856 
857  tabulation_.add
858  (
859  phiq,
860  Rphiq,
861  mechRed_.nActiveSpecies(),
862  celli,
863  deltaT[celli]
864  );
865  }
866 
867  // When operations are done and if mechanism reduction is active,
868  // the number of species (which also affects nEqns) is set back
869  // to the total number of species (stored in the mechRed object)
870  if (reduction_)
871  {
872  setNSpecie(mechRed_.nSpecie());
873  }
874 
875  deltaTMin = min(deltaTChem_[celli], deltaTMin);
876  deltaTChem_[celli] = min(deltaTChem_[celli], deltaTChemMax_);
877  }
878 
879  // Set the RR vector (used in the solver)
880  for (label i=0; i<nSpecie_; i++)
881  {
882  RR_[i][celli] = (Y_[i]*rho - Y0[i]*rho0)/deltaT[celli];
883  }
884 
885  if (loadBalancing_)
886  {
887  chemistryCpuTime.cpuTimeIncrement(celli);
888  }
889  }
890 
891  if (log_)
892  {
893  cpuSolveFile_()
894  << this->time().userTimeValue()
895  << " " << totalSolveCpuTime_ << endl;
896  }
897 
898  mechRed_.update();
899  tabulation_.update();
900 
901  if (reduction_ && Pstream::parRun())
902  {
903  List<bool> active(composition.active());
904  Pstream::listCombineGather(active, orEqOp<bool>());
905  Pstream::listCombineScatter(active);
906 
907  forAll(active, i)
908  {
909  if (active[i])
910  {
911  composition.setActive(i);
912  }
913  }
914  }
915 
916  return deltaTMin;
917 }
918 
919 
920 template<class ThermoType>
922 (
923  const scalar deltaT
924 )
925 {
926  // Don't allow the time-step to change more than a factor of 2
927  return min
928  (
930  2*deltaT
931  );
932 }
933 
934 
935 template<class ThermoType>
937 (
938  const scalarField& deltaT
939 )
940 {
941  return this->solve<scalarField>(deltaT);
942 }
943 
944 
945 // ************************************************************************* //
virtual tmp< volScalarField::Internal > calculateRR(const label reactionI, const label speciei) const
Return reaction rate of the speciei in reactionI.
A class representing the concept of a uniform field which stores only the single value and providing ...
Definition: UniformField.H:47
void setInactive(label speciei) const
Set speciei inactive.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
virtual void derivatives(const scalar t, const scalarField &YTp, const label li, scalarField &dYTpdt) const
Calculate the derivatives in dydx.
virtual void cpuTimeIncrement(const label celli)
Dummy cpuTimeIncrement function.
Definition: cpuLoad.H:99
fluidReactionThermo & thermo
Definition: createFields.H:28
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
virtual tmp< volScalarField > tc() const
Return the chemical time scale.
bool headerOk()
Read header (uses typeGlobalFile to find file) and check.
bool active(label speciei) const
Return true for active species.
Info<< "Predicted p max-min : "<< max(p).value()<< " "<< min(p).value()<< endl;rho==max(rho0+psi *p, rhoMin);# 1 "/home/ubuntu/OpenFOAM-10/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
basicSpecieMixture & composition
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:181
Templated form of IOobject providing type information for file reading and header type checking...
Definition: IOobject.H:537
dimensionedSymmTensor sqr(const dimensionedVector &dv)
To & refCast(From &r)
Reference type cast template function.
Definition: typeInfo.H:106
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
virtual ~chemistryModel()
Destructor.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
tmp< volScalarField > trho
Base-class for multi-component fluid thermodynamic properties.
scalar rho0
label k
Boltzmann constant.
const label nSpecie
const List< specieCoeffs > & lhs() const
Return the components of the left hand side.
Definition: reactionI.H:36
Specialisation of basicMixture for a mixture consisting of a number for molecular species...
fvMesh & mesh
Simple extension of ReactionThermo to handle reaction kinetics in addition to the equilibrium thermod...
Definition: Reaction.H:55
scalar Qdot
Definition: solveChemistry.H:2
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
scalarList Y0(nSpecie, 0.0)
volScalarField & dpdt
const dimensionSet dimTime
const dimensionedScalar RR
Universal gas constant: default SI units: [J/kmol/K].
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))
double cpuTimeIncrement() const
Return CPU time (in seconds) since last call to cpuTimeIncrement()
Definition: cpuTime.C:60
virtual void jacobian(const scalar t, const scalarField &YTp, const label li, scalarField &dYTpdt, scalarSquareMatrix &J) const
Calculate the Jacobian of the system.
Foam::multiComponentMixture.
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
chemistryModel(const fluidReactionThermo &thermo)
Construct from thermo.
word timeName
Definition: getTimeIndex.H:3
static const zero Zero
Definition: zero.H:97
volScalarField scalarField(fieldObject, mesh)
const Mesh & mesh() const
Return mesh.
const dimensionSet dimEnergy
const dimensionSet dimMass
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
virtual void calculate()
Calculates the reaction rates.
void setSize(const label)
Reset size of List.
Definition: List.C:281
const volScalarField & T
Extends base chemistry model by adding a thermo package, and ODE functions. Introduces chemistry equa...
const List< specieCoeffs > & rhs() const
Return the components of the right hand side.
Definition: reactionI.H:42
rhoEqn solve()
#define R(A, B, C, D, E, F, K, M)
virtual const volScalarField & T() const =0
Temperature [K].
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
scalar Cp(const scalar p, const scalar T) const
Definition: EtoHthermo.H:2
const dimensionSet dimVolume
messageStream Info
virtual void reset()
Dummy reset function.
Definition: cpuLoad.H:95
scalar Ha(const scalar p, const scalar T) const
Definition: EtoHthermo.H:20
void setActive(label speciei) const
Set speciei active.
An abstract class for methods of chemical mechanism reduction.
virtual tmp< volScalarField > Qdot() const
Return the heat release rate [kg/m/s^3].
Starts timing CPU usage and return elapsed time from start.
Definition: cpuTime.H:54
volScalarField & p
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:98
Extends base chemistry model adding an ODESystem and the reduction maps needed for tabulation...
SquareMatrix< scalar > scalarSquareMatrix
bool found