Chemical Equilibrium Overview¶
Equilibrium at fixed temperature and pressure¶
For a closed multicomponent system at fixed \(T\), \(P\), and total component amounts, the equilibrium state minimizes total Gibbs energy subject to the component material balances. For every component present in coexisting phases, the stationarity conditions are
Chemical potential is related to fugacity by
so equality of chemical potentials is equivalent to
These conditions follow from constrained Gibbs-energy minimization. The derivation and its computational consequences are developed in Michelsen and Mollerup, chapters 1 and 8, and in Kontogeorgis and Folas, chapter 1. See the bibliographic records.
Necessary conditions are not enough¶
Equal fugacities establish stationarity, not global stability. A solver can converge to a local stationary point, a metastable state, or the algebraic trivial solution in which nominally distinct phases have the same composition. This becomes especially important near critical conditions, where phase compositions and roots coalesce.
For an equation-of-state \(\phi\)-\(\phi\) formulation, a dimensionless tangent-plane distance for a normalized trial composition \(\boldsymbol{w}\) can be written
The reference phase is stable only if the global minimum of TPD over all admissible trial compositions is nonnegative, within a tolerance chosen for the model and dtype. A materially negative minimum identifies a composition direction that lowers Gibbs energy. This criterion and practical minimization algorithms follow Michelsen's stability analysis (Part I).
Numerically, a nonnegative minimum is meaningful only if the minimization itself converged and explored the relevant composition basins. Zero compositions require careful limiting treatment because the logarithms are singular.
Stability in torch-flash¶
import torch
from torch_flash import (
ChemicalState,
component_set,
configure,
peng_robinson_1978,
tangent_plane_stability,
)
runtime = configure(device="cpu", dtype=torch.float64)
model = peng_robinson_1978(component_set(("methane", "n_butane")))
state = ChemicalState(
runtime.tensor(450.0),
runtime.tensor(3.0e6),
runtime.tensor([0.50, 0.50]),
)
stability = tangent_plane_stability(model, state)
print(stability.stable)
print(stability.minimum_tpd)
print(stability.trial_composition)
print(stability.converged, stability.iterations)
two_phase_flash performs this test by default and returns one homogeneous
phase when the test is stable. When a branch is already known—for example,
during a controlled continuation study—the stability test can be disabled,
but that changes the scientific question from phase discovery to a
branch-constrained split.
What to verify¶
For any equilibrium result:
- check solver convergence and the reported residual;
- reconstruct the overall material balance;
- compare component fugacities between phases;
- reject nonpositive or nonnormalized compositions;
- distinguish phase-root selection from physical phase identification; and
- perform a stability analysis when the phase count was not externally established.
The next pages apply these conditions to two phases and to a fixed multiphase count.