Phase equilibrium¶
Vapour-liquid equilibrium by both routes: an equation of state for both phases
(phi-phi) and an activity-coefficient liquid with an EOS or ideal vapour
(gamma-phi). The unified EOSModel / GammaPhiModel interface lets the rest of
the stack switch thermodynamic models without changing call sites.
See the non-ideal phase equilibrium guide for worked examples.
EOS (phi-phi) equilibrium¶
equilibrium
¶
Phase equilibrium: K-values, Rachford-Rice, flash, saturation, and stability.
This module turns the cubic equation of state (fugacio.thermo.eos) into
the equilibrium calculations a process simulator actually calls:
wilson_k: the classic K-value initial guess;rachford_rice: the material-balance root for the vapour fraction;flash_pt: an isothermal-isobaric two-phase flash;psat_eos: pure-component saturation pressure by equifugacity;bubble_pressure_eos/dew_pressure_eos: phase envelopes;stability_analysis: Michelsen's tangent-plane-distance test.
Every iterative result is differentiable end-to-end: the scalar solves carry
hand-written implicit-function-theorem rules (jax.custom_jvp) and the
flash/saturation loops reuse fugacio.thermo.implicit.fixed_point. You can
therefore take a gradient of any equilibrium output with respect to T,
P, composition, or model parameters, the property that makes Fugacio a
differentiable core rather than just another flash package.
Classes:
| Name | Description |
|---|---|
FlashResult |
Result of an isothermal-isobaric flash. |
StabilityResult |
Result of a tangent-plane stability analysis. |
Functions:
| Name | Description |
|---|---|
wilson_k |
Wilson correlation for initial K-values |
rachford_rice |
Solve the Rachford-Rice equation for the vapour fraction |
flash_pt |
Isothermal-isobaric two-phase flash by accelerated successive substitution. |
psat_eos |
Pure-component saturation pressure (Pa) from the EOS by equifugacity. |
bubble_pressure_eos |
Bubble-point pressure and incipient vapour composition at fixed |
dew_pressure_eos |
Dew-point pressure and incipient liquid composition at fixed |
stability_analysis |
Michelsen tangent-plane stability test for a feed |
FlashResult
¶
Bases: NamedTuple
Result of an isothermal-isobaric flash.
Attributes:
| Name | Type | Description |
|---|---|---|
beta |
Array
|
Vapour molar fraction (mol vapour / mol feed). |
x |
Array
|
Liquid-phase mole fractions. |
y |
Array
|
Vapour-phase mole fractions. |
k |
Array
|
Equilibrium ratios |
StabilityResult
¶
Bases: NamedTuple
Result of a tangent-plane stability analysis.
Attributes:
| Name | Type | Description |
|---|---|---|
stable |
Array
|
|
tpd |
Array
|
The smallest (most negative) modified tangent-plane distance found. |
wilson_k
¶
Wilson correlation for initial K-values K_i = y_i / x_i.
K_i = (Pc_i / P) * exp[5.373 (1 + omega_i)(1 - Tc_i / T)].
rachford_rice
¶
Solve the Rachford-Rice equation for the vapour fraction beta.
Returns beta clamped to [0, 1]: 0 for a subcooled liquid, 1
for a superheated vapour, and the interior root otherwise. The residual
sum_i z_i (K_i - 1) / (1 + beta (K_i - 1)) is monotonically decreasing in
beta on (0, 1), so a bisection is used for the interior root.
flash_pt
¶
flash_pt(
eos: CubicEOS,
t: ArrayLike,
p: ArrayLike,
z: Array,
tc: Array,
pc: Array,
omega: Array,
*,
kij: Array | None = None,
tol: float = 1e-12,
max_iter: int = 300,
) -> FlashResult
Isothermal-isobaric two-phase flash by accelerated successive substitution.
Solves the equal-fugacity conditions phi_i^L x_i = phi_i^V y_i together
with the Rachford-Rice material balance, starting from Wilson K-values. The
converged solution (and therefore beta, x, y) is
differentiable with respect to (T, P, z, ...) via implicit
differentiation of the fixed point.
psat_eos
¶
psat_eos(
eos: CubicEOS,
t: ArrayLike,
tc: ArrayLike,
pc: ArrayLike,
omega: ArrayLike,
tol: float = 1e-10,
max_iter: int = 100,
) -> Array
Pure-component saturation pressure (Pa) from the EOS by equifugacity.
Solves ln phi^L(T, P) = ln phi^V(T, P) for P with a Newton iteration
in ln P (which keeps the pressure positive), initialised from the Wilson
vapour-pressure estimate. Differentiable in T (and the critical
constants) via the Clapeyron-like implicit derivative dP/dT.
bubble_pressure_eos
¶
bubble_pressure_eos(
eos: CubicEOS,
t: ArrayLike,
x: Array,
tc: Array,
pc: Array,
omega: Array,
*,
kij: Array | None = None,
tol: float = 1e-12,
max_iter: int = 300,
) -> tuple[Array, Array]
Bubble-point pressure and incipient vapour composition at fixed T, x.
Returns (P, y). Solved as a coupled fixed point in (ln P, y) so the
result is differentiable in temperature and composition.
dew_pressure_eos
¶
dew_pressure_eos(
eos: CubicEOS,
t: ArrayLike,
y: Array,
tc: Array,
pc: Array,
omega: Array,
*,
kij: Array | None = None,
tol: float = 1e-12,
max_iter: int = 300,
) -> tuple[Array, Array]
Dew-point pressure and incipient liquid composition at fixed T, y.
Returns (P, x), differentiable in temperature and composition.
stability_analysis
¶
stability_analysis(
eos: CubicEOS,
t: ArrayLike,
p: ArrayLike,
z: Array,
tc: Array,
pc: Array,
omega: Array,
*,
kij: Array | None = None,
iters: int = 40,
) -> StabilityResult
Michelsen tangent-plane stability test for a feed z at (T, P).
Performs two trial-phase searches (vapour-like and liquid-like). If the
modified tangent-plane distance tm dips below zero for either trial, a
second phase can lower the Gibbs energy and the feed is unstable (it will
split). Returns the worst (smallest) tm found and a stability flag.
Gamma-phi equilibrium¶
gammaphi
¶
Gamma-phi vapour-liquid equilibrium (activity-coefficient liquid model).
The cubic-EOS flash in fugacio.thermo.equilibrium describes both phases
with one equation of state (the phi-phi approach). For the low-pressure, polar,
strongly non-ideal mixtures that dominate real separations (ethanol/water and
other azeotropes, alcohol/ketone/water systems), a cubic EOS with zero binary
interaction parameters is simply the wrong tool. The standard answer is the
gamma-phi approach: model the liquid with an activity-coefficient model and the
vapour with an equation of state (or as an ideal gas at low pressure).
Equilibrium equates the component fugacities
x_i gamma_i(x, T) f_i^{0,L}(T, P) = y_i phi_i^V(y, T, P) P
so the K-values are
K_i = y_i / x_i = gamma_i f_i^{0,L} / (phi_i^V P).
With an ideal vapour (phi^V = 1) and the plain saturation reference
(f^{0,L} = Psat), this collapses to modified Raoult's law
K_i = gamma_i Psat_i / P, enough to reproduce azeotropes that the
zero-kij cubic cannot. The richer reference (saturation fugacity coefficient +
Poynting, see fugacio.thermo.reference) and an EOS vapour are available via
keyword flags.
Every routine here, K-values, the four saturation calculations (bubble/dew at
fixed T or P), and the isothermal flash, is a fixed point or a
bracketed root solved by the implicit-diff primitives in
fugacio.thermo.implicit, so each output is differentiable end-to-end with
respect to T, P, composition, and the activity-model parameters. That
last point is what turns parameter regression (fugacio.thermo.regression)
into plain gradient descent.
Functions:
| Name | Description |
|---|---|
gamma_phi_k_values |
Gamma-phi K-values |
bubble_pressure_gamma |
Bubble-point pressure and incipient vapour composition at fixed |
dew_pressure_gamma |
Dew-point pressure and incipient liquid composition at fixed |
bubble_temperature_gamma |
Bubble-point temperature and incipient vapour at fixed |
dew_temperature_gamma |
Dew-point temperature and incipient liquid at fixed |
flash_pt_gamma |
Isothermal-isobaric gamma-phi flash by accelerated successive substitution. |
gamma_phi_k_values
¶
gamma_phi_k_values(
model: ActivityModel,
t: ArrayLike,
p: ArrayLike,
x: Array,
y: Array,
tc: Array,
pc: Array,
omega: Array,
*,
eos: CubicEOS = PR,
kij: Array | None = None,
vapor: str = "ideal",
poynting: bool = False,
phi_saturation: bool = False,
) -> Array
Gamma-phi K-values K_i = gamma_i f_i^{0,L} / (phi_i^V P).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
ActivityModel
|
Liquid activity-coefficient model. |
required |
t
|
ArrayLike
|
Temperature (K). |
required |
p
|
ArrayLike
|
Pressure (Pa). |
required |
x
|
Array
|
Liquid mole fractions. |
required |
y
|
Array
|
Vapour mole fractions (only matters for an EOS vapour). |
required |
tc
|
Array
|
Component critical temperatures (K). |
required |
pc
|
Array
|
Component critical pressures (Pa). |
required |
omega
|
Array
|
Component acentric factors. |
required |
eos
|
CubicEOS
|
Cubic EOS for the saturation reference and (if selected) the vapour. |
PR
|
kij
|
Array | None
|
Optional binary interaction matrix for the vapour EOS. |
None
|
vapor
|
str
|
|
'ideal'
|
poynting
|
bool
|
Include the Poynting pressure correction in the reference. |
False
|
phi_saturation
|
bool
|
Include the saturation fugacity coefficient in the reference. |
False
|
Returns:
| Type | Description |
|---|---|
Array
|
K-values aligned with |
bubble_pressure_gamma
¶
bubble_pressure_gamma(
model: ActivityModel,
t: ArrayLike,
x: Array,
tc: Array,
pc: Array,
omega: Array,
*,
eos: CubicEOS = PR,
kij: Array | None = None,
vapor: str = "ideal",
poynting: bool = False,
phi_saturation: bool = False,
tol: float = 1e-12,
max_iter: int = 200,
) -> tuple[Array, Array]
Bubble-point pressure and incipient vapour composition at fixed T, x.
Solved as a coupled fixed point in (ln P, y): K-values give an unnormalised
vapour y* = K x whose sum scales the pressure until it is one. Returns
(P, y), differentiable in T, x and the model parameters.
dew_pressure_gamma
¶
dew_pressure_gamma(
model: ActivityModel,
t: ArrayLike,
y: Array,
tc: Array,
pc: Array,
omega: Array,
*,
eos: CubicEOS = PR,
kij: Array | None = None,
vapor: str = "ideal",
poynting: bool = False,
phi_saturation: bool = False,
tol: float = 1e-12,
max_iter: int = 200,
) -> tuple[Array, Array]
Dew-point pressure and incipient liquid composition at fixed T, y.
Coupled fixed point in (ln P, x): with x_i = y_i / K_i (and the
activity coefficients re-evaluated at the updated x), the pressure is
scaled until the liquid sums to one. Returns (P, x).
bubble_temperature_gamma
¶
bubble_temperature_gamma(
model: ActivityModel,
p: ArrayLike,
x: Array,
tc: Array,
pc: Array,
omega: Array,
*,
eos: CubicEOS = PR,
kij: Array | None = None,
vapor: str = "ideal",
poynting: bool = False,
phi_saturation: bool = False,
t_min: float = 150.0,
t_max: float = 700.0,
tol: float = 1e-09,
max_iter: int = 200,
inner_iter: int = 0,
) -> tuple[Array, Array]
Bubble-point temperature and incipient vapour at fixed P, x.
The bubble temperature is the root of sum_i K_i(T) x_i = 1 (the saturation
sum is monotone in T), found with the bracketed solver and differentiated
by the implicit function theorem. Returns (T, y). For an ideal vapour the
K-values are independent of y and inner_iter can stay zero; raise it
for an EOS vapour so the incipient y settles before the bracket step.
dew_temperature_gamma
¶
dew_temperature_gamma(
model: ActivityModel,
p: ArrayLike,
y: Array,
tc: Array,
pc: Array,
omega: Array,
*,
eos: CubicEOS = PR,
kij: Array | None = None,
vapor: str = "ideal",
poynting: bool = False,
phi_saturation: bool = False,
t_min: float = 150.0,
t_max: float = 700.0,
tol: float = 1e-09,
max_iter: int = 200,
inner_iter: int = 30,
) -> tuple[Array, Array]
Dew-point temperature and incipient liquid at fixed P, y.
Root of sum_i (y_i / K_i(T)) = 1 in T with an inner sweep that settles
the incipient liquid x (on which the activity coefficients depend) at each
trial temperature. Returns (T, x).
flash_pt_gamma
¶
flash_pt_gamma(
model: ActivityModel,
t: ArrayLike,
p: ArrayLike,
z: Array,
tc: Array,
pc: Array,
omega: Array,
*,
eos: CubicEOS = PR,
kij: Array | None = None,
vapor: str = "ideal",
poynting: bool = False,
phi_saturation: bool = False,
tol: float = 1e-12,
max_iter: int = 300,
) -> FlashResult
Isothermal-isobaric gamma-phi flash by accelerated successive substitution.
Iterates the gamma-phi K-values to a fixed point in ln K with the
Rachford-Rice material balance closing the phase split at each step. The
converged beta, x, y are differentiable with respect to
(T, P, z) and the activity-model parameters.
Unified model interface¶
phase
¶
A uniform phase-equilibrium model: one interface over EOS and gamma-phi.
The two routes to vapour-liquid equilibrium, a cubic equation of state for both
phases (fugacio.thermo.equilibrium) and an activity model for the liquid
with an EOS/ideal vapour (fugacio.thermo.gammaphi), have, until now,
different call signatures. That made the rest of the stack (flashes inside unit
operations, column K-values, the copilot tools) hard-wire the EOS. This module
unifies them behind a single EquilibriumModel interface so a flowsheet
can be switched from Peng-Robinson to NRTL by swapping one object.
Both concrete models (EOSModel and GammaPhiModel) bundle the
component constants they need and expose the same five calls: flash_pt,
bubble_pressure/bubble_temperature and dew_pressure/dew_temperature.
They are registered JAX pytrees whose parameters (critical constants, kij, and,
for the gamma-phi model, the activity-model parameters) are differentiable
leaves, while structural choices (which cubic, ideal-vs-EOS vapour) are static
metadata. A flowsheet built on a model therefore stays end-to-end differentiable,
including with respect to the thermodynamic model's own parameters.
Classes:
| Name | Description |
|---|---|
EquilibriumModel |
Structural type for a vapour-liquid equilibrium model. |
EOSModel |
Equation-of-state (phi-phi) equilibrium model. |
GammaPhiModel |
Gamma-phi equilibrium model: activity-coefficient liquid, EOS/ideal vapour. |
Functions:
| Name | Description |
|---|---|
eos_model |
Construct an |
gamma_phi_model |
Construct a |
EquilibriumModel
¶
Bases: Protocol
Structural type for a vapour-liquid equilibrium model.
Every model maps operating conditions to a phase split (flash_pt) and to
the four saturation calculations. Implementations bundle their own component
constants, so callers pass only state (T, P, composition).
Methods:
| Name | Description |
|---|---|
flash_pt |
Isothermal-isobaric two-phase flash. |
bubble_pressure |
Bubble pressure and incipient vapour |
dew_pressure |
Dew pressure and incipient liquid |
bubble_temperature |
Bubble temperature and incipient vapour |
dew_temperature |
Dew temperature and incipient liquid |
flash_pt
¶
flash_pt(
t: ArrayLike, p: ArrayLike, z: Array
) -> FlashResult
Isothermal-isobaric two-phase flash.
bubble_pressure
¶
bubble_pressure(
t: ArrayLike, x: Array
) -> tuple[Array, Array]
Bubble pressure and incipient vapour (P, y) at fixed T, x.
dew_pressure
¶
dew_pressure(t: ArrayLike, y: Array) -> tuple[Array, Array]
Dew pressure and incipient liquid (P, x) at fixed T, y.
EOSModel
dataclass
¶
EOSModel(
tc: Array,
pc: Array,
omega: Array,
kij: Array | None,
eos: CubicEOS,
)
Equation-of-state (phi-phi) equilibrium model.
Attributes:
| Name | Type | Description |
|---|---|---|
tc, |
(pc, omega)
|
Component critical constants and acentric factors. |
kij |
Array | None
|
Binary interaction matrix ( |
eos |
CubicEOS
|
Cubic equation of state (static; default Peng-Robinson). |
Methods:
| Name | Description |
|---|---|
flash_pt |
Isothermal-isobaric two-phase flash via the cubic EOS. |
bubble_pressure |
Bubble pressure and incipient vapour at fixed |
dew_pressure |
Dew pressure and incipient liquid at fixed |
bubble_temperature |
Bubble temperature and incipient vapour at fixed |
dew_temperature |
Dew temperature and incipient liquid at fixed |
stability |
Michelsen tangent-plane stability of feed |
flash_pt
¶
flash_pt(
t: ArrayLike, p: ArrayLike, z: Array
) -> FlashResult
Isothermal-isobaric two-phase flash via the cubic EOS.
bubble_pressure
¶
bubble_pressure(
t: ArrayLike, x: Array
) -> tuple[Array, Array]
Bubble pressure and incipient vapour at fixed T, x.
dew_pressure
¶
dew_pressure(t: ArrayLike, y: Array) -> tuple[Array, Array]
Dew pressure and incipient liquid at fixed T, y.
bubble_temperature
¶
bubble_temperature(
p: ArrayLike,
x: Array,
*,
t_min: float = 150.0,
t_max: float = 700.0,
) -> tuple[Array, Array]
Bubble temperature and incipient vapour at fixed P, x.
Found by inverting bubble_pressure for the temperature whose bubble
pressure equals P (the saturation pressure rises monotonically with
temperature), then returning the incipient vapour there.
dew_temperature
¶
dew_temperature(
p: ArrayLike,
y: Array,
*,
t_min: float = 150.0,
t_max: float = 700.0,
) -> tuple[Array, Array]
Dew temperature and incipient liquid at fixed P, y.
stability
¶
stability(
t: ArrayLike, p: ArrayLike, z: Array
) -> StabilityResult
Michelsen tangent-plane stability of feed z at (T, P).
GammaPhiModel
dataclass
¶
GammaPhiModel(
activity: ActivityModel,
tc: Array,
pc: Array,
omega: Array,
kij: Array | None,
eos: CubicEOS,
vapor: str,
poynting: bool,
phi_saturation: bool,
)
Gamma-phi equilibrium model: activity-coefficient liquid, EOS/ideal vapour.
Attributes:
| Name | Type | Description |
|---|---|---|
activity |
ActivityModel
|
Liquid activity-coefficient model (a differentiable pytree). |
tc, |
(pc, omega)
|
Component critical constants and acentric factors. |
kij |
Array | None
|
Binary interaction matrix for an EOS vapour ( |
eos |
CubicEOS
|
Cubic EOS used for the saturation reference and (if selected) vapour. |
vapor |
str
|
|
poynting |
bool
|
Include the Poynting correction in the reference (static). |
phi_saturation |
bool
|
Include the saturation fugacity coefficient (static). |
Methods:
| Name | Description |
|---|---|
flash_pt |
Isothermal-isobaric gamma-phi flash. |
bubble_pressure |
Bubble pressure and incipient vapour at fixed |
dew_pressure |
Dew pressure and incipient liquid at fixed |
bubble_temperature |
Bubble temperature and incipient vapour at fixed |
dew_temperature |
Dew temperature and incipient liquid at fixed |
flash_pt
¶
flash_pt(
t: ArrayLike, p: ArrayLike, z: Array
) -> FlashResult
Isothermal-isobaric gamma-phi flash.
bubble_pressure
¶
bubble_pressure(
t: ArrayLike, x: Array
) -> tuple[Array, Array]
Bubble pressure and incipient vapour at fixed T, x.
dew_pressure
¶
dew_pressure(t: ArrayLike, y: Array) -> tuple[Array, Array]
Dew pressure and incipient liquid at fixed T, y.
eos_model
¶
eos_model(
tc: Array,
pc: Array,
omega: Array,
*,
kij: Array | None = None,
eos: CubicEOS = PR,
) -> EOSModel
Construct an EOSModel from component constants.
gamma_phi_model
¶
gamma_phi_model(
activity: ActivityModel,
tc: Array,
pc: Array,
omega: Array,
*,
kij: Array | None = None,
eos: CubicEOS = PR,
vapor: str = "ideal",
poynting: bool = False,
phi_saturation: bool = False,
) -> GammaPhiModel
Construct a GammaPhiModel from an activity model and constants.
Tangent-plane stability¶
stability
¶
Tangent-plane stability analysis for an arbitrary fugacity model.
A mixture of overall composition z is stable as a single phase only if no
trial composition w lowers the Gibbs energy, i.e. if the (modified)
tangent-plane distance
tm(w) = 1 + sum_i W_i (ln W_i + ln coeff_i(w) - d_i - 1), d_i = ln z_i + ln coeff_i(z)
stays non-negative at every stationary point (w = W / sum W). Here
coeff_i is whatever turns a composition into a fugacity: the activity
coefficient gamma_i for a liquid activity model, or the fugacity coefficient
phi_i for an equation of state. Casting the test in terms of a generic
ln_coeff_fn makes one implementation serve both worlds.
The companion of equilibrium: while fugacio.thermo.equilibrium answers
"given that it splits, into what?", this module answers "does it split at all?",
the test that decides whether a feed is one phase, needs a VLE flash, or (for
a liquid activity model with a miscibility gap) needs the liquid-liquid solver in
fugacio.thermo.lle. The most negative trial result also gives an excellent
initial guess for those splits, which those modules consume directly.
Classes:
| Name | Description |
|---|---|
TangentPlaneResult |
Outcome of a tangent-plane stability search. |
Functions:
| Name | Description |
|---|---|
tangent_plane_distance |
Gibbs tangent-plane distance of trial phase |
stability_analysis_general |
Michelsen stability test for a generic |
liquid_stability |
Test a liquid of composition |
TangentPlaneResult
¶
Bases: NamedTuple
Outcome of a tangent-plane stability search.
Attributes:
| Name | Type | Description |
|---|---|---|
stable |
Array
|
|
tpd |
Array
|
The smallest modified tangent-plane distance found across all trials. |
split |
Array
|
The (normalised) trial composition that achieved |
tangent_plane_distance
¶
Gibbs tangent-plane distance of trial phase w relative to feed z.
tpd(w) = sum_i w_i (ln w_i + ln coeff_i(w) - ln z_i - ln coeff_i(z)); a
negative value means the trial phase w lies below the tangent plane at
z and the feed can lower its Gibbs energy by forming it.
stability_analysis_general
¶
stability_analysis_general(
ln_coeff_fn: LnCoeffFn,
z: Array,
trials: Array,
*,
iters: int = 50,
tol: float = 1e-08,
) -> TangentPlaneResult
Michelsen stability test for a generic ln_coeff_fn and trial set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ln_coeff_fn
|
LnCoeffFn
|
Maps a composition to |
required |
z
|
Array
|
Feed composition. |
required |
trials
|
Array
|
Stack of initial trial-phase compositions, shape |
required |
iters
|
int
|
Successive-substitution iterations per trial. |
50
|
tol
|
float
|
Negative- |
1e-08
|
Returns:
| Type | Description |
|---|---|
TangentPlaneResult
|
A |
liquid_stability
¶
liquid_stability(
model: ActivityModel,
t: ArrayLike,
z: Array,
*,
iters: int = 60,
tol: float = 1e-08,
strength: float = 0.9,
) -> TangentPlaneResult
Test a liquid of composition z for splitting into two liquids at T.
Uses the activity coefficients as the ln_coeff_fn and trial phases enriched
toward each pure component. A negative tpd flags a miscibility gap; the
returned split seeds fugacio.thermo.lle.flash_lle.