MEASUR-Tools-Suite v1.0.11
The MEASUR Tools Suite is a collection of industrial efficiency calculations written in C++ and with bindings for compilation to WebAssembly.
Loading...
Searching...
No Matches
gas_flue_gas_material.h
Go to the documentation of this file.
1#pragma once
2
14#include <cmath>
15#include <functional>
16#include <memory>
17#include <stdexcept>
18#include <string>
19#include <unordered_map>
20
26 public:
41 GasProperties(std::function<double(double t)> specificHeat, const double molecularWeight,
42 const double specificWeight, const double compPercent, const double compByVol, const int o2Generated,
43 const int heatingValue, const int heatingValueVolume, const double h2oGenerated,
44 const double co2Generated)
45 : specificHeat(std::move(specificHeat)), molecularWeight(molecularWeight), specificWeight(specificWeight),
46 compByVol(compPercent), compAdjByVol(compByVol), h2oGenerated(h2oGenerated), co2Generated(co2Generated),
47 o2Generated(o2Generated), heatingValue(heatingValue), heatingValueVolume(heatingValueVolume) {};
48
49 private:
50 friend class GasCompositions;
51 const std::function<double(double t)> specificHeat;
52 // compByWeight == X double bar, compAdjByVol == X bar in document
53 double compByWeight = 0;
54 const double molecularWeight, specificWeight, compByVol, compAdjByVol, h2oGenerated, co2Generated;
55
56 // TODO so2Generated is always 0 according to the one table, are these all the gas types we deal with or not?
57 const int so2Generated = 0, o2Generated, heatingValue, heatingValueVolume;
58};
59
60// TODO should be a private class but unit tests need access to this
61
67 public:
69 ProcessHeatPropertiesResults(double stoichAir, double excessAir, double availableHeat, double specificHeat,
70 double density, double heatValueFuel, double flueGasO2)
71 : stoichAir(stoichAir), excessAir(excessAir), availableHeat(availableHeat), specificHeat(specificHeat),
72 density(density), heatValueFuel(heatValueFuel), flueGasO2(flueGasO2) {}
73
75 double stoichAir = 0, excessAir = 0, availableHeat = 0, specificHeat = 0, density = 0, heatValueFuel = 0,
76 flueGasO2 = 0;
77 };
78
97 GasCompositions(std::string substance, const double CH4, const double C2H6, const double N2, const double H2,
98 const double C3H8, const double C4H10_CnH2n, const double H2O, const double CO, const double CO2,
99 const double SO2, const double O2)
100 : substance(std::move(substance)),
101 totalPercent(CH4 + C2H6 + N2 + H2 + C3H8 + C4H10_CnH2n + H2O + CO + CO2 + SO2 + O2),
102 CH4(std::make_shared<GasProperties>([](double t) { return 4.23 + 0.01177 * t; }, 16.042, 0.042417, CH4,
103 CH4 / totalPercent, 64, 23875, 1012, 36.032, 44.01)),
104 C2H6(std::make_shared<GasProperties>([](double t) { return 4.04 + 0.01636 * t; }, 30.068, 0.079503, C2H6,
105 C2H6 / totalPercent, 112, 22323, 1773, 54.048, 88.02)),
106 N2(std::make_shared<GasProperties>([](double t) { return 9.47 - 3.47 * 1000 / t + 1.07 * 1000000 / (t * t); },
107 28.016, 0.074077, N2, N2 / totalPercent, 0, 0, 0, 0, 0)),
108 H2(std::make_shared<GasProperties>([](double t) { return 5.76 + 0.578 * t / 1000 + 20 / pow(t, 0.5); }, 2.016,
109 0.005331, H2, H2 / totalPercent, 16, 61095, 325, 18.016, 0)),
110 C3H8(std::make_shared<GasProperties>(
111 [](double t) {
112 (void)t;
113 return 17.108;
114 },
115 44.094, 0.116589, C3H8, C3H8 / totalPercent, 160, 21669, 2523, 72.064, 132.03)),
116 C4H10_CnH2n(std::make_shared<GasProperties>(
117 [](double t) {
118 (void)t;
119 return 22.202;
120 },
121 58.12, 0.153675, C4H10_CnH2n, C4H10_CnH2n / totalPercent, 208, 21321, 3270, 90.08, 176.04)),
122 H2O(std::make_shared<GasProperties>([](double t) { return 19.86 - 597 / pow(t, 0.5) + 7500 / t; }, 18.016,
123 0.047636, H2O, H2O / totalPercent, 0, 0, 0, 18.016, 0)),
124 CO(std::make_shared<GasProperties>([](double t) { return 9.46 - 3.29 * 1000 / t + 1.07 * 1000000 / (t * t); },
125 28.01, 0.074061, CO, CO / totalPercent, 16, 4347, 321, 0, 44.01)),
126 CO2(std::make_shared<GasProperties>(
127 [](double t) { return 16.2 - 6.53 * 1000 / t + 1.41 * 1000000 / (t * t); }, 44.01, 0.116367, CO2,
128 CO2 / totalPercent, 0, 0, 0, 0, 44.01)),
129 SO2(std::make_shared<GasProperties>(
130 [](double t) {
131 (void)t;
132 return 17.472;
133 },
134 64.06, 0.169381, SO2, SO2 * 100 / totalPercent, 0, 0, 0, 0, 0)),
135 O2(std::make_shared<GasProperties>([](double t) { return 11.515 - 172 / pow(t, 0.5) + 1530 / t; }, 32.00,
136 0.084611, O2, O2 / totalPercent, -32, 0, 0, 0, 0)) {
137 gasses = {{"CH4", this->CH4}, {"C2H6", this->C2H6}, {"N2", this->N2},
138 {"H2", this->H2}, {"C3H8", this->C3H8}, {"C4H10_CnH2n", this->C4H10_CnH2n},
139 {"H2O", this->H2O}, {"CO", this->CO}, {"CO2", this->CO2},
140 {"SO2", this->SO2}, {"O2", this->O2}};
141
142 calculateCompByWeight();
143 heatingValue = calculateHeatingValueFuel();
144 heatingValueVolume = calculateHeatingValueFuelVolume();
145 specificGravity = calculateSpecificGravity();
146 stoichometricAir = calculateStoichometricAir();
147 }
148
154 double getGasByVol(const std::string& gasName) const {
155 auto const gas = gasses.find(gasName);
156 if (gas == gasses.end()) {
157 throw std::runtime_error("Cannot find " + gasName + " in gasses");
158 }
159 return gas->second->compByVol;
160 }
161
162 double getHeatingValue() const { return heatingValue; };
163 double getHeatingValueVolume() const { return heatingValueVolume; };
164 double getSpecificGravity() const { return specificGravity; };
165 double getStoichometricAir() const { return stoichometricAir; };
166
172 double getSaturationTemperature(const double ppH2O) const;
173
179 double getEnthalpyAtSaturation(const double ppH2O) const;
180
202 ProcessHeatPropertiesResults getProcessHeatProperties(const double flueGasTempF, const double flueGasO2,
203 const double combAirTemperatureF, const double fuelTempF = 60,
204 const double ambientAirTempF = 60,
205 const double combAirMoisturePerc = 0,
206 const double excessAir = 0);
207
208 double calculateExcessAir(double flueGasO2);
209 double calculateO2(double excessAir);
210
215 std::string getSubstance() const;
216
221 int getID() const { return this->id; }
222
227 void setID(const int id) { this->id = id; }
228
229 private:
230 friend class GasFlueGasMaterial;
231 friend class DefaultData;
232
233 double calculateSpecificGravity();
234 double calculateStoichometricAir();
235
236 void calculateCompByWeight();
237 double calculateSensibleHeat(double combustionAirTemp);
238 double calculateHeatCombustionAir(double combustionAirTemp, double excessAir);
239 void calculateMassFlueGasComponents(double excessAir);
240 double calculateHeatingValueFuel();
241 double calculateHeatingValueFuelVolume();
242 void calculateEnthalpy();
243 double calculateTotalHeatContentFlueGas(double flueGasTemperature);
244
245 GasCompositions(std::string substance, const double CH4, const double C2H6, const double N2, const double H2,
246 const double C3H8, const double C4H10_CnH2n, const double H2O, const double CO, const double CO2,
247 const double SO2, const double O2, const double heatingValue, const double heatingValueVolume,
248 const double specificGravity, const double stoichometricAir = 0)
249 : substance(std::move(substance)),
250 totalPercent(CH4 + C2H6 + N2 + H2 + C3H8 + C4H10_CnH2n + H2O + CO + CO2 + SO2 + O2),
251 CH4(std::make_shared<GasProperties>([](double t) { return 4.23 + 0.01177 * t; }, 16.042, 0.042417, CH4,
252 CH4 / totalPercent, 64, 23875, 1012, 36.032, 44.01)),
253 C2H6(std::make_shared<GasProperties>([](double t) { return 4.04 + 0.01636 * t; }, 30.068, 0.079503, C2H6,
254 C2H6 / totalPercent, 112, 22323, 1773, 54.048, 88.02)),
255 N2(std::make_shared<GasProperties>([](double t) { return 9.47 - 3.47 * 1000 / t + 1.07 * 1000000 / (t * t); },
256 28.016, 0.074077, N2, N2 / totalPercent, 0, 0, 0, 0, 0)),
257 H2(std::make_shared<GasProperties>([](double t) { return 5.76 + 0.578 * t / 1000 + 20 / pow(t, 0.5); }, 2.016,
258 0.005331, H2, H2 / totalPercent, 16, 61095, 325, 18.016, 0)),
259 C3H8(std::make_shared<GasProperties>(
260 [](double t) {
261 (void)t;
262 return 17.108;
263 },
264 44.094, 0.116589, C3H8, C3H8 / totalPercent, 160, 21669, 2523, 72.064, 132.03)),
265 C4H10_CnH2n(std::make_shared<GasProperties>(
266 [](double t) {
267 (void)t;
268 return 22.202;
269 },
270 58.12, 0.153675, C4H10_CnH2n, C4H10_CnH2n / totalPercent, 208, 21321, 3270, 90.08, 176.04)),
271 H2O(std::make_shared<GasProperties>([](double t) { return 19.86 - 597 / pow(t, 0.5) + 7500 / t; }, 18.016,
272 0.047636, H2O, H2O / totalPercent, 0, 0, 0, 18.016, 0)),
273 CO(std::make_shared<GasProperties>([](double t) { return 9.46 - 3.29 * 1000 / t + 1.07 * 1000000 / (t * t); },
274 28.01, 0.074061, CO, CO / totalPercent, 16, 4347, 321, 0, 44.01)),
275 CO2(std::make_shared<GasProperties>(
276 [](double t) { return 16.2 - 6.53 * 1000 / t + 1.41 * 1000000 / (t * t); }, 44.01, 0.116367, CO2,
277 CO2 / totalPercent, 0, 0, 0, 0, 44.01)),
278 SO2(std::make_shared<GasProperties>(
279 [](double t) {
280 (void)t;
281 return 17.472;
282 },
283 64.06, 0.169381, SO2, SO2 * 100 / totalPercent, 0, 0, 0, 0, 0)),
284 O2(std::make_shared<GasProperties>([](double t) { return 11.515 - 172 / pow(t, 0.5) + 1530 / t; }, 32.00,
285 0.084611, O2, O2 / totalPercent, -32, 0, 0, 0, 0)),
286 heatingValue(heatingValue), specificGravity(specificGravity), heatingValueVolume(heatingValueVolume),
287 stoichometricAir(stoichometricAir) {
288 gasses = {{"CH4", this->CH4}, {"C2H6", this->C2H6}, {"N2", this->N2},
289 {"H2", this->H2}, {"C3H8", this->C3H8}, {"C4H10_CnH2n", this->C4H10_CnH2n},
290 {"H2O", this->H2O}, {"CO", this->CO}, {"CO2", this->CO2},
291 {"SO2", this->SO2}, {"O2", this->O2}};
292 }
293
294 // the hash map holds a reference to the GasProperties below for easier iterable summations
295 std::unordered_map<std::string, std::shared_ptr<GasProperties>> gasses;
296 int id = 0;
297 std::string substance;
298 double totalPercent;
299 double hH2Osat = 0, tH2Osat = 0;
300 double mH2O = 0, mCO2 = 0, mO2 = 0, mN2 = 0, mSO2 = 0;
301 std::shared_ptr<GasProperties> CH4, C2H6, N2, H2, C3H8, C4H10_CnH2n, H2O, CO, CO2, SO2, O2;
302 double heatingValue = 0, specificGravity = 0, heatingValueVolume = 0, stoichometricAir = 0;
303
309 double getExcessAir(const double flueGasO2) const;
310
311 void flueGasO2AdjustForCalcError(const double excessAir, double& flueO2) const;
312};
313
324 public:
335 GasFlueGasMaterial(const double flueGasTemperature, const double excessAirPercentage,
336 const double combustionAirTemperature, GasCompositions compositions,
337 const double fuelTemperature)
338 : flueGasTemperature(flueGasTemperature), excessAirPercentage(excessAirPercentage / 100.0),
339 combustionAirTemperature(combustionAirTemperature), fuelTemperature(fuelTemperature),
340 compositions(std::move(compositions)) {}
341
350 double getHeatLoss();
351
352 private:
353 const double flueGasTemperature, excessAirPercentage, combustionAirTemperature, fuelTemperature;
354 GasCompositions compositions;
355};
ProcessHeatPropertiesResults getProcessHeatProperties(const double flueGasTempF, const double flueGasO2, const double combAirTemperatureF, const double fuelTempF=60, const double ambientAirTempF=60, const double combAirMoisturePerc=0, const double excessAir=0)
double getGasByVol(const std::string &gasName) const
void setID(const int id)
std::string getSubstance() const
GasCompositions(std::string substance, const double CH4, const double C2H6, const double N2, const double H2, const double C3H8, const double C4H10_CnH2n, const double H2O, const double CO, const double CO2, const double SO2, const double O2)
double getExcessAir(const double flueGasO2) const
double getEnthalpyAtSaturation(const double ppH2O) const
double getSaturationTemperature(const double ppH2O) const
GasFlueGasMaterial(const double flueGasTemperature, const double excessAirPercentage, const double combustionAirTemperature, GasCompositions compositions, const double fuelTemperature)
GasProperties(std::function< double(double t)> specificHeat, const double molecularWeight, const double specificWeight, const double compPercent, const double compByVol, const int o2Generated, const int heatingValue, const int heatingValueVolume, const double h2oGenerated, const double co2Generated)