28 : m_sol(std::move(sol)),
30 m_reacting(cfg.reacting),
31 m_collision(std::move(cfg.collision)),
37 cfg.sigma_T, cfg.sigma_v,
"sigma_T/sigma_v")),
39 cfg.nu_m_T, cfg.nu_m_v,
"nu_m_T/nu_m_v")),
44 if (m_plasma ==
nullptr)
46 throw std::invalid_argument(
47 "PlasmaCell: the phase is a " + m_sol->thermo()->type() +
48 ", not a PlasmaPhase, so it carries no electron temperature.");
51 m_wt.assign(m_sol->thermo()->molecularWeights().begin(),
52 m_sol->thermo()->molecularWeights().end());
57 m_cp_mass.resize(m_nsp);
60 const std::size_t nR = m_sol->kinetics()->nReactions();
66 m_sol->thermo()->speciesName(m_ie),
68 m_is_electron_rxn = std::move(electron_reactions.is_electron_reaction);
69 m_eps_th = std::move(electron_reactions.threshold_energy);
78 return m_sol->thermo()->speciesName(k);
82 double &dTg,
double &dTe,
double *dY,
double &lhs_Tg,
94 auto thermo = m_sol->thermo();
95 auto kin = m_sol->kinetics();
107 const double We = m_wt[m_ie];
115 double cv_heavy = 0.0;
116 for (std::size_t k = 0; k < m_nsp; k++)
120 cv_heavy += m_Yc[k] * (m_cpR[k] - 1.0) *
GasConstant / m_wt[k];
125 const double Ye_cap = std::max(m_Yc[m_ie], 1.0e-12);
126 lhs_Te = Ye_cap * cve * rho;
131 lhs_Tg = cv_heavy * rho;
135 "PlasmaCell::sourceTerms",
136 "the heavy-pool heat capacity is " + std::to_string(lhs_Tg) +
137 " J/m^3/K at Tg = " + std::to_string(Tg) +
" K, Te = " +
138 std::to_string(Te) +
" K, rho = " + std::to_string(rho) +
139 " kg/m^3; it must be positive for the gas-temperature balance.");
143 double sigma, nu_E, nu_eH, nu_eI, nu_eH_mass_weighted;
144 transport(Te, state, sigma, nu_E, nu_eH, nu_eI, nu_eH_mass_weighted);
154 const double P_el = nu_E * n_e * 1.5 *
Boltzmann * (Te - Tg);
158 const double P_joule = sigma * E * E;
161 double P_chem_H = 0.0, P_chem_e = 0.0, P_inel = 0.0;
162 for (std::size_t k = 0; k < m_nsp; k++)
166 kin->getNetProductionRates(m_wdot);
167 kin->getNetRatesOfProgress(m_rop);
168 thermo->getPartialMolarIntEnergies(m_uk);
169 for (std::size_t k = 0; k < m_nsp; k++)
175 dY[k] = m_wdot[k] * m_wt[k] / rho;
177 P_chem_H += m_uk[k] * m_wdot[k];
179 P_chem_e = m_wdot[m_ie] * cve * We * Te;
183 for (std::size_t i = 0; i < m_rop.size(); i++)
185 if (m_is_electron_rxn[i])
186 P_inel += m_eps_th[i] * m_rop[i];
191 dTe = (-P_chem_e - P_el - P_inel + P_joule) / lhs_Te;
192 dTg = (-P_chem_H + P_el + P_inel) / lhs_Tg;
203 if (!std::isfinite(dTg) || !std::isfinite(dTe))
206 "PlasmaCell::sourceTerms",
207 "non-finite temperature rate at Tg = " +
212 std::to_string(rho) +
214 std::to_string(dTg) +
216 std::to_string(dTe) +
").");
218 for (std::size_t k = 0; k < m_nsp; k++)
220 if (!std::isfinite(dY[k]))
223 "PlasmaCell::sourceTerms",
224 "non-finite production rate for species " +
231 std::to_string(rho) +
258 double sigma, nu_E, nu_eH, nu_eI, nu_eH_mass_weighted;
259 transport(Te, state, sigma, nu_E, nu_eH, nu_eI, nu_eH_mass_weighted);
266 return setState(Tg, Te, Y, rho).electron_density;
270 const double *Y,
double rho,
272 double &electron_density)
const
282 setState(Tg, Te, Y, rho);
287 double rho,
double *h)
const
289 setState(Tg, Te, Y, rho);
290 m_sol->thermo()->getPartialMolarEnthalpies(
292 for (std::size_t k = 0; k < m_nsp; k++)
296 const double We = m_wt[m_ie];
304 void PlasmaCell::fillSpeciesCp()
const
311 m_sol->thermo()->getCp_R(m_cpR);
312 for (std::size_t k = 0; k < m_nsp; k++)
316 const double We = m_wt[m_ie];
338 std::ostringstream message;
339 message <<
"Tg = " << Tg <<
" K, Te = "
340 << Te <<
" K, rho = " << rho
344 <<
" K, where the mechanism's thermo and rate fits hold.";
347 auto thermo = m_sol->thermo();
360 for (std::size_t k = 0; k < m_nsp; k++)
362 if (std::isnan(Y[k]))
365 "PlasmaCell::setState",
366 "the mass fraction of species " + m_sol->thermo()->speciesName(k) +
367 " is NaN at Tg = " + std::to_string(Tg) +
" K, Te = " +
368 std::to_string(Te) +
" K.");
370 m_Yc[k] = (Y[k] > 0.0) ? Y[k] : 0.0;
372 thermo->setMassFractions_NoNorm(Cantera::span<const double>(m_Yc.data(), m_nsp));
373 thermo->setElectronTemperature(Te);
374 thermo->setState_TD(Tg, rho);
384 double &sigma,
double &nu_E,
double &nu_eH,
385 double &nu_eI,
double &nu_eH_mass_weighted)
const
387 const double n_e = state.electron_density;
392 if (!m_collision.empty())
398 const double n_tot = state.pressure / (
Boltzmann * state.mean_temperature);
399 m_sol->thermo()->getMoleFractions(Cantera::span<double>(m_X.data(), m_nsp));
400 for (std::size_t k = 0; k < m_nsp; k++)
401 m_nk[k] = m_X[k] * n_tot;
402 m_collision.evaluate(Te, n_e, m_nk.data(), m_nsp, sigma, nu_E, nu_eH, nu_eI,
403 nu_eH_mass_weighted);
413 const double nu_m_eff =
416 :
evalAtState(m_nu_m_tab, Te,
"PlasmaCell::transport",
"nu_m(Te)",
"K",
417 "Extend the nu_m_T/nu_m_v table.");
424 sigma = m_sigma.empty()
426 :
evalAtState(m_sigma, Te,
"PlasmaCell::transport",
428 "Extend the sigma_T/sigma_v table.");
433 nu_eH_mass_weighted = 0.0;
Which reactions of a mechanism the electron takes part in, and what each of them costs the electron p...
One cell of two-temperature reacting plasma: the source terms the 0-D reactor and the 1-D channel bot...
The two-temperature quantities every model in this extension reads back from a PlasmaPhase,...
Evaluate a PropertyTable at a state, refusing a state outside its range.
size_t electronSpeciesIndex() const
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...
double electronDensity(double Tg, double Te, const double *Y, double rho) const
Electron number density [1/m^3], .
void updateSpeciesCp(double Tg, double Te, const double *Y, double rho) const
Refresh speciesCp() at one state without evaluating anything else.
void pressureAndElectronDensity(double Tg, double Te, const double *Y, double rho, double &p, double &electron_density) const
Total pressure [Pa] and electron number density [1/m^3] together, from the two-temperature equation o...
void sourceTerms(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).
PlasmaCell(std::shared_ptr< Cantera::Solution > sol, PlasmaCellConfig cfg)
Construct a PlasmaCell for a given plasma Solution and configuration.
void speciesEnthalpies(double Tg, double Te, const double *Y, double rho, double *h) const
Mass-basis species enthalpy h_k [J/kg], the energy one kilogram of species k carries in when the spec...
std::size_t nSpecies() const
double electricalConductivity(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.
TrialStateError(const std::string &procedure, std::string message)
constexpr double e
Elementary charge [C]. Exact (CODATA).
constexpr double m_e
Electron mass [kg] (CODATA 2022).
constexpr double Boltzmann
constexpr double TemperatureFloor
Lower limit of the mechanism's NASA polynomials [K].
double monatomicElectronCv(double electron_molecular_weight)
Electron specific heat at constant volume, per kg of ELECTRONS, .
constexpr double GasConstant
Universal gas constant [J/kmol/K] and Boltzmann's constant [J/K], from units.h rather than Cantera's ...
ElectronReactionIndex buildElectronReactionIndex(Cantera::Kinetics &kinetics, const std::string &electron, const std::vector< double > &species_h0k, std::size_t n_species, bool reacting)
Build the index for one mechanism.
constexpr double TemperatureCeiling
Upper limit of the physically meaningful range [K].
double evalAtState(const PropertyTable &table, double x, const char *procedure, const char *what, const char *unit, const char *remedy)
Value of table at x, refused outside its tabulated range.
TwoTemperatureState readTwoTemperatureState(const Cantera::PlasmaPhase &phase)
Read the two-temperature EOS back from a phase whose state is set.
The per-reaction data the electron pool's inelastic power needs.
std::vector< double > species_h0k
Per-species standard enthalpy of formation at 0 K [J/kmol], length nSpecies(), in mechanism species-i...
Optional power / Maxwellian-condition breakdown filled by rates() when a non-null pointer is passed.
double nu_eH
Electron-electron collision frequency [1/s] (Mitchner II-8.11e).
double P_elastic
< Elastic electron-heavy exchange power [W/m^3]
double P_chemical_e
Joule heating power [W/m^3].
double nu_eH_mass_weighted
double nu_ee
Electron-ion momentum-transfer collision frequency [1/s].
double P_Joule
Electron-heavy momentum-transfer collision frequency [1/s] (Mitchner II-13.3).
double P_inelastic
Heavy-species chemical power [W/m^3].
double nu_eI
sum_h nu_eh/m_h [1/kg/s] (Mitchner VIII-3.8, term 2)
double P_chemical_H
Electron chemical power [W/m^3].
The two-temperature equation of state at the state currently set on a phase, PHYSICS....
double pressure
Total [Pa].
double electron_density
[1/m^3]
Physical constants and unit conversions, in SI by default.