Skip to content

Commit f66f4f1

Browse files
committed
[oneD] reproducing PR965 with yaml file addition
1 parent d095f70 commit f66f4f1

File tree

3 files changed

+393
-22
lines changed

3 files changed

+393
-22
lines changed

include/cantera/oneD/Flow1D.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,8 @@ class Flow1D : public Domain1D
465465
* Computes the radiative heat loss vector over points jmin to jmax and stores
466466
* the data in the qdotRadiation variable.
467467
*
468+
* The `fit-type` of `polynomial` is uses the model described below.
469+
*
468470
* The simple radiation model used was established by Liu and Rogg
469471
* @cite liu1991. This model considers the radiation of CO2 and H2O.
470472
*
@@ -475,6 +477,20 @@ class Flow1D : public Domain1D
475477
* lines are taken from the RADCAL program @cite RADCAL.
476478
* The coefficients for the polynomials are taken from
477479
* [TNF Workshop](https://tnfworkshop.org/radiation/) material.
480+
*
481+
*
482+
* The `fit-type` of `table` is uses the model described below.
483+
*
484+
* Spectra for molecules are downloaded with HAPI library from // https://hitran.org/hapi/
485+
* [R.V. Kochanov, I.E. Gordon, L.S. Rothman, P. Wcislo, C. Hill, J.S. Wilzewski,
486+
* HITRAN Application Programming Interface (HAPI): A comprehensive approach
487+
* to working with spectroscopic data, J. Quant. Spectrosc. Radiat. Transfer 177,
488+
* 15-30 (2016), https://doi.org/10.1016/j.jqsrt.2016.03.005].
489+
*
490+
* Planck mean optical path lengths are what are read in from a YAML input file.
491+
*
492+
*
493+
*
478494
*/
479495
void computeRadiation(double* x, size_t jmin, size_t jmax);
480496

@@ -952,6 +968,16 @@ class Flow1D : public Domain1D
952968
//! radiative heat loss vector
953969
vector<double> m_qdotRadiation;
954970

971+
// boundary emissivities for the radiation calculations
972+
double m_epsilon_left = 0.0;
973+
double m_epsilon_right = 0.0;
974+
975+
std::map<std::string, int> m_absorptionSpecies; //!< Absorbing species
976+
AnyMap m_PMAC; //!< Absorption coefficient data for each species
977+
978+
// Old radiation variable that can not be deleted for some reason
979+
std::vector<size_t> m_kRadiating;
980+
955981
// fixed T and Y values
956982
//! Fixed values of the temperature at each grid point that are used when solving
957983
//! with the energy equation disabled.

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

@@ -81,10 +83,52 @@ Flow1D::Flow1D(ThermoPhase* ph, size_t nsp, size_t points) :
8183
}
8284
setupGrid(m_points, gr.data());
8385

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

90134
Flow1D::Flow1D(shared_ptr<ThermoPhase> th, size_t nsp, size_t points)
@@ -472,34 +516,61 @@ void Flow1D::computeRadiation(double* x, size_t jmin, size_t jmax)
472516

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

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

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

505576
// Calculation of the radiative heat loss term

0 commit comments

Comments
 (0)