Reactor Types#

Bloc organises its reactor implementations into two distinct layers:

  • Numerical engines — base classes that implement the ODE physics and spatial march algorithms for a given reactor paradigm (PFR, PSR, Tube Furnace).

  • Industrial models — concrete subclasses that inherit from engines and add domain-specific geometry, heat-transfer assumptions, and KPI extraction.

This page describes the physics of each class, explains when to use which model, documents the rename from legacy Design* names, and justifies why Cantera’s built-in FlowReactor is not used in the PFR engine.


Architecture overview#

Cantera ExtensibleIdealGasConstPressureMoleReactor
    │
    ├── PSR                               ← engine: well-mixed open CSTR
    │       ├── ContinuousMixingReactor             ← industrial model: TMR / multi-inlet vessel
    │       └── InstantaneousMixing       ← engine: 0-D HP mix + closed-τ chemistry
    │               └── InstantaneousMixingReactor  ← industrial model: 0-D+C variant
    │
    └── PFR                               ← engine: Lagrangian parcel base
            ├── PFRWallProfile            ← engine: prescribed T_wall profile
            │       └── TubeFurnace       ← industrial model: tube furnace
            │
            ├── PFRHomogeneousShell       ← engine: homogeneous-shell radial loss + FBS
            │       └── RefractoryReactor ← industrial model: CGR / insulated vessel
            │
            ├── PFRThinShell              ← engine: thin-shell local-T radial loss
            │       └── QuartzTubeReactor ← industrial model: quartz-tube / lab reactor
            │
            └── PFRGasTemperatureProfile  ← engine + STONE kind: imposed gas T(x)
                                            (Dirichlet on the gas, energy OFF)

TorchInstantaneousHeating                 ← engine: instantaneous enthalpy jump (not a PFR)
            └── PlasmaTorchInstantaneousHeating  ← industrial model: plasma torch

Why not Cantera’s FlowReactor?#

Cantera provides a FlowReactor that is integrated as a 1-D PFR. Bloc cannot use it for three reasons:

  1. Spatial DAE, not a time-ODE. FlowReactor is discretised axially: each spatial step is a time step advancing along z. ReactorNet integrates it as a differential–algebraic system over axial distance, not time. Mixing a FlowReactor with time-dependent ODE reactors (PSR, IdealGasReactor) in one ReactorNet is not supported.

  2. Adiabatic and frictionless. The built-in FlowReactor carries no wall heat-transfer mechanism. Supplying wall loss requires after_eval hooks or custom wall objects — at which point the simplicity advantage disappears.

  3. No steady-state coupling. A Bloc SPRING network requires a PSR (torch mixing zone) to feed a PFR (growth reactor) in a single staged solve. The FlowReactor alone in its own spatial ReactorNet cannot share state with the upstream PSR at advance-time.

Bloc therefore implements PFRs as closed Lagrangian parcel marches: a single ExtensibleIdealGasConstPressureMoleReactor is advanced in time along the tube axis. At each checkpoint the reactor state equals the state of a fluid parcel that has spent t = z / u(z) seconds in the tube. Wall heat transfer is added through Cantera’s after_eval hook or ct.Wall objects — both supported in time-ODE networks.


Numerical engines#

PFR — Plug Flow Reactor (base)#

Physics: Closed Lagrangian parcel at constant pressure. A single fluid parcel marches from z = 0 to z = L along the tube axis. At each step the ODE

dT/dt = Q_wall / (m_parcel * cp)
dn_k/dt = V_parcel * omega_k   (molar species production)

is integrated by Cantera’s CVODE solver at constant pressure. No mass enters or leaves during the march: dm/dt = 0.

Common invariants:

  • ExtensibleIdealGasConstPressureMoleReactor family (constant pressure, mole-based state).

  • Geometry stored in _meta (length, diameter, mass_flow_rate).

  • _pending_init / before_update_state pattern for injecting initial conditions without constructing a new reactor each step.

Subclasses add heat-transfer physics. All share PFRNetwork as driver.


PFRWallProfile — Prescribed Wall Temperature Profile#

Physics: The wall temperature varies along the tube axis according to a user-supplied profile (e.g., the plateau/ramp profile of an electric tube furnace). Heat transfer to the fluid parcel has two components evaluated at each after_eval call:

  • Forced convection: Q_conv = h * A_lateral * (T_wall(z) - T_gas), where h is computed from the Nusselt correlation for internal pipe flow.

  • Grey-gas radiation: Q_rad = kappa_grey * 4 * sigma * (T_wall(z)⁴ - T_gas⁴) * V_parcel.

SOLVER_MODE = "adaptive" — the network uses net.step() (adaptive step) to resolve the steep temperature gradients near the ramp boundaries.

When to use: Electrically heated tube furnaces with a known, spatially varying wall temperature (plateau + cold legs + ramps). Industrial model: TubeFurnace.


PFRHomogeneousShell — Homogeneous-Shell Radial Heat Loss#

Physics: Thick-walled, heavily insulated vessel where axial wall conduction smears temperature gradients along the shell. The total wall heat loss Φ [kW] is evaluated from the spatial-mean gas temperature T_mean using a radial resistance stack (insulation layers + external natural convection + radiation):

Phi = (T_mean - T_amb) / R_total [kW]

This heat loss is distributed uniformly along the tube in a single forward ODE pass via a ct.Wall with heat_flux = -Phi / A_lateral. Because T_mean depends on the solution and the solution depends on Φ, the solver uses a Forward-Backward Sweep (FBS):

  1. Adiabatic pass → T_mean_0.

  2. Compute Φ from T_mean_0.

  3. Heated forward pass → new T_mean_1.

  4. Iterate until |Phi_n - Phi_{n-1}| / Phi_0 < CONVERGENCE_TOL (default 1 %).

SOLVER_MODE = "fixed_checkpoint" — uniform checkpoints along the axis.

When to use: SPRING reactors (CGR), insulated refractory-lined vessels, any reactor where axial wall conduction prevents local temperature gradients from dominating heat loss. Industrial model: RefractoryReactor.


PFRThinShell — Thin-Shell Local-Temperature Radial Heat Loss#

Physics: Thin-walled reactor (quartz tube, steel tube with negligible axial conduction) where heat loss at each axial position depends only on the local gas temperature T(z):

q(z) = (T(z) - T_amb) / R_total  [W/m²]

The wall conductance is inserted as a ct.Wall with time-varying heat_flux pinned to q(z) at each checkpoint. Because q(z) depends only on T(z) (no FBS needed), the solution requires only a single forward pass.

SOLVER_MODE = "fixed_checkpoint" — uniform checkpoints along the axis, no FBS.

When to use: Quartz-tube lab reactors, thin-wall steel tubes, any reactor where axial wall conduction is negligible. Industrial model: QuartzTubeReactor.


PFRGasTemperatureProfile — Imposed Gas Temperature Profile#

Physics: The gas temperature itself is prescribed along the axis as a profile T_gas(x) (Dirichlet on the gas). This is the boundary condition the other PFR engines do not cover: PFRWallProfile prescribes the wall temperature and lets the gas lag behind it through a convective + radiative film, whereas here the gas temperature is imposed and the energy equation is switched off — only the kinetics evolve:

T_gas(x) = T_prescribed(x)          (energy equation disabled)
dn_k/dt  = V_parcel * omega_k       (kinetics still integrated)

Numerically the closed Lagrangian parcel is marched with march_lagrangian_parcel(..., energy_off=True); the temperature is re-imposed before each checkpoint advance, so the stepwise-constant history converges to the continuous profile as the checkpoint count grows. This is the OO, closed-parcel counterpart of the procedural bloc.reactors.solve_fixed_position_temperature_profile_pfr.

SOLVER_MODE = "fixed_checkpoint" — uniform checkpoints along the axis, energy off, no FBS.

When to use: Kinetics validation against a measured in-stream gas temperature (thermocouple trace), or any study where you want predicted species under a known thermal history rather than a predicted temperature.

STONE kind: PFRGasTemperatureProfile. Exceptionally, this numerical engine is registered directly as a STONE kind (no separate industrial-model wrapper): the imposed-gas-temperature march is itself the modelled object. Driven by PFRGasTemperatureProfileNet.

Key YAML fields: diameter, total_length, T_gas_K, T_ambient_K, entry_leg, exit_leg, entry_zone, plateau_zone, optional T_gas_profile.


PSR — Perfectly Stirred Reactor (base)#

Physics: Well-mixed control volume at constant pressure. In an open stage network (SPRING ContinuousMixingReactor), Cantera integrates:

dT/dt = (sum_k h_k * V * omega_k - mdot * (h_out - h_in)) / (m * cp)
dn_k/dt = V * omega_k + mdot * (X_k,in - X_k)

with continuous inlet/outlet mass flows until steady state (advance_to_steady_state).

Network topology:

  • Stage YAML: OPEN — MFC in, PC/MFC out.

  • Inner physics: OPEN CSTR (not a closed parcel like the torch).

Common invariants:

  • ExtensibleIdealGasConstPressureMoleReactor family.

  • Design residence time t_res_s sizes volume: V = t_res_s * mdot / rho via Bloc post-build (_post_build_design_volumes).

When to use: Continuously-fed well-mixed reactor zones (torch outlet mixing tee, multi-inlet vessel). Industrial model: ContinuousMixingReactor.


InstantaneousMixing — 0-D HP Mix + Closed Residence-Time Chemistry#

Physics: Two inlet streams are combined via constant-H, constant-P algebraic mixing (mix_two_streams), then a closed parcel integrates ODE chemistry from t = 0 to t = t_res_s with no mass exchange during integration.

The two steps implement the Da_mix ≫ 1 assumption: turbulent mixing time is much shorter than the chemical relaxation time, so mixing can be treated as instantaneous before chemistry begins.

Step 1: gas_mix = HP_mix(gas_1, qm_1, gas_2, qm_2)  # algebraic, 0-D
Step 2: advance closed parcel 0 → t_res_s             # CVODE, no MFC flux

Network topology:

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

  • Inner physics: CLOSED parcel (no flux during CVODE integration). MFC rates are used only to identify the two inlet streams and their mass_flow_rate.

When to use: Feedforward one-shot mixing scenarios where the inlets arrive at distinct conditions (temperature, composition) and the mixing timescale is much faster than chemistry. For a continuously-fed CSTR, use ContinuousMixingReactor instead.

Industrial model: InstantaneousMixingReactor.


Industrial Models#

Industrial models are thin concrete subclasses of the engine classes. They add domain-specific parameter names, default values, KPI extractors, and documentation. They do not change the underlying physics.

TubeFurnacePFRWallProfile#

Electric tube furnace with a spatially varying internal wall temperature (plateau + entry/exit ramps + unheated cold legs). Uses forced convection and grey-gas radiation from the LagrangianPFRReactor engine.

STONE kind: TubeFurnace

Key YAML fields: diameter, total_length, T_wall_K, T_ambient_K, entry_leg, exit_leg, entry_zone, plateau_zone, kappa_grey, mass_flow_rate.

KPI function: bloc.reactor_models:compute_tube_furnace_kpis


RefractoryReactorPFRHomogeneousShell#

Insulated refractory-lined growth reactor (CGR in SPRING). Uses the homogeneous-shell heat-loss model with Forward-Backward Sweep.

STONE kind: RefractoryReactor (YAML node id CGR is a user convention)

Key YAML fields: length, diameter, mass_flow_rate, eps_wall, T_wall_hyp, T_amb, insulation, adiabatic, heat_loss_corr_factor.


QuartzTubeReactorPFRThinShell#

Quartz-tube or thin-wall lab reactor. Uses the thin-shell local-T heat-loss model.

STONE kind: QuartzTubeReactor

Key YAML fields: same as RefractoryReactor.


ContinuousMixingReactorPSR#

Multi-inlet well-mixed open CSTR (TMR in SPRING). Accepts multiple inlet: ports. Volume is sized by Bloc post-build using V = t_res_s * mdot / rho.

STONE kind: ContinuousMixingReactor (YAML node id TMR is a user convention)

Key YAML fields: t_res_s, temperature, pressure, composition.

Mixing model: Da_mix ≫ 1 assumed. Inlet streams are stirred by Cantera’s MFC topology inside the open CSTR until advance_to_steady_state. This is appropriate when the mixing and chemistry occur simultaneously in a continuously-fed vessel.


InstantaneousMixingReactorInstantaneousMixingPSR#

Two-inlet reactor that combines algebraic HP mixing with closed-parcel chemistry.

STONE kind: InstantaneousMixingReactor

Key YAML fields: t_res_s, temperature, pressure, composition.

Requires exactly two inlet MassFlowController connections. Bloc post-build (_post_build_design_volumes) gathers both inlet states and mass flow rates, calls InstantaneousMixing.solve_premixed, and writes the outlet back to reactor.phase

  • syncState().

When to choose over ContinuousMixingReactor:

Criterion

ContinuousMixingReactor

InstantaneousMixingReactor

Feed mode

Continuously fed

One-shot feedforward

Chemistry

CSTR (open, steady-state)

Closed parcel (no MFC flux)

Mixing

In-vessel MFC stirring

Algebraic HP mix before chemistry

Da_mix assumption

Implicit (well-mixed vessel)

Explicit (Da_mix ≫ 1)

t_res_s role

Sizes volume via V = τṁ/ρ

CVODE integration horizon

is_psr meta

True

False


PlasmaTorchInstantaneousHeatingTorchInstantaneousHeating#

Plasma torch modelled as an instantaneous enthalpy injection followed by chemical equilibration. Not a PFR. The InstantaneousHeating suffix reserves the namespace for future torch models with different heating physics.

STONE kind: PlasmaTorchInstantaneousHeating

Key YAML fields: torch_eff, gen_eff, t_res_s, temperature, pressure, composition.


Kind rename map#

The table below maps the legacy Design* YAML kinds to the current names. Legacy kinds are no longer registered — new and existing YAML files should use the current names.

Legacy kind

Current kind

Engine base

DesignTubeFurnace

TubeFurnace

PFRWallProfile

DesignPFR

RefractoryReactor

PFRHomogeneousShell

DesignPFRThinShell

QuartzTubeReactor

PFRThinShell

DesignPSR

ContinuousMixingReactor

PSR

DesignTorchInstantaneousHeating

PlasmaTorchInstantaneousHeating

TorchInstantaneousHeating

See the migration guide to update YAML files from legacy kinds to the current names.


PFRNetwork — Unified network driver#

PFRNetwork is the single network driver for all PFR subclasses. It dispatches on SOLVER_MODE:

  • "adaptive" — uses Cantera’s net.step() for each spatial checkpoint. Used by PFRWallProfile / TubeFurnace.

  • "fixed_checkpoint" — advances to each checkpoint with net.advance(t_check). May iterate (FBS) when PFRHomogeneousShell is used. Single-pass for PFRThinShell.

All PFR subclasses set NETWORK_CLASS = PFRNetwork.