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, andbatch_reactorintegrate the rate laws offugacio.thermo.kineticsover 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 in legacy calls 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) in legacy calls. Passing a
property package or ReactionSet to equilibrium_reactor, cstr, or pfr selects
the checked common-package implementation with phase-specific properties.
Its ReactionResult also retains acceptance reports and profiles.
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, |
ReactorResult
¶
Bases: NamedTuple
Outcome of a reactor calculation.
Attributes:
| Name | Type | Description |
|---|---|---|
outlet |
Stream
|
Product |
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 |
equilibrium_reactor
¶
equilibrium_reactor(
feed: Stream,
reactions: Reaction | Sequence[Reaction] | ReactionSet,
*,
model: Model = None,
phase: str = "vapor",
rate_basis: str = "concentration",
check: bool = True,
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 | ReactionResult
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 |
required |
reactions
|
Reaction | Sequence[Reaction] | ReactionSet
|
One reaction or several sharing the feed's component ordering. |
required |
t_out
|
ArrayLike | None
|
Isothermal operating temperature (K); defaults to |
None
|
adiabatic
|
bool
|
Solve the outlet temperature from an adiabatic balance instead. |
False
|
basis
|
str
|
|
'ideal-gas'
|
eos
|
CubicEOS
|
Cubic EOS used when |
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
|
model
|
Model
|
Common property package; enables the checked reactor implementation. |
None
|
phase
|
str
|
Homogeneous reaction phase for a newly constructed reaction set. |
'vapor'
|
rate_basis
|
str
|
Kinetic input convention for a newly constructed reaction set. |
'concentration'
|
check
|
bool
|
Raise on failed concrete package-based results. |
True
|
Returns:
| Type | Description |
|---|---|
ReactorResult | ReactionResult
|
A |
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,
model: Model = None,
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.
Pass model to use the flowsheet package's sensible and residual
enthalpies plus ideal-gas formation enthalpies. With no model, the historical
ideal-gas energy basis is retained. Reference-fluid packages have a different
energy reference and aren't supported for reaction thermochemistry.
Raises:
| Type | Description |
|---|---|
ValueError
|
if not exactly one of |
cstr
¶
cstr(
feed: Stream,
reactions: Reaction | Sequence[Reaction] | ReactionSet,
rate_laws: Any = None,
volume: ArrayLike | None = None,
*,
model: Model = None,
phase: str = "vapor",
rate_basis: str = "concentration",
check: bool = True,
t_out: ArrayLike | None = None,
adiabatic: bool = False,
tol: float = 1e-10,
max_iter: int = 100,
) -> ReactorResult | ReactionResult
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 ( |
required |
reactions
|
Reaction | Sequence[Reaction] | ReactionSet
|
Reaction(s) over |
required |
rate_laws
|
Any
|
One rate law per reaction; omit when reactions is a ReactionSet. |
None
|
volume
|
ArrayLike | None
|
Reactor volume (m^3). |
None
|
t_out
|
ArrayLike | None
|
Isothermal temperature (K); defaults to |
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
|
model
|
Model
|
Common property package; enables the checked reactor implementation. |
None
|
phase
|
str
|
Homogeneous reaction phase for a newly constructed reaction set. |
'vapor'
|
rate_basis
|
str
|
Kinetic input convention for a newly constructed reaction set. |
'concentration'
|
check
|
bool
|
Raise on failed concrete package-based results. |
True
|
pfr
¶
pfr(
feed: Stream,
reactions: Reaction | Sequence[Reaction] | ReactionSet,
rate_laws: Any = None,
volume: ArrayLike | None = None,
*,
model: Model = None,
phase: str = "vapor",
rate_basis: str = "concentration",
check: bool = True,
integration_rtol: float = 1e-05,
integration_atol: float = 1e-08,
t_out: ArrayLike | None = None,
adiabatic: bool = False,
steps: int = 200,
) -> ReactorResult | ReactionResult
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).
A package or ReactionSet selects the checked common-package path, including step doubling and phase-specific caloric properties. With a ReactionSet, omit rate_laws and specify volume by keyword.
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).
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 common-package units alongside the legacy gamma-phi approximation:
-
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_column: energy-balanced MESH with a common property package and volumetric rates on a declared liquid or vapor phase. -
reactive_distillation: a legacy multistage approximation (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 activitiesa_i = x_i gamma_iand a per-stage molar holdupH_j. For an equimolar reaction (sum_i nu_i = 0, the dominant reactive distillation class: esterification, transesterification, metathesis, isomerisation) the source conserves total moles. Constant molar overflow remains a material-balance approximation; it does not establish energy closure.
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 |
Solve isothermal chemical equilibrium coupled to a package PT flash. |
reactive_distillation |
Rate-based reactive distillation by the gamma-phi Wang-Henke method (CMO). |
reactive_column |
Solve reactive MESH distillation with formation-consistent stage energy. |
ReactiveFlashResult
¶
Bases: NamedTuple
Outcome of a simultaneous reaction + vapour-liquid flash.
Attributes:
| Name | Type | Description |
|---|---|---|
vapor |
Stream
|
Vapour product |
liquid |
Stream
|
Liquid product |
beta |
Array
|
Vapour fraction (mol vapour / mol after reaction). |
extent |
Array
|
Equilibrium extent of each reaction (mol/s), shape |
duty |
Array
|
External heat input, including formation energy exactly once (W). |
generation |
Array
|
Component generation (mol/s). |
report |
SolveReport
|
Chemical solve and final phase-solve acceptance. |
phase_report |
SolveReport
|
Actual final PT flash iteration report. |
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 |
x |
Array
|
Liquid mole fractions, shape |
y |
Array
|
Vapour mole fractions, shape |
distillate |
Stream
|
Distillate product |
bottoms |
Stream
|
Bottoms product |
reflux |
Array
|
Reflux ratio used. |
generation |
Array
|
Net mole generation by reaction on each stage (mol/s),
shape |
reactive_flash
¶
reactive_flash(
feed: Stream,
reactions: Reaction | Sequence[Reaction] | ReactionSet,
t: ArrayLike,
p: ArrayLike,
model: Model,
*,
tol: float = 1e-09,
max_iter: int = 100,
check: bool = True,
) -> ReactiveFlashResult
Solve isothermal chemical equilibrium coupled to a package PT flash.
All property and thermochemical parameters pass explicitly through the implicit solve, including under JIT, JVP, and VJP. The reaction quotient uses the liquid fugacity when liquid is present, otherwise the vapor fugacity. Absent phases never determine chemical equilibrium. Formation enthalpy is included once in the reported heat input (W).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
feed
|
Stream
|
Inlet material and thermal state. |
required |
reactions
|
Reaction | Sequence[Reaction] | ReactionSet
|
One reaction, a sequence, or a validated ReactionSet. |
required |
t
|
ArrayLike
|
Drum temperature (K). |
required |
p
|
ArrayLike
|
Drum pressure (Pa). |
required |
model
|
Model
|
Common property package or compatible equilibrium model. |
required |
tol
|
float
|
Chemical-equilibrium residual tolerance. |
1e-09
|
max_iter
|
int
|
Root iteration cap. |
100
|
check
|
bool
|
Raise for failed concrete solves; compiled callers inspect report. |
True
|
Returns:
| Type | Description |
|---|---|
ReactiveFlashResult
|
Products preserving phase inventories, reaction extents, heat input, |
ReactiveFlashResult
|
generation, and the actual chemical solve report. Process-case audits |
ReactiveFlashResult
|
independently assess product equilibrium, stability, and balances. |
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.
This legacy screening model has no stage energy equations. Equimolar stoichiometry does not establish energy closure. Use reactive_column for energy-balanced design and non-equimolar reactions.
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 |
required |
rate_laws
|
Any
|
One rate law per reaction ( |
required |
holdup
|
ArrayLike
|
Liquid molar holdup |
required |
n_stages
|
int
|
Number of equilibrium stages including the reboiler. |
required |
feed_stage
|
int
|
1-indexed feed stage. |
required |
reflux
|
ArrayLike
|
Reflux ratio |
required |
distillate_rate
|
ArrayLike
|
Distillate molar flow (mol/s). |
required |
reactive_stages
|
tuple[int, int] | None
|
Inclusive 1-indexed |
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 |
reactive_column
¶
reactive_column(
feeds: Sequence[ColumnFeed],
n_stages: int,
reactions: ReactionSet,
reaction_volumes: ArrayLike,
**kwargs: Any,
) -> RigorousColumnResult
Solve reactive MESH distillation with formation-consistent stage energy.
Arguments follow rigorous_column. Volumes are reacting-phase m^3; a scalar selects interior stages and a vector explicitly selects each stage. This rigorous entry point replaces CMO assumptions for process design. The older reactive_distillation function retains its historical molar-holdup screening convention and should only be used for comparisons with those old examples.
Checked common-package reactors¶
reaction_units
¶
Checked, property-package-consistent steady-state reaction calculations.
Reacting units use one declared homogeneous phase. Their energy includes formation enthalpies exactly once. A phase change is a rejected homogeneous reactor calculation; a reactive flash or reactive MESH column handles coupled reaction and phase separation explicitly.
Classes:
| Name | Description |
|---|---|
ReactionResult |
Reaction products, actual numerical reports, balances, and retained profiles. |
Functions:
| Name | Description |
|---|---|
reaction_parameter_validity |
Check finite reaction parameters and element conservation under JAX too. |
reaction_reactor |
Solve a homogeneous equilibrium reactor, CSTR, or PFR with a common package. |
ReactionResult
¶
Bases: NamedTuple
Reaction products, actual numerical reports, balances, and retained profiles.
Extents and generation are in mol/s; duty is W, positive into the fluid.
integration_error is a dimensionless step-doubling error ratio for
PFRs (accepted at <= 1), zero for algebraic reactors. Profiles use the
refined axial grid, including the inlet. Acceptance checks homogeneous
phase compatibility in addition to balance closure, but a finite PT flash
isn't an independent global phase-stability proof. Case runs add the
existing stream stability audit.
Methods:
| Name | Description |
|---|---|
check |
Raise with the retained report for a rejected concrete calculation. |
Attributes:
| Name | Type | Description |
|---|---|---|
converged |
Array
|
Whether numerical, physical-domain, and integration checks passed. |
reaction_parameter_validity
¶
reaction_parameter_validity(system: ReactionSet) -> Array
Check finite reaction parameters and element conservation under JAX too.
reaction_reactor
¶
reaction_reactor(
feed: Stream,
system: ReactionSet,
*,
kind: str = "equilibrium",
model: Model = None,
volume: float | Array = 1.0,
t_out: float | Array | None = None,
duty: float | Array | None = None,
dp: float | Array = 0.0,
steps: int = 64,
integration_rtol: float = 1e-05,
integration_atol: float = 1e-08,
tol: float = 1e-10,
max_iter: int = 100,
check: bool = True,
) -> ReactionResult
Solve a homogeneous equilibrium reactor, CSTR, or PFR with a common package.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
feed
|
Stream
|
Inlet material and phase state. |
required |
system
|
ReactionSet
|
Validated reactions, kinetic laws, phase, and rate basis. |
required |
kind
|
str
|
|
'equilibrium'
|
model
|
Model
|
Property package; defaults to Peng-Robinson. |
None
|
volume
|
float | Array
|
Reacting-phase volume (m^3), required positive for kinetic units. |
1.0
|
t_out
|
float | Array | None
|
Isothermal temperature. Omission retains inlet T if duty is omitted. |
None
|
duty
|
float | Array | None
|
Specified heat input (W); zero selects adiabatic operation. Mutually exclusive with t_out. PFR heat is distributed uniformly. |
None
|
dp
|
float | Array
|
Nonnegative pressure loss (Pa); PFR pressure decreases linearly. |
0.0
|
steps
|
int
|
Coarse PFR mesh size; a 2*steps mesh supplies the returned solution. |
64
|
integration_rtol
|
float
|
Relative step-doubling and energy error scale. |
1e-05
|
integration_atol
|
float
|
Absolute step-doubling scale in normalized coordinates. |
1e-08
|
tol
|
float
|
Scaled nonlinear residual tolerance. |
1e-10
|
max_iter
|
int
|
Newton iteration cap. |
100
|
check
|
bool
|
Raise on a rejected concrete result; traced callers inspect report. |
True
|
Returns:
| Type | Description |
|---|---|
ReactionResult
|
A ReactionResult retaining failed primals and nonfinite failed derivatives. |
ReactionResult
|
PFRs compare coarse/refined extents and temperatures, independently audit |
ReactionResult
|
energy, and reject negative inventory without clipping the final solution. |