SCOPELaminarFlameSpeed.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 "IFstream.H"
27 #include "SCOPELaminarFlameSpeed.H"
29 
30 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
31 
32 namespace Foam
33 {
34 namespace laminarFlameSpeedModels
35 {
36  defineTypeNameAndDebug(SCOPE, 0);
37 
39  (
40  laminarFlameSpeed,
41  SCOPE,
42  dictionary
43  );
44 }
45 }
46 
47 
48 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
49 
50 Foam::laminarFlameSpeedModels::SCOPE::polynomial::polynomial
51 (
52  const dictionary& polyDict
53 )
54 :
55  FixedList<scalar, 7>(polyDict.lookup("coefficients")),
56  ll(polyDict.lookup<scalar>("lowerLimit")),
57  ul(polyDict.lookup<scalar>("upperLimit")),
58  llv(polyPhi(ll, *this)),
59  ulv(polyPhi(ul, *this)),
60  lu(0)
61 {}
62 
63 
64 Foam::laminarFlameSpeedModels::SCOPE::SCOPE
65 (
66  const dictionary& dict,
67  const psiuReactionThermo& ct
68 )
69 :
70  laminarFlameSpeed(dict, ct),
71 
72  coeffsDict_
73  (
74  dictionary
75  (
76  IFstream
77  (
78  fileName
79  (
80  dict.lookup("fuelFile")
81  )
82  )()
83  ).optionalSubDict(typeName + "Coeffs")
84  ),
85  LFL_(coeffsDict_.lookup<scalar>("lowerFlamabilityLimit")),
86  UFL_(coeffsDict_.lookup<scalar>("upperFlamabilityLimit")),
87  SuPolyL_(coeffsDict_.subDict("lowerSuPolynomial")),
88  SuPolyU_(coeffsDict_.subDict("upperSuPolynomial")),
89  Texp_(coeffsDict_.lookup<scalar>("Texp")),
90  pexp_(coeffsDict_.lookup<scalar>("pexp")),
91  MaPolyL_(coeffsDict_.subDict("lowerMaPolynomial")),
92  MaPolyU_(coeffsDict_.subDict("upperMaPolynomial"))
93 {
94  SuPolyL_.ll = max(SuPolyL_.ll, LFL_) + small;
95  SuPolyU_.ul = min(SuPolyU_.ul, UFL_) - small;
96 
97  SuPolyL_.lu = 0.5*(SuPolyL_.ul + SuPolyU_.ll);
98  SuPolyU_.lu = SuPolyL_.lu - small;
99 
100  MaPolyL_.lu = 0.5*(MaPolyL_.ul + MaPolyU_.ll);
101  MaPolyU_.lu = MaPolyL_.lu - small;
102 
103  if (debug)
104  {
105  Info<< "phi Su (T = Tref, p = pref)" << endl;
106  label n = 200;
107  for (int i=0; i<n; i++)
108  {
109  scalar phi = (2.0*i)/n;
110  Info<< phi << token::TAB << SuRef(phi) << endl;
111  }
112  }
113 }
114 
115 
116 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
117 
119 {}
120 
121 
122 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
123 
124 inline Foam::scalar Foam::laminarFlameSpeedModels::SCOPE::polyPhi
125 (
126  scalar phi,
127  const polynomial& a
128 )
129 {
130  scalar x = phi - 1.0;
131 
132  return
133  a[0]
134  *(
135  scalar(1)
136  + x*(a[1] + x*(a[2] + x*(a[3] + x*(a[4] + x*(a[5] + x*a[6])))))
137  );
138 }
139 
140 
141 inline Foam::scalar Foam::laminarFlameSpeedModels::SCOPE::SuRef
142 (
143  scalar phi
144 ) const
145 {
146  if (phi < LFL_ || phi > UFL_)
147  {
148  // Return 0 beyond the flamibility limits
149  return scalar(0);
150  }
151  else if (phi < SuPolyL_.ll)
152  {
153  // Use linear interpolation between the low end of the
154  // lower polynomial and the lower flamibility limit
155  return SuPolyL_.llv*(phi - LFL_)/(SuPolyL_.ll - LFL_);
156  }
157  else if (phi > SuPolyU_.ul)
158  {
159  // Use linear interpolation between the upper end of the
160  // upper polynomial and the upper flamibility limit
161  return SuPolyU_.ulv*(UFL_ - phi)/(UFL_ - SuPolyU_.ul);
162  }
163  else if (phi < SuPolyL_.lu)
164  {
165  // Evaluate the lower polynomial
166  return polyPhi(phi, SuPolyL_);
167  }
168  else if (phi > SuPolyU_.lu)
169  {
170  // Evaluate the upper polynomial
171  return polyPhi(phi, SuPolyU_);
172  }
173  else
174  {
176  << "phi = " << phi
177  << " cannot be handled by SCOPE function with the "
178  "given coefficients"
179  << exit(FatalError);
180 
181  return scalar(0);
182  }
183 }
184 
185 
187 (
188  scalar phi
189 ) const
190 {
191  if (phi < MaPolyL_.ll)
192  {
193  // Beyond the lower limit assume Ma is constant
194  return MaPolyL_.llv;
195  }
196  else if (phi > MaPolyU_.ul)
197  {
198  // Beyond the upper limit assume Ma is constant
199  return MaPolyU_.ulv;
200  }
201  else if (phi < SuPolyL_.lu)
202  {
203  // Evaluate the lower polynomial
204  return polyPhi(phi, MaPolyL_);
205  }
206  else if (phi > SuPolyU_.lu)
207  {
208  // Evaluate the upper polynomial
209  return polyPhi(phi, MaPolyU_);
210  }
211  else
212  {
214  << "phi = " << phi
215  << " cannot be handled by SCOPE function with the "
216  "given coefficients"
217  << exit(FatalError);
218 
219  return scalar(0);
220  }
221 }
222 
223 
224 inline Foam::scalar Foam::laminarFlameSpeedModels::SCOPE::Su0pTphi
225 (
226  scalar p,
227  scalar Tu,
228  scalar phi
229 ) const
230 {
231  static const scalar Tref = 300.0;
232  static const scalar pRef = 1.013e5;
233 
234  return SuRef(phi)*pow((Tu/Tref), Texp_)*pow((p/pRef), pexp_);
235 }
236 
237 
238 Foam::tmp<Foam::volScalarField> Foam::laminarFlameSpeedModels::SCOPE::Su0pTphi
239 (
240  const volScalarField& p,
241  const volScalarField& Tu,
242  scalar phi
243 ) const
244 {
245  tmp<volScalarField> tSu0
246  (
248  (
249  "Su0",
250  p.mesh(),
252  )
253  );
254 
255  volScalarField& Su0 = tSu0.ref();
256 
257  forAll(Su0, celli)
258  {
259  Su0[celli] = Su0pTphi(p[celli], Tu[celli], phi);
260  }
261 
262  volScalarField::Boundary& Su0Bf = Su0.boundaryFieldRef();
263 
264  forAll(Su0Bf, patchi)
265  {
266  scalarField& Su0p = Su0Bf[patchi];
267  const scalarField& pp = p.boundaryField()[patchi];
268  const scalarField& Tup = Tu.boundaryField()[patchi];
269 
270  forAll(Su0p, facei)
271  {
272  Su0p[facei] = Su0pTphi(pp[facei], Tup[facei], phi);
273  }
274  }
275 
276  return tSu0;
277 }
278 
279 
280 Foam::tmp<Foam::volScalarField> Foam::laminarFlameSpeedModels::SCOPE::Su0pTphi
281 (
282  const volScalarField& p,
283  const volScalarField& Tu,
284  const volScalarField& phi
285 ) const
286 {
287  tmp<volScalarField> tSu0
288  (
290  (
291  "Su0",
292  p.mesh(),
294  )
295  );
296 
297  volScalarField& Su0 = tSu0.ref();
298 
299  forAll(Su0, celli)
300  {
301  Su0[celli] = Su0pTphi(p[celli], Tu[celli], phi[celli]);
302  }
303 
304  volScalarField::Boundary& Su0Bf = Su0.boundaryFieldRef();
305 
306  forAll(Su0Bf, patchi)
307  {
308  scalarField& Su0p = Su0Bf[patchi];
309  const scalarField& pp = p.boundaryField()[patchi];
310  const scalarField& Tup = Tu.boundaryField()[patchi];
311  const scalarField& phip = phi.boundaryField()[patchi];
312 
313  forAll(Su0p, facei)
314  {
315  Su0p[facei] =
316  Su0pTphi
317  (
318  pp[facei],
319  Tup[facei],
320  phip[facei]
321  );
322  }
323  }
324 
325  return tSu0;
326 }
327 
328 
330 (
331  const volScalarField& phi
332 ) const
333 {
334  tmp<volScalarField> tMa
335  (
337  (
338  "Ma",
339  phi.mesh(),
341  )
342  );
343 
344  volScalarField& ma = tMa.ref();
345 
346  forAll(ma, celli)
347  {
348  ma[celli] = Ma(phi[celli]);
349  }
350 
351  volScalarField::Boundary& maBf = ma.boundaryFieldRef();
352 
353  forAll(maBf, patchi)
354  {
355  scalarField& map = maBf[patchi];
356  const scalarField& phip = phi.boundaryField()[patchi];
357 
358  forAll(map, facei)
359  {
360  map[facei] = Ma(phip[facei]);
361  }
362  }
363 
364  return tMa;
365 }
366 
367 
370 {
372  {
373  const volScalarField& ft = psiuReactionThermo_.composition().Y("ft");
374 
375  return Ma
376  (
378  (
379  psiuReactionThermo_.lookup("stoichiometricAirFuelMassRatio")
380  )*ft/(scalar(1) - ft)
381  );
382  }
383  else
384  {
385  const fvMesh& mesh = psiuReactionThermo_.p().mesh();
386 
387  return tmp<volScalarField>
388  (
390  (
391  "Ma",
392  mesh,
394  )
395  );
396  }
397 }
398 
399 
402 {
404  {
405  const volScalarField& ft = psiuReactionThermo_.composition().Y("ft");
406 
407  return Su0pTphi
408  (
412  (
413  psiuReactionThermo_.lookup("stoichiometricAirFuelMassRatio")
414  )*ft/(scalar(1) - ft)
415  );
416  }
417  else
418  {
419  return Su0pTphi
420  (
424  );
425  }
426 }
427 
428 
429 // ************************************************************************* //
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
virtual basicCombustionMixture & composition()=0
Return the composition of the combustion mixture.
error FatalError
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
volScalarField & Y(const word &specieName)
Return the mass-fraction field for a specie given by name.
static tmp< GeometricField< scalar, fvPatchField, volMesh > > New(const word &name, const Internal &, const PtrList< fvPatchField< scalar >> &)
Return a temporary field constructed from name,.
scalar equivalenceRatio_
Equivalence ratio of a homogeneous mixture.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
tmp< volScalarField > operator()() const
Return the laminar flame speed [m/s].
virtual volScalarField & p()
Pressure [Pa].
Definition: fluidThermo.C:79
virtual const volScalarField & Tu() const =0
Unburnt gas temperature [K].
Macros for easy insertion into run-time selection tables.
phi
Definition: pEqn.H:104
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:57
stressControl lookup("compactNormalStress") >> compactNormalStress
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
addToRunTimeSelectionTable(laminarFlameSpeed, constant, dictionary)
const Mesh & mesh() const
Return mesh.
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
Internal & ref()
Return a reference to the dimensioned internal field.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
label patchi
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:47
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
const psiuReactionThermo & psiuReactionThermo_
bool contains(const word &specieName) const
Does the mixture include this specie?
messageStream Info
label n
A class for managing temporary objects.
Definition: PtrList.H:53
tmp< volScalarField > Ma() const
Return the Markstein number.
Namespace for OpenFOAM.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:812
const dimensionSet dimVelocity