rizer.adaptive_models#

Adaptive-model framework: interchangeable stages, self-switching solve.

The machinery behind rizer’s adaptive composite reactors — the BasePhysicalModel stage contract, the canonical PlasmaState, conservation-checked transition operators, the goal-oriented ModelSelector, and the generic AdaptiveCompositeReactor solve loop — together with the concrete reactor built on it: PulsedPlasmaReactor (one NRP pulse: isochoric deposition -> isentropic expansion -> isobaric cooling).

Design: rizer/adaptive_models/ARCHITECTURE.md; prior art: SOTA.md.

Submodules#

Classes#

AdaptiveCompositeReactor

Base class of every adaptive (self-switching) composite reactor.

AdaptiveResult

Unified trajectory of an adaptive composite solve.

PulsedPlasmaReactor

A single-pulse composite reactor with self-switching fidelity.

FidelitySignature

What a stage solver actually evolves.

PlasmaState

Canonical, model-agnostic plasma state.

Package Contents#

class rizer.adaptive_models.AdaptiveCompositeReactor(plasma: cantera.Solution, collision_freq: rizer.transport.mixture_law.MixtureCollisionFrequencies, stages: list[rizer.adaptive_models.models_list.BasePhysicalModel], rules: list[rizer.adaptive_models.selector.SwitchRule], qoi: rizer.adaptive_models.contract.QoISet = ('T', 'P', 'deposited_energy'), tol: float = 0.01, allowed_models: set[str] | None = None)#

Base class of every adaptive (self-switching) composite reactor.

Subclasses build the ladder and call this constructor; users interact with the concrete reactor’s from_config and solve() only.

Parameters:
  • plasma (cantera.Solution) – The shared Cantera plasma Solution every stage reads and writes.

  • collision_freq (MixtureCollisionFrequencies) – Collision-frequency wrapper around plasma (the modeling-error estimator’s elastic-exchange and conductivity closures).

  • stages (list of BasePhysicalModel) – The ladder’s stage solvers. stages[0] seeds the trajectory; which model is active thereafter is decided by live conditions, not position (see SwitchRule/ ModelSelector).

  • rules (list of SwitchRule) – All ladder edges (unordered; several may share the same outgoing — whichever fires wins).

  • qoi (tuple of str) – Quantities of interest driving the goal-oriented switching.

  • tol (float) – The single accuracy knob [-].

  • allowed_models (set of str, optional) – Restrict the graph to just these stage names (and the edges between them) for this run — for testing a single model in isolation, or comparing runs across model combinations. None (default): every stage/edge the subclass registered is available. The seed stage (stages[0]) must itself be in allowed_models when given. A stage left with no outgoing edges after filtering is a valid configuration (it simply never switches away), not an error.

plasma#
qoi = ('T', 'P', 'deposited_energy')#
tol#
final_state() → rizer.adaptive_models.state.PlasmaState#

Canonical state of whichever stage is active when solve returns.

solve(t_end: float) → AdaptiveResult#

March the ladder to t_end and return the unified trajectory.

The mutation decision (which edge, blend weight, hand-off/rebound bookkeeping) is entirely internal to advance() — this loop only advances the active stage and reacts to the HandoffStep it returns.

class rizer.adaptive_models.AdaptiveResult#

Bases: rizer.models.nrp.engineering_model.base.TimeSeriesState

Unified trajectory of an adaptive composite solve.

Extends TimeSeriesState (t, T, P, plot) with the plasma fields and the model provenance. T is the unified temperature (Tg; equal to the single temperature after any 2-T stage).

Tg: numpy.ndarray#
Te: numpy.ndarray#
V: numpy.ndarray#
R: numpy.ndarray#
E: numpy.ndarray#
Y: numpy.ndarray#
deposited_energy: numpy.ndarray#
species_names: list[str] = []#
stage_trace: list[str] = []#
active_model_log: list[str] = []#
switch_times: list[float] = []#
plot(show: bool = True)#

Plot T/Te and P vs time with the model switches annotated.

class rizer.adaptive_models.PulsedPlasmaReactor(params: dict[str, Any], qoi: rizer.adaptive_models.contract.QoISet = ('T', 'P', 'deposited_energy'), tol: float = 0.01, first_stage: str = 'isochoric_plasma_0d2t', lte_ionization_fraction: float = 0.01, **kwargs: Any)#

Bases: rizer.adaptive_models.composite.AdaptiveCompositeReactor

A single-pulse composite reactor with self-switching fidelity.

Construct via from_config(), call solve(t_end), read the unified AdaptiveResult.

Parameters:
  • params (dict) – Fully-assembled nrp_driver-layout parameters (use from_config() instead of building this by hand). plasma must carry ambient_temperature [K] (gas surrounding the kernel, the expansion tier’s T_amb) and wall_temperature [K, or None for adiabatic] (sink of the isobaric tier’s conductive loss): user-file quantities, never defaulted.

  • qoi (tuple of str) – Quantities of interest driving the goal-oriented switching.

  • tol (float) – The single accuracy knob [-].

  • first_stage (str) – Which deposition-tier model the trajectory starts in: "isochoric_plasma_0d2t" (2-T finite-rate, default) or "isochoric_lte" (equilibrium) — both remain available and connected by the thermalization edge regardless of this choice, so the ladder may still hand off between them based on live conditions — or "isochoric_eos" (chemistry-free), which opts out of the 2-T/LTE pair entirely (no thermalization edge exists for it).

  • lte_ionization_fraction (float) – Ionization fraction n_e / N above which the column counts as thermalized, arming the 2-T -> LTE hand-off (default 1e-2). A fraction, not an absolute density, so the criterion does not depend on the kernel’s pre-heating or dissociation. The limit of the regime is the fully ionized thermal spark of Minesi et al. 2020; the equilibration criterion is investigated by Maillard et al. Not used when first_stage="isochoric_eos".

  • allowed_models – See AdaptiveCompositeReactor.

Examples

lte_ionization_fraction#
classmethod from_config(config: str | pathlib.Path = 'nrp.yaml', mechanism: str = 'Goutier2025/CH4_to_C2H2', qoi: rizer.adaptive_models.contract.QoISet = ('T', 'P', 'deposited_energy'), tol: float = 0.01, first_stage: str = 'isochoric_plasma_0d2t', overrides: dict[str, Any] | None = None, **kwargs: Any) → PulsedPlasmaReactor#

Build the reactor from a YAML configuration.

Two layouts are accepted:

  • a circuit config (rizer/configs/nrp.yaml layout: generator / cable / circuit blocks plus an environment block with ambient_temperature and wall_temperature) — the plasma and solver sections come from the built-in CH4 validation defaults;

  • a full run-script config (sections plasma, electric_circuit, simulation; plasma must carry ambient_temperature and wall_temperature) — used verbatim.

Parameters:
  • config (str or pathlib.Path) – Config file; bare names resolve against rizer/configs.

  • mechanism (str) – Mechanism reference (.yaml appended when missing); resolved under data/mechanisms.

  • qoi – See PulsedPlasmaReactor.

  • tol – See PulsedPlasmaReactor.

  • first_stage – See PulsedPlasmaReactor.

  • overrides (dict, optional) – Deep-merged into the assembled parameter dictionary (e.g. {"plasma": {"initial_conditions": {"gap": 1e-3}}}).

  • **kwargs – Forwarded to the constructor (lte_ionization_fraction, allowed_models, …).

static params_from_config(config: str | pathlib.Path = 'nrp.yaml', mechanism: str = 'Goutier2025/CH4_to_C2H2', overrides: dict[str, Any] | None = None) → dict[str, Any]#

Assemble the nrp_driver-layout parameter dictionary.

class rizer.adaptive_models.FidelitySignature#

What a stage solver actually evolves.

Parameters:
  • dims (int) – Spatial dimensionality (0 for the current ladder).

  • n_temperatures (int) – Number of temperatures evolved (2 = Tg + Te, 1 = T).

  • chemistry (bool) – Whether finite-rate chemistry is evolved.

  • eedf (str) – Electron energy distribution closure: "maxwell", "druyvesteyn" or "boltzmann".

  • process (str) – Thermodynamic process regime: one of PROCESSES.

dims: int#
n_temperatures: int#
chemistry: bool#
eedf: str = 'maxwell'#
process: str = 'isochoric'#
class rizer.adaptive_models.PlasmaState#

Canonical, model-agnostic plasma state.

All quantities are SI. mass and gap ride along so every stage can reconstruct density and volume consistently across seams (the constant-mass invariant of the 0-D ladder).

Parameters:
  • t (float) – Absolute time [s].

  • Y (numpy.ndarray) – Species mass fractions, ordered by the plasma-phase species list of mechanism.

  • mechanism (str) – Mechanism file the Y ordering refers to.

  • Tg (float) – Heavy-species, electron and vibrational temperatures [K]. A 1-T model keeps Te == Tv == Tg.

  • Te (float) – Heavy-species, electron and vibrational temperatures [K]. A 1-T model keeps Te == Tv == Tg.

  • Tv (float) – Heavy-species, electron and vibrational temperatures [K]. A 1-T model keeps Te == Tv == Tg.

  • rho (float) – Mass density [kg/m^3].

  • V (float) – Plasma volume [m^3].

  • P (float) – Pressure [Pa].

  • R (float) – Cylindrical channel radius [m].

  • E (float) – Applied electric field [V/m].

  • mass (float) – Total plasma mass [kg] (constant across the ladder).

  • gap (float) – Inter-electrode gap [m] (constant).

  • eedf (str) – Active EEDF closure flag ("maxwell" | "druyvesteyn" | "boltzmann").

  • qoi_accum (dict) – Running quantity-of-interest accumulators, e.g. {"deposited_energy": <J>} (extensive).

Examples

>>> import numpy as np
>>> s = PlasmaState(
...     t=0.0,
...     Y=np.array([0.9, 0.1]),
...     mechanism="CH4_to_C2H2.yaml",
...     Tg=300.0,
...     Te=300.0,
...     rho=1.2,
...     V=1.0e-9,
...     P=101325.0,
...     R=5.0e-4,
...     mass=1.2e-9,
...     gap=3.0e-3,
... )
>>> s.Tv  # not assigned by the caller -- NaN until a stage sets it
nan
>>> s.deposited_energy  # not tracked yet
0.0
t: float#
Y: numpy.ndarray#
mechanism: str#
Tg: float#
Te: float#
rho: float#
V: float#
P: float#
R: float#
mass: float#
gap: float#
Tv: float#
E: float = 0.0#
eedf: str = 'maxwell'#
qoi_accum: dict[str, float]#
copy(**changes: Any) → PlasmaState#

Return a copy with changes applied (Y deep-copied).

property deposited_energy: float#

Accumulated deposited energy [J] (0 when not tracked yet).