Skip to content

Commit a9bf1e5

Browse files
committed
[oneD] reproducing PR965 with yaml file addition
1 parent 1dd756a commit a9bf1e5

File tree

3 files changed

+393
-30
lines changed

3 files changed

+393
-30
lines changed

include/cantera/oneD/Flow1D.h

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,8 @@ class Flow1D : public Domain1D
447447
* Computes the radiative heat loss vector over points jmin to jmax and stores
448448
* the data in the qdotRadiation variable.
449449
*
450+
* The `fit-type` of `polynomial` is uses the model described below.
451+
*
450452
* The simple radiation model used was established by Liu and Rogg
451453
* @cite liu1991. This model considers the radiation of CO2 and H2O.
452454
*
@@ -457,6 +459,20 @@ class Flow1D : public Domain1D
457459
* lines are taken from the RADCAL program @cite RADCAL.
458460
* The coefficients for the polynomials are taken from
459461
* [TNF Workshop](https://tnfworkshop.org/radiation/) material.
462+
*
463+
*
464+
* The `fit-type` of `table` is uses the model described below.
465+
*
466+
* Spectra for molecules are downloaded with HAPI library from // https://hitran.org/hapi/
467+
* [R.V. Kochanov, I.E. Gordon, L.S. Rothman, P. Wcislo, C. Hill, J.S. Wilzewski,
468+
* HITRAN Application Programming Interface (HAPI): A comprehensive approach
469+
* to working with spectroscopic data, J. Quant. Spectrosc. Radiat. Transfer 177,
470+
* 15-30 (2016), https://doi.org/10.1016/j.jqsrt.2016.03.005].
471+
*
472+
* Planck mean optical path lengths are what are read in from a YAML input file.
473+
*
474+
*
475+
*
460476
*/
461477
void computeRadiation(double* x, size_t jmin, size_t jmax);
462478

@@ -853,14 +869,6 @@ class Flow1D : public Domain1D
853869
Kinetics* m_kin = nullptr;
854870
Transport* m_trans = nullptr;
855871

856-
// boundary emissivities for the radiation calculations
857-
double m_epsilon_left = 0.0;
858-
double m_epsilon_right = 0.0;
859-
860-
//! Indices within the ThermoPhase of the radiating species. First index is
861-
//! for CO2, second is for H2O.
862-
vector<size_t> m_kRadiating;
863-
864872
// flags
865873
vector<bool> m_do_energy;
866874
bool m_do_soret = false;
@@ -874,6 +882,16 @@ class Flow1D : public Domain1D
874882
//! radiative heat loss vector
875883
vector<double> m_qdotRadiation;
876884

885+
// boundary emissivities for the radiation calculations
886+
double m_epsilon_left = 0.0;
887+
double m_epsilon_right = 0.0;
888+
889+
std::map<std::string, int> m_absorptionSpecies; //!< Absorbing species
890+
AnyMap m_PMAC; //!< Absorption coefficient data for each species
891+
892+
// Old radiation variable that can not be deleted for some reason
893+
std::vector<size_t> m_kRadiating;
894+
877895
// fixed T and Y values
878896
vector<double> m_fixedtemp;
879897
vector<double> m_zfix;

src/oneD/Flow1D.cpp

Lines changed: 93 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include "cantera/transport/TransportFactory.h"
1111
#include "cantera/numerics/funcs.h"
1212
#include "cantera/base/global.h"
13+
#include "cantera/thermo/Species.h"
14+
1315

1416
using namespace std;
1517

@@ -84,10 +86,52 @@ Flow1D::Flow1D(ThermoPhase* ph, size_t nsp, size_t points) :
8486
}
8587
setupGrid(m_points, gr.data());
8688

87-
// Find indices for radiating species
88-
m_kRadiating.resize(2, npos);
89-
m_kRadiating[0] = m_thermo->speciesIndex("CO2");
90-
m_kRadiating[1] = m_thermo->speciesIndex("H2O");
89+
// Parse radiation data from the YAML file
90+
for (auto& name : m_thermo->speciesNames()) {
91+
auto& data = m_thermo->species(name)->input;
92+
if (data.hasKey("radiation")) {
93+
cout << "Radiation data found for species " << name << endl;
94+
m_absorptionSpecies.insert({name, m_thermo->speciesIndex(name)});
95+
if (data["radiation"].hasKey("fit-type")) {
96+
m_PMAC[name]["fit-type"] = data["radiation"]["fit-type"].asString();
97+
} else {
98+
throw InputFileError("Flow1D::Flow1D", data,
99+
"No 'fit-type' entry found for species '{}'", name);
100+
}
101+
102+
// This is the direct tabulation of the optical path length
103+
if (data["radiation"]["fit-type"] == "table") {
104+
if (data["radiation"].hasKey("temperatures")) {
105+
cout << "Storing temperatures for species " << name << endl;
106+
// Each species may have a specific set of temperatures that are used
107+
m_PMAC[name]["temperatures"] = data["radiation"]["temperatures"].asVector<double>();
108+
} else {
109+
throw InputFileError("Flow1D::Flow1D", data,
110+
"No 'temperatures' entry found for species '{}'", name);
111+
}
112+
if (data["radiation"].hasKey("data")) {
113+
cout << "Storing data for species " << name << endl;
114+
// This data is the Plank mean absorption coefficient
115+
m_PMAC[name]["coefficients"] = data["radiation"]["data"].asVector<double>();
116+
} else {
117+
throw InputFileError("Flow1D::Flow1D", data,
118+
"No 'data' entry found for species '{}'", name);
119+
}
120+
} else if (data["radiation"]["fit-type"] == "polynomial") {
121+
cout << "Polynomial fit found for species " << name << endl;
122+
if (data["radiation"].hasKey("data")) {
123+
cout << "Storing data for species " << name << endl;
124+
m_PMAC[name]["coefficients"] = data["radiation"]["data"].asVector<double>();
125+
} else {
126+
throw InputFileError("Flow1D::Flow1D", data,
127+
"No 'data' entry found for species '{}'", name);
128+
}
129+
} else {
130+
throw InputFileError("Flow1D::Flow1D", data,
131+
"Invalid 'fit-type' entry found for species '{}'", name);
132+
}
133+
}
134+
}
91135
}
92136

93137
Flow1D::Flow1D(shared_ptr<ThermoPhase> th, size_t nsp, size_t points)
@@ -470,34 +514,61 @@ void Flow1D::computeRadiation(double* x, size_t jmin, size_t jmax)
470514

471515
// Polynomial coefficients:
472516
const double c_H2O[6] = {-0.23093, -1.12390, 9.41530, -2.99880,
473-
0.51382, -1.86840e-5};
517+
0.51382, -1.86840e-5};
474518
const double c_CO2[6] = {18.741, -121.310, 273.500, -194.050,
475-
56.310, -5.8169};
519+
56.310, -5.8169};
476520

477521
// Calculation of the two boundary values
478522
double boundary_Rad_left = m_epsilon_left * StefanBoltz * pow(T(x, 0), 4);
479523
double boundary_Rad_right = m_epsilon_right * StefanBoltz * pow(T(x, m_points - 1), 4);
480524

525+
double coef = 0.0;
481526
for (size_t j = jmin; j < jmax; j++) {
482527
// calculation of the mean Planck absorption coefficient
483528
double k_P = 0;
484-
// Absorption coefficient for H2O
485-
if (m_kRadiating[1] != npos) {
486-
double k_P_H2O = 0;
487-
for (size_t n = 0; n <= 5; n++) {
488-
k_P_H2O += c_H2O[n] * pow(1000 / T(x, j), (double) n);
489-
}
490-
k_P_H2O /= k_P_ref;
491-
k_P += m_press * X(x, m_kRadiating[1], j) * k_P_H2O;
492-
}
493-
// Absorption coefficient for CO2
494-
if (m_kRadiating[0] != npos) {
495-
double k_P_CO2 = 0;
496-
for (size_t n = 0; n <= 5; n++) {
497-
k_P_CO2 += c_CO2[n] * pow(1000 / T(x, j), (double) n);
529+
530+
for(const auto& [sp_name, sp_idx] : m_absorptionSpecies) {
531+
if (m_PMAC[sp_name]["fit-type"].asString() == "table") {
532+
// temperature table interval search
533+
int T_index = 0;
534+
const int OPL_table_size = m_PMAC[sp_name]["temperatures"].asVector<double>().size();
535+
for (int k = 0; k < OPL_table_size; k++) {
536+
if (T(x, j) < m_PMAC[sp_name]["temperatures"].asVector<double>()[k]) {
537+
if (T(x, j) < m_PMAC[sp_name]["temperatures"].asVector<double>()[0]) {
538+
T_index = 0; //lower table limit
539+
}
540+
else {
541+
T_index = k;
542+
}
543+
break;
544+
}
545+
else {
546+
T_index=OPL_table_size-1; //upper table limit
547+
}
548+
}
549+
550+
// absorption coefficient for specie
551+
double k_P_specie = 0.0;
552+
if ((T_index == 0) || (T_index == OPL_table_size-1)) {
553+
coef=log(1.0/m_PMAC[sp_name]["coefficients"].asVector<double>()[T_index]);
554+
}
555+
else {
556+
coef=log(1.0/m_PMAC[sp_name]["coefficients"].asVector<double>()[T_index-1])+
557+
(log(1.0/m_PMAC[sp_name]["coefficients"].asVector<double>()[T_index])-log(1.0/m_PMAC[sp_name]["coefficients"].asVector<double>()[T_index-1]))*
558+
(T(x, j)-m_PMAC[sp_name]["temperatures"].asVector<double>()[T_index-1])/(m_PMAC[sp_name]["temperatures"].asVector<double>()[T_index]-m_PMAC[sp_name]["temperatures"].asVector<double>()[T_index-1]);
559+
}
560+
k_P_specie = exp(coef);
561+
562+
k_P_specie /= k_P_ref;
563+
k_P += m_press * X(x, m_absorptionSpecies[sp_name], j) * k_P_specie;
564+
} else if (m_PMAC[sp_name]["fit-type"].asString() == "polynomial") {
565+
double k_P_specie = 0.0;
566+
for (size_t n = 0; n <= 5; n++) {
567+
k_P_specie += m_PMAC[sp_name]["coefficients"].asVector<double>()[n] * pow(1000 / T(x, j), (double) n);
568+
}
569+
k_P_specie /= k_P_ref;
570+
k_P += m_press * X(x, m_absorptionSpecies[sp_name], j) * k_P_specie;
498571
}
499-
k_P_CO2 /= k_P_ref;
500-
k_P += m_press * X(x, m_kRadiating[0], j) * k_P_CO2;
501572
}
502573

503574
// Calculation of the radiative heat loss term

0 commit comments

Comments
 (0)