rizer.electrical_model.circuit.adapter#

Adapter making a stateful BaseCircuit circuit answer per-call queries.

Lets a stateful BaseCircuit (real ODE state: current, voltage, …) be used as a drop-in electric_circuit=-style argument for a reactor whose own stepping loop is driven by cantera.ReactorNet (so the reactor’s state cannot be stacked with the circuit’s from outside) – the same per-call interface TransmissionLineResistiveCircuit already answers. For a scipy.integrate.solve_ivp-driven reactor, prefer the exact, non-windowed StackedReactorCircuit instead.

Attributes#

Classes#

DrivenCircuitAdapter

Wrap a stateful circuit so it answers compute_plasma_voltage(t, R_p) -> float.

Functions#

check_window_span_compatible(→ None)

Raise if a reactor's own max_step would violate a DrivenCircuitAdapter window's causality bound.

Module Contents#

rizer.electrical_model.circuit.adapter.DEFAULT_R_P_RTOL = 0.001#
class rizer.electrical_model.circuit.adapter.DrivenCircuitAdapter(circuit: rizer.electrical_model.circuit.base_circuit.BaseCircuit, output: Callable[[float, numpy.ndarray, float], float], window_span: float, r_p_rtol: float = DEFAULT_R_P_RTOL)#

Wrap a stateful circuit so it answers compute_plasma_voltage(t, R_p) -> float.

Exposes that exact method name – not just any callable – so an instance is a literal drop-in for the electric_circuit= argument of Isomass2TVolumeReactor (and its C++-backed counterpart, and solve_split_circuit()), all of which call self.electric_circuit.compute_plasma_voltage(t, R_p=...) verbatim, the same as they would with an TransmissionLineResistiveCircuit. The output callable does not have to compute a voltage specifically – it can map to any scalar the caller needs (current, for a different kind of reactor coupling) – but the method name matches what these reactors actually call, regardless.

Internally, re-solves the circuit with dense_output=True over a window (solve_window()) whenever the queried t falls outside the currently-cached window, using R_p frozen from the call that opened the window. The reactor itself needs zero changes to its own stepping mechanism, since the adapter only interacts with it through this same call signature.

The cached window is also re-solved when R_p drifts beyond r_p_rtol from the value it was frozen at, even if t is still inside the window – otherwise every Newton-corrector iteration within one solver step (all at the same trial t, slightly different state) would reuse a stale current, making the outer solver’s own right-hand side artificially insensitive to its state through the R_p -> output feedback path within a step.

Caller responsibility: cap the reactor’s own maximum step size (e.g. net.max_time_step for a Cantera ReactorNet) to something conservative relative to window_span and to the circuit’s own timescale, so the reactor can never advance past an open window before this adapter re-syncs.

Parameters:
  • circuit (BaseCircuit) – Stateful circuit to drive externally.

  • output (Callable[[float, numpy.ndarray, float], float]) – Maps the queried time, the circuit’s window-local state, and the frozen R_p to the scalar the caller needs (plasma voltage, or plasma current).

  • window_span (float) – Length of each re-solved window, in seconds. Public: callers must cap their own solver’s max step size relative to this.

  • r_p_rtol (float, optional) – Relative tolerance on R_p drift within a window before it is forced to re-solve, even if t is still inside the cached window. Default 1e-3.

circuit#
window_span#
compute_plasma_voltage(t: float, R_p: float) → float#

Evaluate the wrapped circuit’s output at t, for the given R_p.

Named compute_plasma_voltage to match TransmissionLineResistiveCircuit’s own method of the same name exactly, despite the output callable being free to compute something other than a voltage – see the class docstring.

Parameters:
  • t (float) – Time, in seconds.

  • R_p (float) – Plasma resistance at time t, in Ohm.

Returns:

The scalar produced by output (plasma voltage or plasma current).

Return type:

float

rizer.electrical_model.circuit.adapter.check_window_span_compatible(max_step: float, window_span: float, context: str) → None#

Raise if a reactor’s own max_step would violate a DrivenCircuitAdapter window’s causality bound.

Shared by every caller that builds a stateful, DrivenCircuitAdapter-wrapped circuit and needs to check it against a reactor/solver’s own step size before integration starts, rather than letting a misconfigured max_step surface as a confusing RuntimeError mid-integration (e.g. check_circuit_solver_compatibility() and wire_electrical_circuit()).

Parameters:
  • max_step (float) – The reactor/solver’s own maximum step size [s].

  • window_span (float) – The stateful circuit’s own re-solve window [s].

  • context (str) – Free text naming what is being checked, appended to the error message (e.g. "source.type='c_shunt'").

Raises:

ValueError – If max_step exceeds half window_span – each window must only ever need already-finalized wave-buffer history (method-of-steps DDE requirement), the same bound TransmissionLineRCLoadCircuit and its siblings impose on their own window_span argument.