29bool equationHasElectron(
const std::string& equation,
const std::string& electron)
31 std::string s = equation;
33 if (ch ==
'+' || ch ==
'=' || ch ==
'<' || ch ==
'>') ch =
' ';
35 std::istringstream iss(s);
37 while (iss >> token) {
38 if (token == electron)
return true;
50 : m_sol(std::move(sol))
52 , m_ie(m_sol->thermo()->speciesIndex(
"e-"))
53 , m_reacting(cfg.reacting)
54 , m_collision(std::move(cfg.collision))
59 , m_sigma(
PropertyTable::fromTableOrScalar(cfg.sigma_T, cfg.sigma_v))
60 , m_nu_m_tab(
PropertyTable::fromTableOrScalar(cfg.nu_m_T, cfg.nu_m_v))
65 throw std::invalid_argument(
"ReactorRHS: mechanism has no 'e-' species.");
67 m_wt.assign(m_sol->thermo()->molecularWeights().begin(),
68 m_sol->thermo()->molecularWeights().end());
73 m_cp_mass.resize(m_nsp);
76 const std::size_t nR = m_sol->kinetics()->nReactions();
79 m_is_electron_rxn.assign(nR, 0);
85 const std::string e_name = m_sol->thermo()->speciesName(m_ie);
86 for (std::size_t i = 0; i < nR; i++) {
87 if (equationHasElectron(m_sol->kinetics()->reaction(i)->equation(), e_name)) {
88 m_is_electron_rxn[i] = 1;
95 return m_sol->thermo()->speciesName(k);
98void ReactorRHS::setState(
double Tg,
double Te,
const double* Y,
double rho,
double& P,
99 double& Xe,
double& Tmean,
double& n_e)
const
101 auto thermo = m_sol->thermo();
105 for (std::size_t k = 0; k < m_nsp; k++) m_Yc[k] = (Y[k] > 0.0) ? Y[k] : 0.0;
106 const double Tg_c = std::max(Tg, 200.0);
107 const double Te_c = std::max(Te, 200.0);
109 thermo->setElectronTemperature(Te_c);
110 thermo->setState_TD(Tg_c, rho);
111 P = thermo->pressure();
112 Xe = thermo->moleFraction(m_ie);
117 Tmean = (1.0 - Xe) * Tg_c + Xe * Te_c;
121void ReactorRHS::transport(
double Te,
double n_e,
double P,
double Tmean,
double& sigma,
122 double& nu_E,
double& cond_maxwell_2)
const
124 const double Te_c = std::max(Te, 200.0);
129 if (!m_collision.
empty()) {
134 const double n_tot = P / (
Boltzmann * Tmean);
136 for (std::size_t k = 0; k < m_nsp; k++) m_nk[k] = m_X[k] * n_tot;
137 m_collision.
evaluate(Te_c, n_e, m_nk.data(), m_nsp, sigma, nu_E, cond_maxwell_2);
144 const double nu_m_eff = m_nu_m_tab.empty() ? m_nu_m : m_nu_m_tab.eval(Te_c);
145 sigma = (nu_m_eff > 0.0)
147 : m_sigma.eval(Te_c);
149 cond_maxwell_2 = 0.0;
154 double& dTg,
double& dTe,
double* dY,
double& lhs_Tg,
157 auto thermo = m_sol->thermo();
158 auto kin = m_sol->kinetics();
160 double P, Xe, Tmean, n_e;
161 setState(Tg, Te, Y, rho, P, Xe, Tmean, n_e);
162 const double Tg_c = std::max(Tg, 200.0);
163 const double Te_c = std::max(Te, 200.0);
165 thermo->getCp_R(m_cpR);
166 const double We = m_wt[m_ie];
175 for (std::size_t k = 0; k < m_nsp; k++) {
185 double cv_heavy = 0.0;
186 for (std::size_t k = 0; k < m_nsp; k++) {
187 if (k == m_ie)
continue;
188 cv_heavy += m_Yc[k] * (m_cpR[k] - 1.0) *
GasConstant / m_wt[k];
193 const double Ye_cap = std::max(m_Yc[m_ie], 1.0e-12);
194 lhs_Te = Ye_cap * cve * rho;
195 lhs_Tg = std::max(cv_heavy * rho, 1.0e-3);
197 double sigma, nu_E, cond_maxwell_2;
198 transport(Te_c, n_e, P, Tmean, sigma, nu_E, cond_maxwell_2);
207 const double P_el = nu_E * n_e * 1.5 *
Boltzmann * (Te_c - Tg_c);
211 const double P_joule = sigma * E * E;
213 double P_chem = 0.0, P_chem_e = 0.0, P_inel = 0.0;
214 for (std::size_t k = 0; k < m_nsp; k++) dY[k] = 0.0;
216 kin->getNetProductionRates(m_wdot);
217 kin->getNetRatesOfProgress(m_rop);
218 thermo->getPartialMolarIntEnergies(m_uk);
226 for (std::size_t k = 0; k < m_nsp; k++) {
231 dY[k] = m_wdot[k] * m_wt[k] / rho;
232 if (k != m_ie) P_chem += m_uk[k] * m_wdot[k];
234 P_chem_e = m_wdot[m_ie] * cve * We * Te_c;
235 for (std::size_t i = 0; i < m_rop.size(); i++) {
236 if (m_is_electron_rxn[i]) P_inel += m_dU[i] * m_rop[i];
240 dTe = (-P_chem_e - P_el - P_inel + P_joule) / lhs_Te;
241 dTg = (-P_chem + P_el + P_inel) / lhs_Tg;
243 if (!std::isfinite(dTe)) dTe = 0.0;
244 if (!std::isfinite(dTg)) dTg = 0.0;
245 for (std::size_t k = 0; k < m_nsp; k++) {
246 if (!std::isfinite(dY[k])) dY[k] = 0.0;
249 if (diag !=
nullptr) {
266 double P, Xe, Tmean, n_e;
267 setState(Tg, Te, Y, rho, P, Xe, Tmean, n_e);
268 double sigma, nu_E, cond_maxwell_2;
269 transport(std::max(Te, 200.0), n_e, P, Tmean, sigma, nu_E, cond_maxwell_2);
276 double P, Xe, Tmean, n_e;
277 setState(Tg, Te, Y, rho, P, Xe, Tmean, n_e);
static double electronElectronCollisionFrequency(double n_e, double Te)
Electron-electron collision frequency [1/s] (Mitchner II-8.11e with Z=1), the closed-form ingredient...
void evaluate(double Te, double n_e, const double *n_k, std::size_t nsp, double &sigma, double &nu_E, double &cond_maxwell_2) const
Composition-resolved electron transport.
double conductivity(double Tg, double Te, const double *Y, double rho) const
Electrical conductivity [S/m] at a node state.
std::string speciesName(std::size_t k) const
Name of species k in the mechanism.
ReactorRHS(std::shared_ptr< Cantera::Solution > sol, Config cfg)
Construct a ReactorRHS for a given plasma Solution and configuration.
double electronDensity(double Tg, double Te, const double *Y, double rho) const
Electron number density [1/m^3], .
void rates(double Tg, double Te, const double *Y, double rho, double E, double &dTg, double &dTe, double *dY, double &lhs_Tg, double &lhs_Te, Diagnostics *diag=nullptr) const
Single-cell RHS (no transport, no volume work).
std::size_t nSpecies() const
constexpr double k_b
Boltzmann constant [J/K]. Exact (CODATA).
constexpr double R_kmol
Ideal gas constant [J/(kmol K)] (matches Cantera's GasConstant).
constexpr double e
Elementary charge [C]. Exact (CODATA).
constexpr double m_e
Electron mass [kg] (CODATA 2022).
constexpr double Boltzmann
constexpr double GasConstant
Optional power / Maxwellian-condition breakdown filled by rates() when a non-null pointer is passed.
double cond_maxwell_1
nu_ee/m_e [1/kg/s] (Mitchner VIII-3.8, term 1)
double P_Joule
Joule heating power [W/m^3].
double P_chemical_e
Electron chemical power [W/m^3].
double P_chemical
Heavy-species chemical power [W/m^3].
double P_inelastic
Inelastic electron-impact-reaction power [W/m^3].
double P_elastic
Elastic electron-heavy exchange power [W/m^3].
double cond_maxwell_2
sum_h nu_eh/m_h [1/kg/s] (Mitchner VIII-3.8, term 2)
Physical constants and unit conversions, in SI by default.