1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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.
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
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/>.
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.
32 \*---------------------------------------------------------------------------*/
36 #include "dictionary.H"
38 #include "OSspecific.H"
41 #include "specieThermo.H"
42 #include "janafThermo.H"
43 #include "perfectGas.H"
47 typedef specieThermo<janafThermo<perfectGas> > thermo;
49 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
51 int main(int argc, char *argv[])
53 argList::validArgs.append("controlFile");
54 argList args(argc, argv);
56 const fileName controlFileName = args[1];
58 // Construct control dictionary
59 IFstream controlFile(controlFileName);
61 // Check controlFile stream is OK
62 if (!controlFile.good())
64 FatalErrorIn(args.executable())
65 << "Cannot read file " << controlFileName
69 dictionary control(controlFile);
72 scalar P(readScalar(control.lookup("P")));
73 const word fuelName(control.lookup("fuel"));
74 scalar n(readScalar(control.lookup("n")));
75 scalar m(readScalar(control.lookup("m")));
78 Info<< nl << "Reading Burcat data dictionary" << endl;
80 fileName BurcatCpDataFileName(findEtcFile("thermoData/BurcatCpData"));
82 // Construct control dictionary
83 IFstream BurcatCpDataFile(BurcatCpDataFileName);
85 // Check BurcatCpData stream is OK
86 if (!BurcatCpDataFile.good())
88 FatalErrorIn(args.executable())
89 << "Cannot read file " << BurcatCpDataFileName
93 dictionary thermoData(BurcatCpDataFile);
96 Info<< nl << "Reading Burcat data for relevant species" << nl << endl;
99 thermo FUEL(thermoData.lookup(fuelName));
100 thermo O2(thermoData.lookup("O2"));
101 thermo N2(thermoData.lookup("N2"));
104 thermo CO2(thermoData.lookup("CO2"));
105 thermo H2O(thermoData.lookup("H2O"));
108 thermo CO(thermoData.lookup("CO"));
109 thermo H2(thermoData.lookup("H2"));
112 // Product dissociation reactions
125 // Stoiciometric number of moles of species for one mole of fuel
126 scalar stoicO2 = n + m/4.0;
127 scalar stoicN2 = (0.79/0.21)*(n + m/4.0);
129 scalar stoicH2O = m/2.0;
139 dimensionedScalar stoichiometricAirFuelMassRatio
141 "stoichiometricAirFuelMassRatio",
143 (oxidant.W()*oxidant.nMoles())/FUEL.W()
146 Info<< "stoichiometricAirFuelMassRatio "
147 << stoichiometricAirFuelMassRatio << ';' << endl;
149 Info<< "Equilibrium flame temperature data ("
150 << P/1e5 << " bar)" << nl << nl
156 << setw(12) << "Terror"
157 << setw(20) << "O2res (mole frac)" << nl
161 // Loop over equivalence ratios
162 for (int i=0; i<16; i++)
164 scalar equiv = 0.6 + i*0.05;
165 scalar ft = 1/(1 + stoichiometricAirFuelMassRatio.value()/equiv);
167 // Loop over initial temperatures
168 for (int j=0; j<28; j++)
170 scalar T0 = 300.0 + j*100.0;
172 // Number of moles of species for one mole of fuel
173 scalar o2 = (1.0/equiv)*stoicO2;
174 scalar n2 = (0.79/0.21)*o2;
175 scalar fres = max(1.0 - 1.0/equiv, 0.0);
176 scalar fburnt = 1.0 - fres;
178 // Initial guess for number of moles of product species
179 // ignoring product dissociation
180 scalar oresInit = max(1.0/equiv - 1.0, 0.0)*stoicO2;
181 scalar co2Init = fburnt*stoicCO2;
182 scalar h2oInit = fburnt*stoicH2O;
184 scalar ores = oresInit;
185 scalar co2 = co2Init;
186 scalar h2o = h2oInit;
191 // Total number of moles in system
192 scalar N = fres + n2 + co2 + h2o + ores;
195 // Initial guess for adiabatic flame temperature
196 scalar adiabaticFlameTemperature =
198 + (fburnt/(1.0 + o2 + n2))/(1.0/(1.0 + (1.0 + 0.79/0.21)*stoicO2))
201 scalar equilibriumFlameTemperature = adiabaticFlameTemperature;
204 // Iteration loop for adiabatic flame temperature
205 for (int j=0; j<20; j++)
213 CO2BreakUp.Kn(equilibriumFlameTemperature, P, N)
214 /::sqrt(max(ores, 0.001)),
221 H2OBreakUp.Kn(equilibriumFlameTemperature, P, N)
222 /::sqrt(max(ores, 0.001)),
228 ores = oresInit + 0.5*co + 0.5*h2;
238 fres*FUEL + ores*O2 + n2*N2
239 + co2*CO2 + h2o*H2O + co*CO + h2*H2
243 scalar equilibriumFlameTemperatureNew =
244 products.TH(reactants.H(T0), adiabaticFlameTemperature);
248 adiabaticFlameTemperature = equilibriumFlameTemperatureNew;
252 equilibriumFlameTemperature = 0.5*
254 equilibriumFlameTemperature
255 + equilibriumFlameTemperatureNew
260 Info<< setw(3) << equiv
263 << setw(12) << adiabaticFlameTemperature
264 << setw(12) << equilibriumFlameTemperature
266 << adiabaticFlameTemperature - equilibriumFlameTemperature
267 << setw(12) << ores/N
272 Info<< nl << "end" << endl;
278 // ************************************************************************* //