Skip to content

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 K_i = y_i / x_i.

rachford_rice

Solve the Rachford-Rice equation for the vapour fraction beta.

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 T, x.

dew_pressure_eos

Dew-point pressure and incipient liquid composition at fixed T, y.

stability_analysis

Michelsen tangent-plane stability test for a feed z at (T, P).

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 K_i = y_i / x_i at the solution.

StabilityResult

Bases: NamedTuple

Result of a tangent-plane stability analysis.

Attributes:

Name Type Description
stable Array

True if the feed is single-phase stable.

tpd Array

The smallest (most negative) modified tangent-plane distance found.

wilson_k

wilson_k(
    t: ArrayLike,
    p: ArrayLike,
    tc: Array,
    pc: Array,
    omega: Array,
) -> Array

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

rachford_rice(z: Array, k: Array) -> Array

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 K_i = gamma_i f_i^{0,L} / (phi_i^V P).

bubble_pressure_gamma

Bubble-point pressure and incipient vapour composition at fixed T, x.

dew_pressure_gamma

Dew-point pressure and incipient liquid composition at fixed T, y.

bubble_temperature_gamma

Bubble-point temperature and incipient vapour at fixed P, x.

dew_temperature_gamma

Dew-point temperature and incipient liquid at fixed P, y.

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" (phi^V = 1) or "eos".

'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 x.

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 EOSModel from component constants.

gamma_phi_model

Construct a GammaPhiModel from an activity model and constants.

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 (P, y) at fixed T, x.

dew_pressure

Dew pressure and incipient liquid (P, x) at fixed T, y.

bubble_temperature

Bubble temperature and incipient vapour (T, y) at fixed P, x.

dew_temperature

Dew temperature and incipient liquid (T, x) at fixed P, y.

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.

bubble_temperature

bubble_temperature(
    p: ArrayLike, x: Array
) -> tuple[Array, Array]

Bubble temperature and incipient vapour (T, y) at fixed P, x.

dew_temperature

dew_temperature(
    p: ArrayLike, y: Array
) -> tuple[Array, Array]

Dew temperature and incipient liquid (T, x) at fixed P, 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 (None => zeros).

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 T, x.

dew_pressure

Dew pressure and incipient liquid at fixed T, y.

bubble_temperature

Bubble temperature and incipient vapour at fixed P, x.

dew_temperature

Dew temperature and incipient liquid at fixed P, y.

stability

Michelsen tangent-plane stability of feed z at (T, P).

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 (None => zeros).

eos CubicEOS

Cubic EOS used for the saturation reference and (if selected) vapour.

vapor str

"ideal" (phi^V = 1) or "eos" (static).

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 T, x.

dew_pressure

Dew pressure and incipient liquid at fixed T, y.

bubble_temperature

Bubble temperature and incipient vapour at fixed P, x.

dew_temperature

Dew temperature and incipient liquid at fixed P, y.

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.

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.

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.

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 w relative to feed z.

stability_analysis_general

Michelsen stability test for a generic ln_coeff_fn and trial set.

liquid_stability

Test a liquid of composition z for splitting into two liquids at T.

TangentPlaneResult

Bases: NamedTuple

Outcome of a tangent-plane stability search.

Attributes:

Name Type Description
stable Array

True if the feed is single-phase stable (no negative tm).

tpd Array

The smallest modified tangent-plane distance found across all trials.

split Array

The (normalised) trial composition that achieved tpd, a ready initial guess for the incipient phase when the feed is unstable.

tangent_plane_distance

tangent_plane_distance(
    ln_coeff_fn: LnCoeffFn, z: Array, w: Array
) -> Array

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 ln(coeff_i) (ln gamma or ln phi) at the fixed temperature/pressure of interest.

required
z Array

Feed composition.

required
trials Array

Stack of initial trial-phase compositions, shape (n_trials, n).

required
iters int

Successive-substitution iterations per trial.

50
tol float

Negative-tm threshold below which the feed is declared unstable.

1e-08

Returns:

Type Description
TangentPlaneResult

A TangentPlaneResult.

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.