rizer.cantera_ext
C++ Cantera 1-D plasma extension (custom Domain1D models and solvers)
Toggle main menu visibility
Loading...
Searching...
No Matches
Plasma0DReactor.cpp
Go to the documentation of this file.
1
#include "
Plasma0DReactor.h
"
2
#include "
PlasmaRates.h
"
3
#include "
units.h
"
4
5
#include "
cantera/thermo/ThermoPhase.h
"
6
7
#include <algorithm>
8
#include <cmath>
9
10
namespace
rizer
{
11
12
namespace
{
13
Cantera::shared_ptr<Cantera::Solution>
14
loadMechanism(
const
std::string& mech,
const
std::string& phase)
15
{
16
registerPlasmaRates
();
// Idempotent
17
return
Cantera::newSolution
(mech, phase);
18
}
19
}
// namespace
20
21
Plasma0DReactor::Plasma0DReactor
(
const
Config
& cfg)
22
: m_sol(loadMechanism(cfg.mech, cfg.phase))
23
, m_gap(cfg.gap)
24
{
25
auto
thermo = m_sol->thermo();
26
const
std::size_t nsp = thermo->nSpecies();
27
// Locate the electron pseudo-species; its index is used throughout (mole/mass
28
// fraction lookups, is_electron flag below, and the partial-pressure split in
29
// rhs()).
30
m_ie = thermo->speciesIndex(
"e-"
);
31
if
(m_ie ==
Cantera::npos
) {
32
throw
std::invalid_argument(
"Plasma0DReactor: mechanism has no 'e-' species."
);
33
}
34
// Fill molar_mass [kg/mol] and is_electron into the per-species collision specs.
35
std::vector<double> wt(thermo->molecularWeights().begin(),
36
thermo->molecularWeights().end());
// kg/kmol
37
std::vector<CollisionModel::SpeciesSpec> specs = cfg.
specs
;
38
specs.resize(nsp);
39
for
(std::size_t k = 0; k < nsp; k++) {
40
specs[k].molar_mass = wt[k] * 1.0e-3;
// kg/kmol -> kg/mol
41
specs[k].is_electron = (k == m_ie);
42
}
43
// CollisionModel tabulates composition-resolved transport/rate coefficients
44
// (e.g. mobility, collision frequency) over the electron-temperature grid
45
// [Te_min, Te_max] with Te_n points; spitzer toggles the Coulomb contribution.
46
CollisionModel
collision(specs, cfg.
Te_min
, cfg.
Te_max
, cfg.
Te_n
, cfg.
spitzer
);
47
48
// ReactorRHS is the physics core shared with PlasmaChannel1D: chemistry source
49
// terms (if reacting), Joule heating, and elastic/inelastic Tg<->Te exchange.
50
ReactorRHS::Config
rc;
51
rc.
reacting
= cfg.
reacting
;
52
rc.
collision
= std::move(collision);
53
m_rhs = std::make_unique<ReactorRHS>(m_sol, std::move(rc));
54
}
55
56
std::vector<std::string>
Plasma0DReactor::speciesNames
()
const
57
{
58
std::vector<std::string> names(m_rhs->nSpecies());
59
for
(std::size_t k = 0; k < names.size(); k++) names[k] = m_rhs->speciesName(k);
60
return
names;
61
}
62
63
void
Plasma0DReactor::rhs
(
double
Tg,
double
Te,
double
V,
const
double
* Y,
double
E,
64
double
mass,
double
p_ext,
double
polytropic_index,
65
double
* dydt)
const
66
{
67
// Constant-mass reactor: density is derived from the instantaneous volume rather
68
// than integrated directly (mirrors ConstantMassPlasmaReactorOde in Python).
69
const
double
rho = mass / V;
70
// dTg, dTe accumulate the RHS's energy-balance source terms [K/s]; lhsTg,
71
// lhsTe are the (heat-capacity-like) coefficients multiplying dTg/dt, dTe/dt
72
// on the LHS of the energy balance, so source terms below can be added as
73
// @f$ \text{source} / \text{lhs} @f$.
74
double
dTg = 0.0, dTe = 0.0, lhsTg = 1.0, lhsTe = 1.0;
75
// dY goes straight into dydt[3..]; rates() leaves thermo at (Tg,Te,Y,rho).
76
// &m_diag caches the power/Maxwellian-condition breakdown for diagnostics().
77
m_rhs->rates(Tg, Te, Y, rho, E, dTg, dTe, dydt + 3, lhsTg, lhsTe, &m_diag);
78
79
double
dV = 0.0;
80
if
(std::isfinite(polytropic_index) && polytropic_index > 0.0 && m_gap > 0.0) {
81
// Polytropic rarefaction (mirrors ConstantMassPlasmaReactorOde): the hot
82
// core's overpressure relaxes toward p_ext over the acoustic (rarefaction)
83
// timescale tau derived below.
84
auto
thermo = m_rhs->solution()->thermo();
85
const
double
P = thermo->pressure();
86
const
double
Xe = thermo->moleFraction(m_ie);
87
// Electron partial pressure [Pa], via the ideal-gas Dalton split
88
// @f$ p_e = X_e P @f$.
89
const
double
p_e = Xe * P;
90
// Clamp to avoid unphysical/singular values (e.g. at startup) feeding
91
// sqrt() below.
92
const
double
Tg_c = std::max(Tg, 200.0);
93
const
double
Te_c = std::max(Te, 200.0);
94
// Two-temperature mixture temperature (mole-fraction-weighted blend of Tg
95
// and Te), used as the effective temperature for the speed-of-sound
96
// estimate below:
97
// @f[
98
// \overline{T} = (1 - X_e) T_g + X_e T_e.
99
// @f]
100
const
double
Tmean = (1.0 - Xe) * Tg_c + Xe * Te_c;
101
const
double
cp = thermo->cp_mass();
102
const
double
cv = thermo->cv_mass();
103
// Fall back to diatomic-air @f$ \gamma @f$ if @f$ c_v \approx 0 @f$.
104
const
double
gamma = (cv > 0.0) ? cp / cv : 1.4;
105
const
double
M = thermo->meanMolecularWeight() * 1.0e-3;
// kg/mol
106
// Treat the plasma volume as a cylinder of fixed axial length m_gap to
107
// recover an effective radius r, then the ideal-gas speed of sound at
108
// @f$ \overline{T} @f$ and the acoustic (rarefaction) timescale tau over
109
// which the core relaxes toward p_ext:
110
// @f[
111
// r = \sqrt{\frac{V}{\text{m\_gap} \, \pi}}, \qquad
112
// c_\text{sound} = \sqrt{\frac{\gamma R \overline{T}}{M}}, \qquad
113
// \tau = \frac{r}{c_\text{sound}}.
114
// @f]
115
const
double
radius = std::sqrt(V / (m_gap *
units::pi
));
116
const
double
c_sound = std::sqrt(gamma *
units::R
* Tmean / M);
117
const
double
tau = radius / c_sound;
118
// Polytropic volume equation (mirrors ConstantMassPlasmaReactorOde): the
119
// pressure relaxes toward p_ext over tau, and the volume responds via the
120
// polytropic relation with index n:
121
// @f[
122
// \frac{dp}{dt} = -\frac{P - p_\text{ext}}{\tau}, \qquad
123
// \frac{dV}{dt} = -\frac{1}{n} \frac{V}{P} \frac{dp}{dt}.
124
// @f]
125
const
double
dp_dt = -(P - p_ext) / tau;
126
dV = -1.0 / polytropic_index * (V / P) * dp_dt;
127
// Pressure work removes energy from each population as the cell expands.
128
if
(std::isfinite(dV)) {
129
dTe -= (p_e * dV / V) / lhsTe;
130
dTg -= ((P - p_e) * dV / V) / lhsTg;
131
}
else
{
132
dV = 0.0;
133
}
134
}
135
136
dydt[0] = dTg;
137
dydt[1] = dTe;
138
dydt[2] = dV;
139
// dydt[3..] (dY) already written by rates().
140
}
141
142
}
// namespace rizer
Plasma0DReactor.h
PlasmaRates.h
ThermoPhase.h
rizer::CollisionModel
Composition-resolved electron-heavy momentum-transfer collision model.
Definition
CollisionModel.h:56
rizer::Plasma0DReactor::speciesNames
std::vector< std::string > speciesNames() const
Definition
Plasma0DReactor.cpp:56
rizer::Plasma0DReactor::rhs
void rhs(double Tg, double Te, double V, const double *Y, double E, double mass, double p_ext, double polytropic_index, double *dydt) const
Full 0D RHS.
Definition
Plasma0DReactor.cpp:63
rizer::Plasma0DReactor::Plasma0DReactor
Plasma0DReactor(const Config &cfg)
Construct from a mechanism/phase and collision-model configuration.
Definition
Plasma0DReactor.cpp:21
Cantera::newSolution
shared_ptr< Solution > newSolution(const string &infile, const string &name="", const string &transport="default", const vector< shared_ptr< Solution > > &adjacent={})
Cantera::npos
const size_t npos
rizer::units::R
constexpr double R
Ideal gas constant [J/(mol K)].
Definition
units.h:58
rizer::units::pi
constexpr double pi
pi (matches numpy's np.pi used in units.py).
Definition
units.h:51
rizer
Definition
CollisionModel.cpp:7
rizer::registerPlasmaRates
void registerPlasmaRates()
Register the custom plasma reaction rates with Cantera's ReactionRateFactory.
Definition
PlasmaRates.cpp:26
rizer::Plasma0DReactor::Config
Definition
Plasma0DReactor.h:34
rizer::Plasma0DReactor::Config::spitzer
bool spitzer
Use Spitzer (Coulomb) conductivity contribution when true.
Definition
Plasma0DReactor.h:48
rizer::Plasma0DReactor::Config::Te_n
std::size_t Te_n
Number of points in the tabulated Te grid [-].
Definition
Plasma0DReactor.h:46
rizer::Plasma0DReactor::Config::Te_max
double Te_max
Upper bound of the tabulated electron-temperature grid [K].
Definition
Plasma0DReactor.h:44
rizer::Plasma0DReactor::Config::reacting
bool reacting
If false, disables chemistry source terms in the RHS.
Definition
Plasma0DReactor.h:37
rizer::Plasma0DReactor::Config::specs
std::vector< CollisionModel::SpeciesSpec > specs
Per-species cross-section model (cross-section data / radius / ion Z).
Definition
Plasma0DReactor.h:40
rizer::Plasma0DReactor::Config::Te_min
double Te_min
Lower bound of the tabulated electron-temperature grid [K].
Definition
Plasma0DReactor.h:42
rizer::ReactorRHS::Config
Definition
ReactorRHS.h:58
rizer::ReactorRHS::Config::reacting
bool reacting
Include finite-rate chemistry source terms (true) or freeze composition (false) [-].
Definition
ReactorRHS.h:61
rizer::ReactorRHS::Config::collision
CollisionModel collision
Composition-resolved sigma/nu_E (preferred).
Definition
ReactorRHS.h:63
units.h
Physical constants and unit conversions, in SI by default.
rizer
cantera_ext
src
Plasma0DReactor.cpp
Generated by
1.17.0