equilibriumFlameT.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2017 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 Application
25  equilibriumFlameT
26 
27 Description
28  Calculates the equilibrium flame temperature for a given fuel and
29  pressure for a range of unburnt gas temperatures and equivalence
30  ratios; the effects of dissociation on O2, H2O and CO2 are included.
31 
32 \*---------------------------------------------------------------------------*/
33 
34 #include "argList.H"
35 #include "Time.H"
36 #include "dictionary.H"
37 #include "IFstream.H"
38 #include "OSspecific.H"
39 #include "etcFiles.H"
40 #include "IOmanip.H"
41 
42 #include "specie.H"
43 #include "perfectGas.H"
44 #include "thermo.H"
45 #include "janafThermo.H"
46 #include "absoluteEnthalpy.H"
47 
48 using namespace Foam;
49 
51  thermo;
52 
53 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
54 
55 int main(int argc, char *argv[])
56 {
57  argList::validArgs.append("control file");
58  argList args(argc, argv);
59 
60  const fileName controlFileName = args[1];
61 
62  // Construct control dictionary
63  IFstream controlFile(controlFileName);
64 
65  // Check controlFile stream is OK
66  if (!controlFile.good())
67  {
69  << "Cannot read file " << controlFileName
70  << abort(FatalError);
71  }
72 
73  dictionary control(controlFile);
74 
75 
76  scalar P(readScalar(control.lookup("P")));
77  const word fuelName(control.lookup("fuel"));
78  scalar n(readScalar(control.lookup("n")));
79  scalar m(readScalar(control.lookup("m")));
80 
81 
82  Info<< nl << "Reading thermodynamic data dictionary" << endl;
83 
84  fileName thermoDataFileName(findEtcFile("thermoData/thermoData"));
85 
86  // Construct control dictionary
87  IFstream thermoDataFile(thermoDataFileName);
88 
89  // Check thermoData stream is OK
90  if (!thermoDataFile.good())
91  {
93  << "Cannot read file " << thermoDataFileName
94  << abort(FatalError);
95  }
96 
97  dictionary thermoData(thermoDataFile);
98 
99 
100  Info<< nl << "Reading thermodynamic data for relevant species"
101  << nl << endl;
102 
103  // Reactants (mole-based)
104  thermo FUEL(thermoData.subDict(fuelName)); FUEL *= FUEL.W();
105 
106  // Oxidant (mole-based)
107  thermo O2(thermoData.subDict("O2")); O2 *= O2.W();
108  thermo N2(thermoData.subDict("N2")); N2 *= N2.W();
109 
110  // Intermediates (mole-based)
111  thermo H2(thermoData.subDict("H2")); H2 *= H2.W();
112 
113  // Products (mole-based)
114  thermo CO2(thermoData.subDict("CO2")); CO2 *= CO2.W();
115  thermo H2O(thermoData.subDict("H2O")); H2O *= H2O.W();
116  thermo CO(thermoData.subDict("CO")); CO *= CO.W();
117 
118 
119  // Product dissociation reactions
120 
121  thermo CO2BreakUp
122  (
123  CO2 == CO + 0.5*O2
124  );
125 
126  thermo H2OBreakUp
127  (
128  H2O == H2 + 0.5*O2
129  );
130 
131 
132  // Stoiciometric number of moles of species for one mole of fuel
133  scalar stoicO2 = n + m/4.0;
134  scalar stoicN2 = (0.79/0.21)*(n + m/4.0);
135  scalar stoicCO2 = n;
136  scalar stoicH2O = m/2.0;
137 
138  // Oxidant
139  thermo oxidant
140  (
141  "oxidant",
142  stoicO2*O2
143  + stoicN2*N2
144  );
145 
146  dimensionedScalar stoichiometricAirFuelMassRatio
147  (
148  "stoichiometricAirFuelMassRatio",
149  dimless,
150  oxidant.Y()/FUEL.W()
151  );
152 
153  Info<< "stoichiometricAirFuelMassRatio "
154  << stoichiometricAirFuelMassRatio << ';' << endl;
155 
156  Info<< "Equilibrium flame temperature data ("
157  << P/1e5 << " bar)" << nl << nl
158  << setw(3) << "Phi"
159  << setw(12) << "ft"
160  << setw(7) << "T0"
161  << setw(12) << "Tad"
162  << setw(12) << "Teq"
163  << setw(12) << "Terror"
164  << setw(20) << "O2res (mole frac)" << nl
165  << endl;
166 
167 
168  // Loop over equivalence ratios
169  for (int i=0; i<16; i++)
170  {
171  scalar equiv = 0.6 + i*0.05;
172  scalar ft = 1/(1 + stoichiometricAirFuelMassRatio.value()/equiv);
173 
174  // Loop over initial temperatures
175  for (int j=0; j<28; j++)
176  {
177  scalar T0 = 300.0 + j*100.0;
178 
179  // Number of moles of species for one mole of fuel
180  scalar o2 = (1.0/equiv)*stoicO2;
181  scalar n2 = (0.79/0.21)*o2;
182  scalar fres = max(1.0 - 1.0/equiv, 0.0);
183  scalar fburnt = 1.0 - fres;
184 
185  // Initial guess for number of moles of product species
186  // ignoring product dissociation
187  scalar oresInit = max(1.0/equiv - 1.0, 0.0)*stoicO2;
188  scalar co2Init = fburnt*stoicCO2;
189  scalar h2oInit = fburnt*stoicH2O;
190 
191  scalar ores = oresInit;
192  scalar co2 = co2Init;
193  scalar h2o = h2oInit;
194 
195  scalar co = 0.0;
196  scalar h2 = 0.0;
197 
198  // Total number of moles in system
199  scalar N = fres + n2 + co2 + h2o + ores;
200 
201 
202  // Initial guess for adiabatic flame temperature
203  scalar adiabaticFlameTemperature =
204  T0
205  + (fburnt/(1.0 + o2 + n2))/(1.0/(1.0 + (1.0 + 0.79/0.21)*stoicO2))
206  *2000.0;
207 
208  scalar equilibriumFlameTemperature = adiabaticFlameTemperature;
209 
210 
211  // Iteration loop for adiabatic flame temperature
212  for (int j=0; j<20; j++)
213  {
214  if (j > 0)
215  {
216  co = co2*
217  min
218  (
219  CO2BreakUp.Kn(P, equilibriumFlameTemperature, N)
220  /::sqrt(max(ores, 0.001)),
221  1.0
222  );
223 
224  h2 = h2o*
225  min
226  (
227  H2OBreakUp.Kn(P, equilibriumFlameTemperature, N)
228  /::sqrt(max(ores, 0.001)),
229  1.0
230  );
231 
232  co2 = co2Init - co;
233  h2o = h2oInit - h2;
234  ores = oresInit + 0.5*co + 0.5*h2;
235  }
236 
237  thermo reactants
238  (
239  FUEL + o2*O2 + n2*N2
240  );
241 
242  thermo products
243  (
244  fres*FUEL + ores*O2 + n2*N2
245  + co2*CO2 + h2o*H2O + co*CO + h2*H2
246  );
247 
248 
249  scalar equilibriumFlameTemperatureNew =
250  products.THa(reactants.Ha(P, T0), P, adiabaticFlameTemperature);
251 
252  if (j==0)
253  {
254  adiabaticFlameTemperature = equilibriumFlameTemperatureNew;
255  }
256  else
257  {
258  equilibriumFlameTemperature = 0.5*
259  (
260  equilibriumFlameTemperature
261  + equilibriumFlameTemperatureNew
262  );
263  }
264  }
265 
266  Info<< setw(3) << equiv
267  << setw(12) << ft
268  << setw(7) << T0
269  << setw(12) << adiabaticFlameTemperature
270  << setw(12) << equilibriumFlameTemperature
271  << setw(12)
272  << adiabaticFlameTemperature - equilibriumFlameTemperature
273  << setw(12) << ores/N
274  << endl;
275  }
276  }
277 
278  Info<< nl << "end" << endl;
279 
280  return 0;
281 }
282 
283 
284 // ************************************************************************* //
A class for handling file names.
Definition: fileName.H:69
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:154
Thermodynamics mapping class to expose the absolute enthalpy functions.
psiReactionThermo & thermo
Definition: createFields.H:31
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
A class for handling words, derived from string.
Definition: word.H:59
Functions to search &#39;etc&#39; directories for configuration files etc.
Extract command arguments and options from the supplied argc and argv parameters. ...
Definition: argList.H:102
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if succesful.
Definition: doubleScalar.H:63
errorManip< error > abort(error &err)
Definition: errorManip.H:131
fileName findEtcFile(const fileName &, bool mandatory=false)
Search for a file using findEtcFiles.
Definition: etcFiles.C:252
Istream and Ostream manipulators taking arguments.
static const char nl
Definition: Ostream.H:262
Input from file stream.
Definition: IFstream.H:81
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:47
messageStream Info
label N
Definition: createFields.H:22
label n
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
Foam::argList args(argc, argv)
Namespace for OpenFOAM.