EulerImplicit.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 "EulerImplicit.H"
28 #include "simpleMatrix.H"
29 #include "Reaction.H"
30 
31 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
32 
33 template<class ChemistryModel>
35 (
36  const typename ChemistryModel::reactionThermo& thermo
37 )
38 :
40  coeffsDict_(this->subDict("EulerImplicitCoeffs")),
41  cTauChem_(coeffsDict_.lookup<scalar>("cTauChem")),
42  eqRateLimiter_(coeffsDict_.lookup("equilibriumRateLimiter")),
43  cTp_(this->nEqns())
44 {}
45 
46 
47 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
48 
49 template<class ChemistryModel>
51 {}
52 
53 
54 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
55 
56 template<class ChemistryModel>
58 (
59  const label index,
60  const scalar pr,
61  const scalar pf,
62  const scalar corr,
63  const label lRef,
64  const label rRef,
65  const scalar p,
66  const scalar T,
68 ) const
69 {
71  this->reactions_[index];
72 
73  forAll(R.lhs(), s)
74  {
75  const label si = R.lhs()[s].index;
76  const scalar sl = R.lhs()[s].stoichCoeff;
77  RR[si][rRef] -= sl*pr*corr;
78  RR[si][lRef] += sl*pf*corr;
79  }
80 
81  forAll(R.rhs(), s)
82  {
83  const label si = R.rhs()[s].index;
84  const scalar sr = R.rhs()[s].stoichCoeff;
85  RR[si][lRef] -= sr*pf*corr;
86  RR[si][rRef] += sr*pr*corr;
87  }
88 }
89 
90 
91 template<class ChemistryModel>
93 (
94  scalar& p,
95  scalar& T,
96  scalarField& c,
97  const label li,
98  scalar& deltaT,
99  scalar& subDeltaT
100 ) const
101 {
102  const label nSpecie = this->nSpecie();
103  simpleMatrix<scalar> RR(nSpecie, 0, 0);
104 
105  for (label i=0; i<nSpecie; i++)
106  {
107  c[i] = max(0, c[i]);
108  }
109 
110  // Calculate the absolute enthalpy
111  const scalar cTot = sum(c);
112  typename ChemistryModel::thermoType mixture
113  (
114  (this->specieThermos_[0].W()*c[0])*this->specieThermos_[0]
115  );
116  for (label i=1; i<nSpecie; i++)
117  {
118  mixture += (this->specieThermos_[i].W()*c[i])*this->specieThermos_[i];
119  }
120  const scalar ha = mixture.Ha(p, T);
121  const scalar deltaTEst = min(deltaT, subDeltaT);
122 
123  forAll(this->reactions(), i)
124  {
125  scalar pf, cf, pr, cr;
126  label lRef, rRef;
127 
128  const scalar omegai
129  (
130  this->omegaI(i, p, T, c, li, pf, cf, lRef, pr, cr, rRef)
131  );
132 
133  scalar corr = 1;
134  if (eqRateLimiter_)
135  {
136  if (omegai < 0)
137  {
138  corr = 1/(1 + pr*deltaTEst);
139  }
140  else
141  {
142  corr = 1/(1 + pf*deltaTEst);
143  }
144  }
145 
146  updateRRInReactionI(i, pr, pf, corr, lRef, rRef, p, T, RR);
147  }
148 
149  // Calculate the stable/accurate time-step
150  scalar tMin = great;
151 
152  for (label i=0; i<nSpecie; i++)
153  {
154  scalar d = 0;
155  for (label j=0; j<nSpecie; j++)
156  {
157  d -= RR(i, j)*c[j];
158  }
159 
160  if (d < -small)
161  {
162  tMin = min(tMin, -(c[i] + small)/d);
163  }
164  else
165  {
166  d = max(d, small);
167  const scalar cm = max(cTot - c[i], 1e-5);
168  tMin = min(tMin, cm/d);
169  }
170  }
171 
172  subDeltaT = cTauChem_*tMin;
173  deltaT = min(deltaT, subDeltaT);
174 
175  // Add the diagonal and source contributions from the time-derivative
176  for (label i=0; i<nSpecie; i++)
177  {
178  RR(i, i) += 1/deltaT;
179  RR.source()[i] = c[i]/deltaT;
180  }
181 
182  // Solve for the new composition
183  c = RR.LUsolve();
184 
185  // Limit the composition
186  for (label i=0; i<nSpecie; i++)
187  {
188  c[i] = max(0, c[i]);
189  }
190 
191  // Update the temperature
192  mixture = (this->specieThermos_[0].W()*c[0])*this->specieThermos_[0];
193  for (label i=1; i<nSpecie; i++)
194  {
195  mixture += (this->specieThermos_[i].W()*c[i])*this->specieThermos_[i];
196  }
197  T = mixture.THa(ha, p, T);
198 }
199 
200 
201 // ************************************************************************* //
Field< Type > & source()
Return access to the source.
Definition: simpleMatrix.H:97
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
An abstract base class for solving chemistry.
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
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
const List< specieCoeffs > & lhs() const
Return the components of the left hand side.
Definition: ReactionI.H:57
rhoReactionThermo & thermo
Definition: createFields.H:28
const label nSpecie
Simple extension of ReactionThermo to handle reaction kinetics in addition to the equilibrium thermod...
Definition: Reaction.H:56
Macros for easy insertion into run-time selection tables.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
EulerImplicit(const typename ChemistryModel::reactionThermo &thermo)
Construct from thermo.
Definition: EulerImplicit.C:35
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 solve(scalar &p, scalar &T, scalarField &c, const label li, scalar &deltaT, scalar &subDeltaT) const
Update the concentrations and return the chemical time.
Definition: EulerImplicit.C:93
Field< Type > LUsolve() const
Solve the matrix using LU decomposition with pivoting.
Definition: simpleMatrix.C:86
const dimensionedScalar & e
Elementary charge.
Definition: doubleScalar.H:105
A simple square matrix solver with scalar coefficients.
Definition: simpleMatrix.H:47
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
#define R(A, B, C, D, E, F, K, M)
const scalarList W(::W(thermo))
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
phaseChangeTwoPhaseMixture & mixture
Definition: createFields.H:38
void updateRRInReactionI(const label index, const scalar pr, const scalar pf, const scalar corr, const label lRef, const label rRef, const scalar p, const scalar T, simpleMatrix< scalar > &RR) const
Definition: EulerImplicit.C:58
virtual ~EulerImplicit()
Destructor.
Definition: EulerImplicit.C:50