bloc.reactors.torch_mixing#

Torch instantaneous-heating reactor models and stage network.

Classes#

TorchInstantaneousHeatingNet

ReactorNet subclass implementing torch adiabatic integration.

TorchInstantaneousHeating

Torch physics engine with instantaneous enthalpy jump (plasma / simplified).

PlasmaTorchInstantaneousHeating

Industrial Plasma Torch model — instantaneous-heating variant.

ContinuousMixingReactor

Industrial Torch Mixing Reactor (TMR) / multi-inlet well-mixed vessel.

InstantaneousMixingNet

ReactorNet subclass for instantaneous-mix + closed-τ chemistry.

InstantaneousMixing

Engine: instantaneous HP mix of two inlet streams + closed-τ chemistry.

InstantaneousMixingReactor

Industrial model: instantaneous mix + closed chemical residence time.

Functions#

compute_torch_sei_mj_kg(electric_power_kW, mdot_kg_s)

Specific Energy Input [MJ/kg] = electrical input per kg of feed.

compute_torch_seo_mj_kg(effective_power_kW, mdot_kg_s)

Specific Energy Output [MJ/kg] = thermal power to gas per kg of feed.

is_torch_reactor_kind(kind)

Return True when kind is a registered STONE kind for any torch.

Module Contents#

bloc.reactors.torch_mixing.compute_torch_sei_mj_kg(electric_power_kW, mdot_kg_s)#

Specific Energy Input [MJ/kg] = electrical input per kg of feed.

SEI = electric_power_kW·1e3 / mdot / 1e6. Returns None when mdot_kg_s is not positive.

bloc.reactors.torch_mixing.compute_torch_seo_mj_kg(effective_power_kW, mdot_kg_s)#

Specific Energy Output [MJ/kg] = thermal power to gas per kg of feed.

SEO = effective_power_kW·1e3 / mdot / 1e6 where effective_power_kW = electric_power_kW × torch_eff × gen_eff. Matches the SEO_torch KPI in bloc.reporting.spring_kpi. Returns None when mdot_kg_s is not positive.

class bloc.reactors.torch_mixing.TorchInstantaneousHeatingNet(reactors, meta=None)#

Bases: cantera.ReactorNet

ReactorNet subclass implementing torch adiabatic integration.

Mirrors the PFRHomogeneousShellNet pattern: overrides advance() so the torch stage runs the same physics as the legacy simulation_non_isothermal_reactors path — instantaneous enthalpy addition followed by adiabatic kinetics for t_res_s.

Parameters:
  • reactors – List of reactors for this stage. Must contain exactly one TorchInstantaneousHeating.

  • meta (dict, optional) – Parameters injected by _build_torch_instantaneous() and enriched by _post_build_design_volumes(): effective_power_kW, mass_flow_rate, t_res_s, mechanism.

role: ClassVar[str] = 'torch'#
advance_to_steady_state()#

Validate that precomputed torch outlet data is available.

This stage does not integrate dynamics here; the outlet profile is precomputed in _post_build_design_volumes().

solve_steady()#

Delegate steady solve to advance_to_steady_state().

Base ReactorNet would run on an empty reactor list and raise.

advance(time)#

Validate and expose the precomputed torch outlet.

_post_build_design_volumes() pre-computes a torch outlet profile and stores _states before this TorchInstantaneousHeatingNet is instantiated. Downstream extraction reads torch.phase after solve_adiabatic() writeback.

Parameters:

time – Nominal advance time [s], unused and kept for API compatibility.

property states: cantera.SolutionArray | None#

Adiabatic post-enthalpy profile (satisfies CustomStageNetwork).

property scalars: Dict[str, Any]#

Torch build parameters and outlet-state physics quantities.

class bloc.reactors.torch_mixing.TorchInstantaneousHeating(gas, *args, **kwargs)#

Bases: cantera.IdealGasConstPressureMoleReactor

Torch physics engine with instantaneous enthalpy jump (plasma / simplified).

Boulder’s build_sub_network detects NETWORK_CLASS and instantiates TorchInstantaneousHeatingNet for the torch stage. That class uses the same physics as the legacy simulation_non_isothermal_reactors path: instantaneous enthalpy addition (gas.HP += Q/mdot) followed by adiabatic kinetics for t_res_s.

_meta#

Torch parameters populated by _build_torch_instantaneous() and enriched by _post_build_design_volumes().

Type:

dict

_states#

Residence-time profile written by solve_adiabatic() (extra t [s]).

Type:

ct.SolutionArray or None

NETWORK_CLASS: ClassVar[type | None]#
property SEI_MJ_kg: float | None#

Specific Energy Input [MJ/kg] from _meta (electrical input / feed).

Available on every torch once _post_build_design_volumes() has populated electric_power_kW and mass_flow_rate on _meta.

property SEO_MJ_kg: float | None#

Specific Energy Output [MJ/kg] from _meta (thermal power to gas / feed).

solve_adiabatic(mdot, power_kW, t_res_s, verbose=True)#

Solve adiabatic kinetics using this reactor’s current inlet state.

Adds torch power as an enthalpy jump and integrates one adiabatic pass for t_res_s using a fresh type(self)(gas, clone=False) carrier.

class bloc.reactors.torch_mixing.PlasmaTorchInstantaneousHeating(gas, *args, **kwargs)#

Bases: TorchInstantaneousHeating

Industrial Plasma Torch model — instantaneous-heating variant.

Instantaneous enthalpy jump (plasma power input at eta * P_torch) followed by adiabatic constant-pressure kinetics for t_res_s (see TorchInstantaneousHeating).

STONE kind: PlasmaTorchInstantaneousHeating.

The InstantaneousHeating suffix distinguishes this model from future plasma-torch implementations that may use a different heating model (e.g., arc-discharge, spatially-resolved, or multi-temperature).

Use this kind for all plasma torch stages where the heating is quasi-instantaneous compared to the chemical relaxation time.

See also

TorchInstantaneousHeating

underlying physics class.

NETWORK_CLASS: ClassVar[type | None] = None#
property SEI_MJ_kg: float | None#

Specific Energy Input [MJ/kg] from _meta (electrical input / feed).

Available on every torch once _post_build_design_volumes() has populated electric_power_kW and mass_flow_rate on _meta.

property SEO_MJ_kg: float | None#

Specific Energy Output [MJ/kg] from _meta (thermal power to gas / feed).

solve_adiabatic(mdot, power_kW, t_res_s, verbose=True)#

Solve adiabatic kinetics using this reactor’s current inlet state.

Adds torch power as an enthalpy jump and integrates one adiabatic pass for t_res_s using a fresh type(self)(gas, clone=False) carrier.

bloc.reactors.torch_mixing.is_torch_reactor_kind(kind)#

Return True when kind is a registered STONE kind for any torch.

“Any torch” means TorchInstantaneousHeating or a subclass — the base engine, PlasmaTorchInstantaneousHeating, and any supplier catalog model built on it (e.g. PBR100PlasmaTorch). Resolved via Boulder’s schema registry (reactor_class passed to register_reactor_builder), the same mechanism boulder.schema_registry.is_const_pressure_kind uses — so a new torch subclass is recognized automatically; no hardcoded kind-name list to maintain.

class bloc.reactors.torch_mixing.ContinuousMixingReactor(gas, *args, **kwargs)#

Bases: bloc.reactors.stirred.PSR

Industrial Torch Mixing Reactor (TMR) / multi-inlet well-mixed vessel.

A perfectly stirred reactor (see PSR) used to model the turbulent mixing of two or more streams at the outlet of a plasma torch.

STONE kind: ContinuousMixingReactor. Node id in SPRING YAML: tmr (the TMR in SPRING A3/A4).

Use this kind for any well-mixed stage where axial gradients are negligible. Assume Da_mix ≫ 1: mixing inside the vessel is faster than chemistry so the CSTR approximation holds.

Network topology#

Stage YAML: OPEN — multi-inlet MFCs, outlet PC/MFC; solved with ReactorNet and advance_to_steady_state (default).

Inner physics: OPEN CSTR. t_res_s sizes volume via Bloc post-build (_post_build_design_volumes(), V = τ·ṁ/ρ); it is the design residence time, not the stage advance_time.

See also

PSR

underlying numerical engine.

InstantaneousMixingReactor

closed-parcel alternative when inlet streams are pre-mixed algebraically before chemistry.

NETWORK_CLASS = None#
before_update_state(y)#

Inject a pending initial state into CVODE’s y before the first eval.

Cantera’s Reactor::initialize() restores m_state (the state snapshot taken at construction time) via a direct C++ call that bypasses all Python delegates. The only reliable interception point is here: CVODE calls updateState(y) just before its first eval, and y is writable.

If _pending_init is set, this method overwrites y with values derived from the HP-corrected gas state and clears the flag. All subsequent updateState calls (driven by CVODE’s own stepping) are unaffected.

class bloc.reactors.torch_mixing.InstantaneousMixingNet(reactors, meta=None)#

Bases: cantera.ReactorNet

ReactorNet subclass for instantaneous-mix + closed-τ chemistry.

Mirrors TorchInstantaneousHeatingNet: the stage network holds no live ODE reactors. advance() only validates that _post_build_design_volumes() has pre-computed the outlet profile.

Parameters:
  • reactors – Stage reactor list. Must contain exactly one InstantaneousMixing instance.

  • meta (dict, optional) – Parameters from the STONE builder, enriched by _post_build_design_volumes(): t_res_s, mass_flow_rate.

role: ClassVar[str] = 'PSR'#
advance_to_steady_state()#

Validate precomputed outlet and delegate.

solve_steady()#

Delegate steady solve to advance_to_steady_state().

advance(time)#

Validate precomputed outlet profile from post-build.

Parameters:

time – Nominal advance time [s]; unused, kept for API compatibility.

property states: cantera.SolutionArray | None#

Closed-τ residence-time profile (satisfies CustomStageNetwork).

property scalars: Dict[str, Any]#

Build parameters and outlet-state scalars.

class bloc.reactors.torch_mixing.InstantaneousMixing(gas, *args, **kwargs)#

Bases: bloc.reactors.stirred.PSR

Engine: instantaneous HP mix of two inlet streams + closed-τ chemistry.

Step 1 — inlet streams are combined with constant-HP algebraic mixing (mix_two_streams()), reproducing the Da_mix 1 assumption (turbulent mixing much faster than chemistry).

Step 2 — a closed constant-pressure parcel integrates the ODE from t = 0 to t = t_res_s with no inlet/outlet mass exchange.

This formalises the legacy pattern:

gas_mixed = mix_two_streams(gas_1, qm_1, gas_2, qm_2)
PSR_simu = solve_adiabatic_reactor(qm_total, 0, t_res_s, ...)
_states#

Residence-time profile recorded by solve_premixed().

Type:

ct.SolutionArray or None

NETWORK_CLASS: ClassVar[type | None] = None#
solve_premixed(gas_1, qm_1, gas_2, qm_2, t_res_s, *, verbose=True)#

HP-mix two inlet streams then integrate closed chemistry for t_res_s.

Parameters:
  • gas_1 – Cantera Solution objects for the two inlet streams (same or different mechanisms; both must be on the stage mechanism before calling — species mapping is the caller’s responsibility).

  • gas_2 – Cantera Solution objects for the two inlet streams (same or different mechanisms; both must be on the stage mechanism before calling — species mapping is the caller’s responsibility).

  • qm_1 – Mass flow rates [kg/s] of each stream.

  • qm_2 – Mass flow rates [kg/s] of each stream.

  • t_res_s – Chemical residence time [s]; CVODE integrates 0 → t_res_s on a closed parcel (no MFC flux during integration).

  • verbose – Print outlet state summary.

Returns:

  • dict with keys ````”gas”```` (Solution) and :py:class:``”states”:py:class:``

  • (:class:`~cantera.SolutionArray with extra column t [s]).`

before_update_state(y)#

Inject a pending initial state into CVODE’s y before the first eval.

Cantera’s Reactor::initialize() restores m_state (the state snapshot taken at construction time) via a direct C++ call that bypasses all Python delegates. The only reliable interception point is here: CVODE calls updateState(y) just before its first eval, and y is writable.

If _pending_init is set, this method overwrites y with values derived from the HP-corrected gas state and clears the flag. All subsequent updateState calls (driven by CVODE’s own stepping) are unaffected.

class bloc.reactors.torch_mixing.InstantaneousMixingReactor(gas, *args, **kwargs)#

Bases: InstantaneousMixing

Industrial model: instantaneous mix + closed chemical residence time.

Two inlet streams (e.g. torch primary + secondary injection) are combined with constant-HP algebraic mixing (mix_two_streams()), then chemistry runs for t_res_s in a closed well-mixed parcel.

STONE kind: InstantaneousMixingReactor.

Use when Da_mix ≫ 1 (turbulent mixing time ≪ chemical timescale) and the workflow is a one-shot feedforward chain (not a continuously-fed vessel). For a continuously-fed open CSTR, use ContinuousMixingReactor instead.

Network topology#

Stage YAML: OPEN — two inlet MFCs (source reservoirs or upstream reactor outlets), outlet MFC/PressureController for downstream handoff.

Inner physics: CLOSED parcel. _post_build_design_volumes() gathers both inlet states, calls solve_premixed(), and writes back to reactor.phase + syncState(). No live ODE in the stage ReactorNet.

See also

ContinuousMixingReactor

open CSTR alternative (continuous feed/discharge).

mix_two_streams

algebraic HP mixer used in step 1.

NETWORK_CLASS: ClassVar[type | None] = None#
solve_premixed(gas_1, qm_1, gas_2, qm_2, t_res_s, *, verbose=True)#

HP-mix two inlet streams then integrate closed chemistry for t_res_s.

Parameters:
  • gas_1 – Cantera Solution objects for the two inlet streams (same or different mechanisms; both must be on the stage mechanism before calling — species mapping is the caller’s responsibility).

  • gas_2 – Cantera Solution objects for the two inlet streams (same or different mechanisms; both must be on the stage mechanism before calling — species mapping is the caller’s responsibility).

  • qm_1 – Mass flow rates [kg/s] of each stream.

  • qm_2 – Mass flow rates [kg/s] of each stream.

  • t_res_s – Chemical residence time [s]; CVODE integrates 0 → t_res_s on a closed parcel (no MFC flux during integration).

  • verbose – Print outlet state summary.

Returns:

  • dict with keys ````”gas”```` (Solution) and :py:class:``”states”:py:class:``

  • (:class:`~cantera.SolutionArray with extra column t [s]).`

before_update_state(y)#

Inject a pending initial state into CVODE’s y before the first eval.

Cantera’s Reactor::initialize() restores m_state (the state snapshot taken at construction time) via a direct C++ call that bypasses all Python delegates. The only reliable interception point is here: CVODE calls updateState(y) just before its first eval, and y is writable.

If _pending_init is set, this method overwrites y with values derived from the HP-corrected gas state and clears the flag. All subsequent updateState calls (driven by CVODE’s own stepping) are unaffected.