rizer.cantera_ext.plasma_channel#
Transient 1D two-temperature reacting plasma channel (Cantera-based).
PlasmaChannel is the 1-D radial, transient counterpart of rizer’s 0-D
rizer.plasma.constant_mass_reactor.ConstantMassPlasmaReactorOde: it
solves finite-rate two-temperature plasma chemistry together with radial heat
conduction, and exposes the discharge-channel diameter expansion D(t) for
comparison with rizer’s engineering prediction
(rizer.hybrid.engineering_model.model.diffusion) and experiment.
The heavy solve lives in the compiled rizer.cantera_ext._plasma1d; this
wrapper builds the initial state, calls it, and post-processes the radial
temperature history into a channel radius.
Notes
The native-rate air_plasma_Laux2000 mechanism loads in C++; the Goutier CH4
mechanism has Python-only ExtensibleRate reactions and needs C++ ports for a
fully-kinetic CH4 run (see ARCHITECTURE.md). For a thermal (LTE-conduction)
CH4 expansion, run with reacting=False and an injected CH4 kappa(T).
Classes#
Transient radial two-temperature reacting plasma channel. |
Module Contents#
- class rizer.cantera_ext.plasma_channel.PlasmaChannel(mech: str, phase: str, R_max: float, rho: float, Y0: numpy.ndarray | list[float], grid: numpy.ndarray | list[float] | None = None, Tg_profile: tuple[numpy.ndarray, numpy.ndarray] | None = None, Te_profile: tuple[numpy.ndarray, numpy.ndarray] | None = None, Y0_profile: tuple[numpy.ndarray, numpy.ndarray] | None = None, T_amb: float = 300.0, kappa: tuple[numpy.ndarray, numpy.ndarray] | float | None = None, kappa_e: tuple[numpy.ndarray, numpy.ndarray] | float | None = None, D_species: float = 0.0, sigma: tuple[numpy.ndarray, numpy.ndarray] | float = 0.0, nu_E: float = 0.0, nu_m: float | tuple[numpy.ndarray, numpy.ndarray] = 0.0, mtcf: list[rizer.plasma.collision_frequency.MomentumTransferCollisionFrequencyModel] | None = None, Te_min: float = 300.0, Te_max: float = 100000.0, Te_n: int = 400, spitzer: bool = True, electric_field: float | tuple[numpy.ndarray, numpy.ndarray] = 0.0, reacting: bool = True, dt: float = 1e-08, n_steps: int = 100, record_every: int = 1, n_points: int = 81, integrator: str = 'newton', loglevel: int = 0, gap: float | None = None)#
Transient radial two-temperature reacting plasma channel.
Assumptions and domain of validity
This model is a 1-D radial, axisymmetric, constant-volume generalisation of rizer’s 0-D
ConstantMassPlasmaReactorOde. The state per node is only(Tg, Te, Y_k)— there is no flow. Read these before interpreting results:Fixed mass density
rho(constant volume). There is no continuity or momentum equation, sorhois a fixed parameter, not a state variable. Consequence: pressure is not held constant — a hot core at fixedrhosits at an elevated local pressure (a constant-volume artefact), and the recordedn_eis the model’s own value at that(T, rho)state. Valid when the channel evolves by conduction/diffusion + chemistry; not valid for pressure-driven (shock / Braginskii) gas-dynamic expansion, which would require a compressible flow solve.Prescribed electric field
E(t); no self-consistent field. Poisson is not solved and the plasma is treated quasi-neutral, so the dielectric-relaxation timescale never enters. Valid for a given/measured applied field; not valid for self-consistent sheath/streamer dynamics (use a drift-diffusion-Poisson solver for those).Two-temperature (
Te != Tg): separate electron and heavy-species energy equations coupled by elastic/inelastic exchange, assuming a Maxwellian EEDF atTe.Heat conduction: two-temperature Fourier — radial conduction for both
Tg(kappa(Tg)) andTe(kappa_e(Te)), each active only if its conductivity table is supplied.Species transport: Fickian with a single constant scalar
D_species. No thermal diffusion (Soret) or Dufour, not mixture-averaged / multicomponent (oneDfor every species), and no ambipolar diffusion for charged species (electrons and ions shareD, no field coupling). Species diffusion is frozen whenD_species == 0(the default). Species diffusion also feeds back into both energy equations: a compressibility term (from the two-temperature ideal-gas EOS) and an enthalpy-diffusion (species heat transport) term, each nonzero whenever a composition gradient coincides with species of different heat capacity – not just the mass-fraction equations (seeARCHITECTURE.md).Joule heating
sigma*E^2. Two mutually exclusive closures forsigma(and, for the electron energy equation, the elastic electron-heavy exchange frequency): (a)mtcf, a composition-resolved collision model evaluated live from the evolving composition every step (the same model the 0-DConstantMassPlasmaReactorOdeCppuses) – preferred, sincesigmathen tracks the reacting mixture instead of a frozen snapshot; or (b) the legacy closure:sigmafrom asigma(Te)table, or – ifnu_m > 0–sigma = n_e e^2/(m_e nu_m)from the localn_e, plus a separately-suppliednu_E. Passing both raisesValueError.Geometry/BC: cylindrical 1-D radial, axisymmetric;
r=0symmetry;r=R_maxDirichlet wall atT_amb(and ambient compositionY0for diffusion).Numerics (
integrator):"newton"is adaptive implicit Backward-Euler (CanteraSim1Ddamped-Newton; robust for gentle / near-equilibrium states)."bdf"is a stiff adaptive-order BDF integrator (Cantera CVODE over the method-of-lines RHS) for field-driven plasma chemistry that the Newton solver cannot converge. The stiff limit is the electron-energy equation (tiny electron heat capacity -> sub-nsTedynamics): start gently (Te=Tg) and use a modest field, as rizer’s 0D NRP reactor does. Both air and the CH4Goutier2025mechanism run this way.
- Parameters:
mech (
str) – Cantera mechanism file and phase name (aPlasmaPhasewithe-).phase (
str) – Cantera mechanism file and phase name (aPlasmaPhasewithe-).R_max (
float) – Outer radius of the computational domain [m] (ignored ifgridis given).rho (
float) – (Fixed) mass density [kg/m^3].Y0 (
array_like) – Ambient / wall mass fractions, and the initial composition where noY0_profileis supplied (length = number of species).grid (
array_likeorNone) – Explicit, increasing radial grid [m] (grid[0] == 0). Overridesn_points/R_max; installed directly (Cantera-flame style). If None, a uniformn_pointsgrid on[0, R_max]is built.Tg_profile (
tuple(array,array)orNone) –(r, T)initial radial temperature profiles [m, K]. If None, uniformT_amb.Te_profile (
tuple(array,array)orNone) –(r, T)initial radial temperature profiles [m, K]. If None, uniformT_amb.Y0_profile (
tuple(array,2d-array)orNone) –(r, Y)initial radial composition,Yshaped(len(r), nsp). If None, the uniformY0is used everywhere.T_amb (
float) – Wall/ambient temperature [K].kappa (
tuple(array,array)orfloatorNone) – Gas / electron thermal conductivity, as(T, value)tables or a constant [W/m/K]. None disables that conduction.kappa_e (
tuple(array,array)orfloatorNone) – Gas / electron thermal conductivity, as(T, value)tables or a constant [W/m/K]. None disables that conduction.D_species (
float) – Constant species mass diffusivity [m^2/s] (0 = frozen transport).sigma (
tuple(array,array)orfloat) – Electrical conductivitysigma(Te)[S/m] for Joule heating (legacy closure; mutually exclusive withmtcf).nu_E (
float) – Effective electron-heavy elastic energy-exchange frequency [1/s] (legacy closure; mutually exclusive withmtcf).nu_m (
floatortuple(array,array)) – Electron momentum-transfer frequency [1/s]; if > 0,sigma = n_e e^2/(m_e nu_m)from the localn_e(overrides thesigmatable). Legacy closure; mutually exclusive withmtcf.mtcf (
listofMomentumTransferCollisionFrequencyModelorNone) – Per-species momentum-transfer collision-frequency models (as built byrizer.misc.simulation.simulation.get_momentum_transfer_collision_frequencies_list()), one per species in mechanism order. When given,sigmaand the electron-heavy elastic exchange are evaluated live from the evolving composition every step via the same composition-resolved collision modelConstantMassPlasmaReactorOdeCppuses, instead of the frozensigma/nu_m/nu_Eclosure below. Mutually exclusive withsigma,nu_m, andnu_E: passing a non-default value of any of those together withmtcfraisesValueError.Te_min (
float,float,int) – Log-spaced electron-temperature grid [K],[K],[-] the collision model (mtcf) precomputes its per-species cross-section tables on. Only used whenmtcfis given.Te_max (
float,float,int) – Log-spaced electron-temperature grid [K],[K],[-] the collision model (mtcf) precomputes its per-species cross-section tables on. Only used whenmtcfis given.Te_n (
float,float,int) – Log-spaced electron-temperature grid [K],[K],[-] the collision model (mtcf) precomputes its per-species cross-section tables on. Only used whenmtcfis given.spitzer (
bool) – Apply the Spitzer e-e correction to the collision model. Only used whenmtcfis given.electric_field (
floatortuple(array,array)) – Constant fieldE[V/m], or an arbitrary schedule(t, E)[s, V/m] (linearly interpolated, e.g. a pulse) supplied from Python.reacting (
bool) – Include finite-rate chemistry.dt (
float,int,int) – Output cadence / initial step [s] (dt*n_steps= total time), number of output steps, recording cadence.n_steps (
float,int,int) – Output cadence / initial step [s] (dt*n_steps= total time), number of output steps, recording cadence.record_every (
float,int,int) – Output cadence / initial step [s] (dt*n_steps= total time), number of output steps, recording cadence.n_points (
int) – Radial grid points (ignored ifgridis given).integrator (
str) –"newton"(adaptive Backward-Euler) or"bdf"(stiff CVODE).
- T_amb#
- property t: numpy.ndarray#
Recorded times [s].
- property r: numpy.ndarray#
Radial grid [m].
- property species: list[str]#
Species names, in the mechanism order used by
mass_fractions().
- temperature_profiles() tuple[numpy.ndarray, numpy.ndarray]#
Return the recorded gas- and electron-temperature histories.
- Returns:
Tg (
numpy.ndarray) – Gas (heavy-species) temperature [K], shape(nframes, npts).Te (
numpy.ndarray) – Electron temperature [K], shape(nframes, npts).
- electron_density() numpy.ndarray#
Electron number density
n_e(r, t), shape(nframes, npts)[1/m^3].Computed inside the solver as
X_e * P / (k_B * Tmean)per node (the samen_eused in the electron energy balance), so it is the model’s own value rather than a post-hoc reconstruction.
- mass_fractions() numpy.ndarray#
Species mass fractions
Y_k(r, t), shape(nframes, npts, nsp)[-].
- field() numpy.ndarray#
Return the applied electric field
E(t)[V/m] at the recorded output times.Reconstructs the same field the C++ solver evaluated internally at every internal (sub-
dt) step: a constant, or linear interpolation of the(t, E)schedule supplied at construction (seeChannelOptions::Efield_t/Efield_vinPlasmaChannel1D.h).- Returns:
Field [V/m] at each recorded time in
t.- Return type:
- total_current() numpy.ndarray#
Total current
I(t)[A] through the channel cross-section.I = E(t) \int_0^R \sigma(r) 2\pi r\,dr.\sigmafollows the same fallback as the solver’s own Joule-heating term:\sigma = n_e e^2/(m_e \nu_m)(from the localn_e) whennu_m > 0or anu_m(Te)table is given; otherwise thesigma(Te)conductivity table supplied at construction (matchingReactorRHS::transport, so Joule heating configured purely viasigmais still diagnosable). Assumes the recorded radial profile is uniform along the inter-electrode gap.- Raises:
NotImplementedError – If the channel was built with
mtcf(the composition-resolved collision model): reconstructingsigma(r, t)after the fact would need the live collision-model evaluation at each recorded state, which isn’t exposed from Python yet – reconstructing it from a frozen table here would silently misrepresent the solve.
- joule_power(gap: float | None = None) numpy.ndarray#
Total Joule power dissipated in the channel cross-section.
P(t) = E(t) * gap * I(t) = U(t) * I(t)[W], i.e. the 1-D radial current profile fromtotal_current()extruded uniformly over the inter-electrode gap (the same constant-along-the-gap assumption astotal_current()).- Parameters:
gap (
floatorNone, optional) – Inter-electrode gap [m]. If None (default), uses thegappassed at construction.- Returns:
Joule power [W] at each recorded time in
t.- Return type:
- Raises:
ValueError – If no gap was supplied here or at construction.
- deposited_energy(gap: float | None = None) float#
Total deposited (Joule) energy over the run.
E_dep = \int_0^{t_{end}} E(t) * gap * I(t)\,dt[J], the time integral ofjoule_power()(trapezoidal rule over the recorded output times).
- channel_radius(method: str = 'half_max') numpy.ndarray#
Channel radius
R(t)[m] from the gas-temperature profile.- Parameters:
method (
{"half_max", "sigma_weighted"}) –half_max: radius whereTg - T_ambdrops to half its axis value.sigma_weighted:sqrt(<r^2>)weighted byTg - T_amb.
- Returns:
Channel radius [m] at each recorded time in
t.- Return type:
- channel_diameter(method: str = 'half_max') numpy.ndarray#
Channel diameter
D(t) = 2 R(t)[m].See
channel_radius()for themethodoptions; this is the quantity directly comparable to rizer’s engineering diffusion model (rizer.hybrid.engineering_model.model.diffusion) and experiment.- Parameters:
method (
{"half_max", "sigma_weighted"}) – Passed through tochannel_radius().- Returns:
Channel diameter [m] at each recorded time in
t.- Return type: