bloc.reactors.march_engine#

Shared Lagrangian parcel march engine for PFR solvers.

Functions#

build_closed_carrier_net(reactor, T, P, X, volume, *)

Build a fresh CLOSED carrier reactor (no flow devices) and a bare ReactorNet.

copy_state(src_phase, dst_reactor)

Copy outlet TPX from src_phase back onto the stage dst_reactor.

march_lagrangian_parcel(reactor, T_in, P_in, X_in, *, ...)

Single forward pass of a CLOSED Lagrangian parcel from inlet to outlet.

Module Contents#

bloc.reactors.march_engine.build_closed_carrier_net(reactor, T, P, X, volume, *, reactor_kwargs=None, use_preconditioner=True, max_steps=None)#

Build a fresh CLOSED carrier reactor (no flow devices) and a bare ReactorNet.

Both reactor families share this constructor so the closed-parcel guarantee (“no mass flow in/out during the inner integration”) has a single named home and cannot silently drift between the tube-furnace and PFRHomogeneousShell paths.

The fresh carrier is built by cloning the mechanism source from reactor._mech_source (present on both PFRWallProfile and DesignIdealGasConstPressureMoleReactor) and constructing a new instance of type(reactor). Because the carrier is a freshly created object it carries no process flow devices (MFC/PC), so CVODE only sees the closed-system ODEs.

Parameters:
  • reactor – Template reactor whose type and mechanism source are reused.

  • T – Inlet thermodynamic state (K, Pa, mole fractions).

  • P – Inlet thermodynamic state (K, Pa, mole fractions).

  • X – Inlet thermodynamic state (K, Pa, mole fractions).

  • volume – Initial reactor volume [m³].

  • reactor_kwargs – Extra keyword arguments passed to type(reactor)(gas, clone=False, **reactor_kwargs).

  • use_preconditioner – Attach a cantera.AdaptivePreconditioner to the network.

  • max_steps – If provided, set net.max_steps on the ReactorNet.

Returns:

carrier — the fresh closed reactor, gas — the cantera.Solution used to initialise it, net — the bare cantera.ReactorNet.

Return type:

(carrier, gas, net)

bloc.reactors.march_engine.copy_state(src_phase, dst_reactor)#

Copy outlet TPX from src_phase back onto the stage dst_reactor.

Called after the inner closed-carrier integration completes so that the original stage reactor (which may carry process flow devices) reflects the converged outlet state. Both phase and the reactor’s internal CVODE state vector are updated.

bloc.reactors.march_engine.march_lagrangian_parcel(reactor, T_in, P_in, X_in, *, length, diameter, mdot, heat_flux_factory=None, on_position=None, recorder=None, reactor_kwargs=None, n_points=200, max_steps=200000, use_preconditioner=True, rtol=None, atol=None, max_time_step=None, energy_off=False)#

Single forward pass of a CLOSED Lagrangian parcel from inlet to outlet.

This is the shared march engine used by both the tube-furnace path (PFRWallProfileNet) and the PFRHomogeneousShell / PFRThinShell family (_march_pfr_to_length()). It always builds a fresh closed carrier reactor (via build_closed_carrier_net()) so the parcel integrates independently of any process flow devices (MFC/PC) that may be attached to the stage reactor. The converged outlet state is copied back to reactor via copy_state().

Integration proceeds in n_points equal spatial checkpoints x = i * dx, dx = length / n_points. At each checkpoint:

  1. on_position(carrier, x_prev) is called (if provided) so the caller can update position-dependent state (e.g. T_wall(x)).

  2. The carrier is advanced to the next time point via net.advance(t + dt) where dt = dx / v and v = mdot / (rho * S).

  3. recorder(carrier, x, net.time) is called (if provided).

A ct.Wall(ambient, carrier) with area = 1 is built when a heat_flux_factory is provided. The factory receives carrier and must return a callable heat_flux(t) -> float [W/m²] (Cantera Wall convention: positive = heat from ambient to carrier).

The ambient reservoir uses a throwaway gri30 gas — it is never advanced, so its thermodynamic state is irrelevant.

Parameters:
  • reactor – Template / stage reactor. type(reactor) and _mech_source are used to build the fresh carrier; the outlet state is copied back here after the march.

  • T_in – Inlet state (K, Pa, mole fractions).

  • P_in – Inlet state (K, Pa, mole fractions).

  • X_in – Inlet state (K, Pa, mole fractions).

  • length – Tube length [m].

  • diameter – Tube inner diameter [m].

  • mdot – Mass flow rate [kg/s].

  • heat_flux_factoryfactory(carrier) -> callable that builds the Wall.heat_flux function. Pass None for adiabatic.

  • on_positionon_position(carrier, x) called before each checkpoint advance. Use to set carrier.T_wall_K, carrier.x_position, etc.

  • recorderrecorder(carrier, x, t) called after each checkpoint.

  • reactor_kwargs – Forwarded to build_closed_carrier_net().

  • n_points – Number of spatial checkpoints. Default 200.

  • max_steps – CVODE maximum steps per checkpoint. Default 200 000.

  • use_preconditioner – Attach cantera.AdaptivePreconditioner. Default True.

  • rtol – Relative / absolute CVODE tolerances forwarded to the inner cantera.ReactorNet. None leaves Cantera defaults.

  • atol – Relative / absolute CVODE tolerances forwarded to the inner cantera.ReactorNet. None leaves Cantera defaults.

  • max_time_step – Optional upper bound on the inner CVODE step size [s]. None (default) lets CVODE choose its own internal steps within each spatial-cell advance.

  • energy_off – When True the carrier’s energy equation is disabled (carrier.energy_enabled = False) so the gas temperature is held constant during each checkpoint advance. The temperature is then a Dirichlet condition imposed by on_position (see PFRGasTemperatureProfile). Default False.

Returns:

Spatial profile with extra columns t (residence time [s]) and x (axial position [m]). The outlet state is also copied back to reactor.

Return type:

ct.SolutionArray