|
10 | 10 | #include "cantera/transport/TransportFactory.h" |
11 | 11 | #include "cantera/numerics/funcs.h" |
12 | 12 | #include "cantera/base/global.h" |
| 13 | +#include "cantera/thermo/Species.h" |
| 14 | + |
13 | 15 |
|
14 | 16 | using namespace std; |
15 | 17 |
|
@@ -84,10 +86,52 @@ Flow1D::Flow1D(ThermoPhase* ph, size_t nsp, size_t points) : |
84 | 86 | } |
85 | 87 | setupGrid(m_points, gr.data()); |
86 | 88 |
|
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 | + } |
91 | 135 | } |
92 | 136 |
|
93 | 137 | 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) |
470 | 514 |
|
471 | 515 | // Polynomial coefficients: |
472 | 516 | 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}; |
474 | 518 | const double c_CO2[6] = {18.741, -121.310, 273.500, -194.050, |
475 | | - 56.310, -5.8169}; |
| 519 | + 56.310, -5.8169}; |
476 | 520 |
|
477 | 521 | // Calculation of the two boundary values |
478 | 522 | double boundary_Rad_left = m_epsilon_left * StefanBoltz * pow(T(x, 0), 4); |
479 | 523 | double boundary_Rad_right = m_epsilon_right * StefanBoltz * pow(T(x, m_points - 1), 4); |
480 | 524 |
|
| 525 | + double coef = 0.0; |
481 | 526 | for (size_t j = jmin; j < jmax; j++) { |
482 | 527 | // calculation of the mean Planck absorption coefficient |
483 | 528 | 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; |
498 | 571 | } |
499 | | - k_P_CO2 /= k_P_ref; |
500 | | - k_P += m_press * X(x, m_kRadiating[0], j) * k_P_CO2; |
501 | 572 | } |
502 | 573 |
|
503 | 574 | // Calculation of the radiative heat loss term |
|
0 commit comments