Skip to content

Reactors & reactive separations

Equilibrium and kinetic reactors (Gibbs/stoichiometric equilibrium, CSTR, PFR) and reactive separations that solve phase and reaction equilibrium together (reactive flash and reactive distillation).

See the reactions & reactors guide for worked examples.

Reactors

reactors

Differentiable reactor unit operations with material and energy balances.

These blocks turn the reaction thermochemistry and kinetics in fugacio.thermo into flowsheet units that consume and produce Stream objects, just like the separation units in fugacio.sim.units. Two families are provided:

  • Equilibrium / stoichiometric reactors: the conversion is set by chemical equilibrium (fugacio.thermo.reaction_equilibrium.equilibrium) or by a specified extent/conversion; no rate law is needed.
  • Kinetic reactors: cstr, pfr, and batch_reactor integrate the rate laws of fugacio.thermo.kinetics over reactor volume (CSTR/PFR) or time (batch).

Every reactor supports an energy balance: run it isothermally at a specified temperature and the heat duty required to hold that temperature is returned (it carries the heat of reaction), or run it adiabatic=True and the outlet temperature is solved from an adiabatic enthalpy balance. The enthalpy bookkeeping is the ideal-gas absolute enthalpy Hf_i(298) + integral Cp_i dT that underlies fugacio.thermo.reactions.delta_h_rxn, so reaction heat and sensible heat are accounted for consistently. Kinetic-reactor concentrations use the ideal-gas relation c_i = y_i P / (R T).

Because the underlying solves (equilibrium root-finds, the CSTR Newton system, the explicit RK4 marches) are differentiable, a reactor's conversion, outlet temperature, and duty are differentiable in the feed, the operating conditions, and the reaction/kinetic parameters, ready for gradient-based design.

Classes:

Name Description
ReactorResult

Outcome of a reactor calculation.

Functions:

Name Description
equilibrium_reactor

Reactor whose outlet is the chemical-equilibrium composition.

stoichiometric_reactor

Reactor with a specified extent or key-reactant conversion (no equilibrium).

cstr

Continuous stirred-tank reactor (perfectly mixed) at steady state.

pfr

Plug-flow reactor: integrate the species balances along the reactor volume.

batch_reactor

Constant-volume batch reactor: integrate the mole balances over time.

conversion

Fractional conversion of a feed component, (n_in - n_out) / n_in.

ReactorResult

Bases: NamedTuple

Outcome of a reactor calculation.

Attributes:

Name Type Description
outlet Stream

Product Stream (at the reactor outlet temperature, solved for adiabatic operation).

duty Array

Heat duty (W) to hold an isothermal reactor at temperature; positive means heat added. Zero for an adiabatic reactor.

extent Array

Extent of each reaction (mol/s for flow reactors, mol for batch), shape (n_reactions,).

equilibrium_reactor

equilibrium_reactor(
    feed: Stream,
    reactions: Reaction | Sequence[Reaction],
    *,
    t_out: ArrayLike | None = None,
    adiabatic: bool = False,
    basis: str = "ideal-gas",
    eos: CubicEOS = PR,
    kij: Array | None = None,
    tol: float = 1e-10,
    max_iter: int = 80,
) -> ReactorResult

Reactor whose outlet is the chemical-equilibrium composition.

Isothermal (default, or with t_out): the equilibrium composition at the operating temperature is found and the duty to hold that temperature returned. Adiabatic (adiabatic=True): the extents and outlet temperature are solved together from the equilibrium conditions plus an adiabatic energy balance (ideal-gas basis).

Parameters:

Name Type Description Default
feed Stream

Inlet stream; reactions must be defined over feed.components.

required
reactions Reaction | Sequence[Reaction]

One reaction or several sharing the feed's component ordering.

required
t_out ArrayLike | None

Isothermal operating temperature (K); defaults to feed.t.

None
adiabatic bool

Solve the outlet temperature from an adiabatic balance instead.

False
basis str

"ideal-gas" or "phi" (EOS fugacity coefficients) for the isothermal equilibrium; adiabatic operation uses the ideal-gas basis.

'ideal-gas'
eos CubicEOS

Cubic EOS used when basis="phi".

PR
kij Array | None

Optional binary interaction matrix for the EOS.

None
tol float

Convergence tolerance on the reaction extents.

1e-10
max_iter int

Maximum number of solver iterations.

80

Returns:

Type Description
ReactorResult

A ReactorResult.

stoichiometric_reactor

stoichiometric_reactor(
    feed: Stream,
    reactions: Reaction | Sequence[Reaction],
    *,
    extent: ArrayLike | None = None,
    conversion: ArrayLike | None = None,
    t_out: ArrayLike | None = None,
    adiabatic: bool = False,
    t_lo: float = 200.0,
    t_hi: float = 6000.0,
) -> ReactorResult

Reactor with a specified extent or key-reactant conversion (no equilibrium).

Provide exactly one of extent (per reaction, mol/s) or conversion (a single-reaction fractional conversion of its limiting reactant). The outlet is n = n_feed + extent @ nu; the energy balance is the same isothermal-duty / adiabatic-temperature treatment as equilibrium_reactor.

Raises:

Type Description
ValueError

if not exactly one of extent / conversion is given, or conversion is used with more than one reaction.

cstr

cstr(
    feed: Stream,
    reactions: Reaction | Sequence[Reaction],
    rate_laws: Any,
    volume: ArrayLike,
    *,
    t_out: ArrayLike | None = None,
    adiabatic: bool = False,
    tol: float = 1e-10,
    max_iter: int = 100,
) -> ReactorResult

Continuous stirred-tank reactor (perfectly mixed) at steady state.

Solves the steady-state mole balance F_out = F_in + V (r . Nu) with the outlet-condition rates r (one per reaction, from rate_laws) and ideal-gas concentrations. Isothermal by default (duty returned); with adiabatic=True the outlet temperature is solved jointly with the flows.

Parameters:

Name Type Description Default
feed Stream

Inlet stream (feed.n are molar flows, mol/s).

required
reactions Reaction | Sequence[Reaction]

Reaction(s) over feed.components.

required
rate_laws Any

One rate law per reaction (a kinetics object with rate(T, c)).

required
volume ArrayLike

Reactor volume (m^3).

required
t_out ArrayLike | None

Isothermal temperature (K); defaults to feed.t.

None
adiabatic bool

Solve the outlet temperature from the energy balance.

False
tol float

Convergence tolerance on the steady-state mole balance.

1e-10
max_iter int

Maximum number of Newton iterations.

100

pfr

pfr(
    feed: Stream,
    reactions: Reaction | Sequence[Reaction],
    rate_laws: Any,
    volume: ArrayLike,
    *,
    t_out: ArrayLike | None = None,
    adiabatic: bool = False,
    steps: int = 200,
) -> ReactorResult

Plug-flow reactor: integrate the species balances along the reactor volume.

Marches dF_i/dV = (r . Nu)_i (ideal-gas concentrations, isobaric) from the feed to volume with explicit RK4. Isothermal by default; with adiabatic=True the temperature is integrated alongside via dT/dV = -(sum_j r_j DH_rxn,j) / (sum_i F_i Cp_i).

batch_reactor

batch_reactor(
    feed: Stream,
    reactions: Reaction | Sequence[Reaction],
    rate_laws: Any,
    volume: ArrayLike,
    time: ArrayLike,
    *,
    t_out: ArrayLike | None = None,
    adiabatic: bool = False,
    steps: int = 200,
) -> ReactorResult

Constant-volume batch reactor: integrate the mole balances over time.

Here feed.n are the initial moles (mol). Marches dN_i/dt = V (r . Nu)_i with concentrations c_i = N_i / V by explicit RK4. Isothermal by default; with adiabatic=True the temperature is integrated via (sum_i N_i Cp_i) dT/dt = -V sum_j r_j DH_rxn,j. The returned extent is in moles and duty (isothermal) is the cumulative heat (J).

conversion

conversion(
    feed: Stream, outlet: Stream, component_index: int
) -> Array

Fractional conversion of a feed component, (n_in - n_out) / n_in.

Reactive separations

reactive

Reactive separations: simultaneous chemical reaction and phase equilibrium.

Real separation equipment often runs with a reaction happening inside it: the whole point of reactive distillation is to push a reaction past its equilibrium limit by continuously pulling products into a different phase. This module adds two such units on top of the gamma-phi property system:

  • reactive_flash: an isothermal flash in which the liquid simultaneously reaches chemical equilibrium (one or more reactions) and phase equilibrium (vapour-liquid). The extents of reaction and the V/L split are solved together, reusing the validated gamma-phi flash and the ideal-gas reaction thermochemistry. Works for any net mole change.

  • reactive_distillation: a rigorous multistage column (Wang-Henke bubble-point, constant molar overflow) with a rate-based reaction source on each reactive stage: S_{j,i} = H_j * sum_r nu_{r,i} * rate_r(T_j, a_j) with the liquid-phase activities a_i = x_i gamma_i and a per-stage molar holdup H_j. For an equimolar reaction (sum_i nu_i = 0, the dominant reactive distillation class: esterification, transesterification, metathesis, isomerisation) the source conserves total moles, so constant molar overflow is exact and the model is rigorous.

The reaction equilibrium constant K(T) comes from the ideal-gas formation data in fugacio.thermo.reactions; at vapour-liquid equilibrium the component fugacities are equal across phases, so the ideal-gas-referenced equilibrium is written consistently in terms of the liquid activities a_i = x_i gamma_i f_i^{0,L}/P_ref. Every result is a differentiable Stream (or profile of them): conversions, product purities, and stage profiles carry gradients with respect to the feed, operating conditions, the activity-model parameters, and the kinetic/thermochemical parameters.

Classes:

Name Description
ReactiveFlashResult

Outcome of a simultaneous reaction + vapour-liquid flash.

ReactiveColumnResult

Converged profile and products of a reactive distillation column.

Functions:

Name Description
reactive_flash

Isothermal flash with simultaneous chemical and phase equilibrium.

reactive_distillation

Rate-based reactive distillation by the gamma-phi Wang-Henke method (CMO).

ReactiveFlashResult

Bases: NamedTuple

Outcome of a simultaneous reaction + vapour-liquid flash.

Attributes:

Name Type Description
vapor Stream

Vapour product Stream.

liquid Stream

Liquid product Stream.

beta Array

Vapour fraction (mol vapour / mol after reaction).

extent Array

Equilibrium extent of each reaction (mol/s), shape (n_reactions,).

ReactiveColumnResult

Bases: NamedTuple

Converged profile and products of a reactive distillation column.

Attributes:

Name Type Description
t Array

Stage temperatures (K), top stage first, shape (n_stages,).

x Array

Liquid mole fractions, shape (n_stages, n_components).

y Array

Vapour mole fractions, shape (n_stages, n_components).

distillate Stream

Distillate product Stream.

bottoms Stream

Bottoms product Stream.

reflux Array

Reflux ratio used.

generation Array

Net mole generation by reaction on each stage (mol/s), shape (n_stages, n_components).

reactive_flash

reactive_flash(
    feed: Stream,
    reactions: Reaction | Sequence[Reaction],
    t: ArrayLike,
    p: ArrayLike,
    model: GammaPhiModel,
    *,
    tol: float = 1e-11,
    max_iter: int = 80,
) -> ReactiveFlashResult

Isothermal flash with simultaneous chemical and phase equilibrium.

Solves for the reaction extents that satisfy chemical equilibrium while the mixture is split by a gamma-phi vapour-liquid flash at (T, P). The reaction equilibrium is imposed on the liquid activities (equivalently the equal vapour fugacities), so it is consistent across the whole vapour-fraction range; it even pins the bubble/dew composition when the flash is single-phase.

Parameters:

Name Type Description Default
feed Stream

Inlet stream; reactions must be defined over feed.components.

required
reactions Reaction | Sequence[Reaction]

One reaction or several over the feed's component ordering.

required
t ArrayLike

Temperature (K).

required
p ArrayLike

Pressure (Pa).

required
model GammaPhiModel

A GammaPhiModel (activity liquid + EOS/ideal vapour), the right tool for the non-ideal mixtures reactive flashes target.

required
tol float

Convergence tolerance on the reaction/flash residual.

1e-11
max_iter int

Maximum number of solver iterations.

80

Returns:

Type Description
ReactiveFlashResult

A ReactiveFlashResult. Differentiable in the feed, (T, P), the

ReactiveFlashResult

activity-model parameters, and the reaction thermochemistry.

reactive_distillation

reactive_distillation(
    feed: Stream,
    model: GammaPhiModel,
    reactions: Reaction | Sequence[Reaction],
    rate_laws: Any,
    holdup: ArrayLike,
    n_stages: int,
    feed_stage: int,
    reflux: ArrayLike,
    distillate_rate: ArrayLike,
    *,
    reactive_stages: tuple[int, int] | None = None,
    q: ArrayLike = 1.0,
    t_top: ArrayLike | None = None,
    t_bottom: ArrayLike | None = None,
    t_min: float = 200.0,
    t_max: float = 700.0,
    tol: float = 1e-11,
    max_iter: int = 600,
) -> ReactiveColumnResult

Rate-based reactive distillation by the gamma-phi Wang-Henke method (CMO).

A total condenser sits above stage 1 and a partial reboiler is stage n_stages; one feed of quality q enters at feed_stage (1-indexed). Each stage equilibrates by the gamma-phi bubble-point method, and on every reactive stage a rate-based source H * sum_r nu_r rate_r(T, a) (liquid activities a_i = x_i gamma_i, molar holdup H) is added to the component balance. The whole profile is converged by the Wegstein tear solver, so the products and profiles are differentiable with respect to reflux, distillate_rate, holdup, the feed, and the model/kinetic parameters.

For an equimolar reaction the source conserves total moles and constant molar overflow is exact. (Non-equimolar reactions also run, but the constant-overflow traffic then neglects the reaction's volume change.)

Parameters:

Name Type Description Default
feed Stream

Feed stream.

required
model GammaPhiModel

Gamma-phi property model for the (non-ideal) liquid.

required
reactions Reaction | Sequence[Reaction]

One reaction or several over feed.components.

required
rate_laws Any

One rate law per reaction (rate(T, a); activities passed as the concentration argument for a pseudo-homogeneous, activity-based rate).

required
holdup ArrayLike

Liquid molar holdup H on each reactive stage (mol).

required
n_stages int

Number of equilibrium stages including the reboiler.

required
feed_stage int

1-indexed feed stage.

required
reflux ArrayLike

Reflux ratio L/D.

required
distillate_rate ArrayLike

Distillate molar flow (mol/s).

required
reactive_stages tuple[int, int] | None

Inclusive 1-indexed (first, last) reactive stage range; defaults to all interior stages (2, n_stages - 1).

None
q ArrayLike

Feed thermal quality (1 = saturated liquid).

1.0
t_top ArrayLike | None

Optional initial top-stage temperature (K).

None
t_bottom ArrayLike | None

Optional initial bottom-stage temperature (K).

None
t_min float

Lower per-stage temperature clamp (K).

200.0
t_max float

Upper per-stage temperature clamp (K).

700.0
tol float

Convergence tolerance for the outer fixed point.

1e-11
max_iter int

Maximum number of outer sweeps.

600

Returns:

Type Description
ReactiveColumnResult

A ReactiveColumnResult.