Liquid-liquid & vapour-liquid-liquid equilibrium¶
Rigorous two-liquid (LLE) and three-phase (VLLE) flashes, heterogeneous azeotropes, and the tangent-plane machinery that decides when a second liquid appears.
Liquid-liquid equilibrium¶
lle
¶
Liquid-liquid equilibrium (LLE): two-liquid flash, tie-lines, and binodals.
Partially miscible liquids split into two phases I and II whose component
fugacities are equal. With an activity-coefficient model that equality is the
isoactivity condition
x_i^I gamma_i(x^I, T) = x_i^II gamma_i(x^II, T),
i.e. K_i = x_i^II / x_i^I = gamma_i^I / gamma_i^II,
closed by the same Rachford-Rice material balance as a vapour-liquid flash, with
the phase fraction psi now the mole fraction in phase II:
sum_i z_i (K_i - 1) / (1 + psi (K_i - 1)) = 0,
x_i^I = z_i / (1 + psi (K_i - 1)), x_i^II = K_i x_i^I.
The catch is the ever-present trivial solution x^I = x^II = z (K = 1); we
avoid it by seeding the iteration from the unstable trial phase found by the
tangent-plane test in fugacio.thermo.stability. The converged split is
differentiable in temperature, feed, and the model parameters via implicit
differentiation of the fixed point, so tie-lines move smoothly under a gradient,
which matters for solvent-selection optimisation and parameter fitting to
mutual-solubility data.
Only an activity model can describe an LLE; Wilson's model is excluded by construction (it has no miscibility gap), so use NRTL, UNIQUAC, or UNIFAC.
Classes:
| Name | Description |
|---|---|
LLEResult |
Result of a two-liquid (LLE) flash. |
Functions:
| Name | Description |
|---|---|
flash_lle |
Split feed |
binary_binodal |
Mutual-solubility (binodal) compositions of a binary at temperature |
tie_line |
One ternary tie-line through feed |
binodal_curve |
Binary binodal branches over a temperature range. |
LLEResult
¶
Bases: NamedTuple
Result of a two-liquid (LLE) flash.
Attributes:
| Name | Type | Description |
|---|---|---|
psi |
Array
|
Mole fraction of the feed in liquid phase |
x_i |
Array
|
Phase |
x_ii |
Array
|
Phase |
k |
Array
|
Distribution ratios |
flash_lle
¶
flash_lle(
model: ActivityModel,
t: ArrayLike,
z: Array,
*,
k_guess: Array | None = None,
tol: float = 1e-12,
max_iter: int = 400,
) -> LLEResult
Split feed z into two liquids at temperature t (isoactivity flash).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
ActivityModel
|
Liquid activity-coefficient model (must admit a miscibility gap). |
required |
t
|
ArrayLike
|
Temperature (K). |
required |
z
|
Array
|
Overall (feed) mole fractions. |
required |
k_guess
|
Array | None
|
Optional initial distribution ratios |
None
|
tol
|
float
|
Fixed-point convergence tolerance. |
1e-12
|
max_iter
|
int
|
Maximum number of fixed-point iterations. |
400
|
Returns:
| Type | Description |
|---|---|
LLEResult
|
An |
LLEResult
|
collapses toward the trivial |
LLEResult
|
|
LLEResult
|
split exists. |
binary_binodal
¶
binary_binodal(
model: ActivityModel,
t: ArrayLike,
*,
feed: ArrayLike = 0.5,
tol: float = 1e-12,
max_iter: int = 400,
) -> tuple[Array, Array]
Mutual-solubility (binodal) compositions of a binary at temperature t.
Returns (x1_phase_I, x1_phase_II), the mole fraction of component 1 in
each conjugate liquid (the tie-line ends). Any feed inside the gap gives the
same pair; the default 50/50 feed sits squarely in a symmetric gap.
tie_line
¶
tie_line(
model: ActivityModel,
t: ArrayLike,
z: Array,
*,
tol: float = 1e-12,
max_iter: int = 400,
) -> tuple[Array, Array, Array]
One ternary tie-line through feed z: (x_raffinate, x_extract, psi).
A thin wrapper over flash_lle returning the two conjugate-phase
compositions and the phase fraction, the unit of a ternary LLE diagram.
binodal_curve
¶
binodal_curve(
model: ActivityModel,
temperatures: Array,
*,
feed: ArrayLike = 0.5,
tol: float = 1e-12,
max_iter: int = 400,
) -> tuple[Array, Array]
Binary binodal branches over a temperature range.
Maps binary_binodal across temperatures and returns
(x1_phase_I, x1_phase_II) arrays aligned with the input, the two branches
of the solubility envelope that meet at the upper (or lower) critical solution
temperature.
Vapour-liquid-liquid equilibrium¶
vlle
¶
Three-phase vapour-liquid-liquid equilibrium (VLLE).
When a vapour coexists with two partially miscible liquids (the heterogeneous
azeotropes that make water/organic distillation and decantation work), neither a
two-phase VLE flash nor an LLE flash alone suffices. VLLE couples them: a vapour
V and two liquids I and II all at equal temperature, pressure, and
component fugacity.
Following Michelsen, both non-reference phases are referred to liquid I through
two sets of K-values,
K_i^V = y_i / x_i^I = gamma_i^I f_i^{0,L} / (phi_i^V P),
K_i^L = x_i^II / x_i^I = gamma_i^I / gamma_i^II,
so the material balance gives x_i^I = z_i / D_i with
D_i = 1 + beta_V (K_i^V - 1) + beta_II (K_i^L - 1). The two phase fractions
(beta_V, beta_II) solve the pair of Rachford-Rice equations
sum_i z_i (K_i^V - 1)/D_i = 0 and sum_i z_i (K_i^L - 1)/D_i = 0 (a small
2x2 Newton with an analytic Jacobian), and the K-values are updated from the
fugacity equalities until consistent.
The flash is seeded from a VLE flash followed by a stability-driven split of its liquid, which is what makes the non-trivial three-phase root reliably found. The converged state is differentiable through the fixed point.
Classes:
| Name | Description |
|---|---|
HeterogeneousAzeotrope |
A binary heterogeneous (two-liquid) azeotrope at fixed pressure. |
VLLEResult |
Result of a three-phase vapour-liquid-liquid flash. |
Functions:
| Name | Description |
|---|---|
flash_vlle |
Isothermal-isobaric three-phase (V-L-L) flash of feed |
heterogeneous_azeotrope |
Binary heterogeneous azeotrope: the boiling temperature of two conjugate liquids. |
HeterogeneousAzeotrope
¶
Bases: NamedTuple
A binary heterogeneous (two-liquid) azeotrope at fixed pressure.
Attributes:
| Name | Type | Description |
|---|---|---|
t |
Array
|
Azeotrope temperature (K). |
x_i |
Array
|
Composition of liquid |
x_ii |
Array
|
Composition of liquid |
y |
Array
|
Common vapour composition in equilibrium with both liquids. |
VLLEResult
¶
Bases: NamedTuple
Result of a three-phase vapour-liquid-liquid flash.
Attributes:
| Name | Type | Description |
|---|---|---|
beta_v |
Array
|
Vapour mole fraction of the feed. |
beta_l1 |
Array
|
Mole fraction in liquid |
beta_l2 |
Array
|
Mole fraction in liquid |
y |
Array
|
Vapour composition. |
x_i |
Array
|
Liquid |
x_ii |
Array
|
Liquid |
three_phase |
Array
|
|
flash_vlle
¶
flash_vlle(
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-11,
max_iter: int = 300,
) -> VLLEResult
Isothermal-isobaric three-phase (V-L-L) flash of feed z at (T, P).
Seeds a vapour/liquid split from fugacio.thermo.gammaphi.flash_pt_gamma
and a liquid/liquid split from fugacio.thermo.lle.flash_lle, then drives
both K-value sets to consistency with a 2x2 Rachford-Rice inner solve. Inspect
three_phase to confirm a genuine three-phase root (otherwise one phase
fraction has collapsed and the relevant two-phase flash applies).
heterogeneous_azeotrope
¶
heterogeneous_azeotrope(
model: ActivityModel,
p: ArrayLike,
tc: Array,
pc: Array,
omega: Array,
*,
eos: CubicEOS = PR,
feed: ArrayLike = 0.5,
t_min: float = 250.0,
t_max: float = 500.0,
tol: float = 1e-09,
max_iter: int = 200,
) -> HeterogeneousAzeotrope
Binary heterogeneous azeotrope: the boiling temperature of two conjugate liquids.
Inside a miscibility gap the two conjugate liquids have equal component
activities (a_i = x_i gamma_i matches across the LLE tie-line), so they
necessarily boil to the same vapour y_i = a_i Psat_i / P. The
heterogeneous azeotrope is the temperature at which that shared vapour's total
pressure sum_i a_i Psat_i reaches the system pressure P, a single,
well-posed scalar root, solved here with the bracketed solver and
differentiable in P and the model parameters.
Returns:
| Type | Description |
|---|---|
HeterogeneousAzeotrope
|
A |
HeterogeneousAzeotrope
|
compositions, and the common vapour). Use a |
HeterogeneousAzeotrope
|
component 1) that lies inside the miscibility gap. |