Class SpinodalDecompositionDetector

java.lang.Object
neqsim.util.nucleation.SpinodalDecompositionDetector

public class SpinodalDecompositionDetector extends Object
Detects spinodal decomposition conditions in thermodynamic systems.

Spinodal decomposition occurs when the system is inside the spinodal curve (thermodynamically unstable region), where the second derivative of the Gibbs free energy with respect to composition becomes negative. In this regime, phase separation is barrierless — any infinitesimal fluctuation grows spontaneously, unlike classical nucleation which requires overcoming a free energy barrier.

The phase transition regions are:

  • Stable (outside binodal): Single-phase, no phase transition possible
  • Metastable (between binodal and spinodal): Classical nucleation applies — phase transition requires a nucleation barrier. Use ClassicalNucleationTheory.
  • Unstable (inside spinodal): Spinodal decomposition — barrierless, spontaneous phase separation with characteristic wavelength selection.

This class uses the EOS-computed Helmholtz free energy derivatives to determine the stability of the mixture. For a binary mixture, spinodal decomposition occurs when:

$$\frac{\partial^2 A}{\partial n_i \partial n_j} \leq 0$$ for the unstable component pair (i,j)

For multicomponent systems, the full Hessian matrix of the Helmholtz free energy with respect to composition is computed, and the minimum eigenvalue is checked.

Usage:


// Flash the system first
ThermodynamicOperations ops = new ThermodynamicOperations(system);
ops.TPflash();
system.initProperties();

SpinodalDecompositionDetector detector = new SpinodalDecompositionDetector(system);
detector.analyze();

if (detector.isInsideSpinodal()) {
    // Barrierless phase separation — spinodal decomposition
    double wavelength = detector.getDominantWavelength();
} else if (detector.isMetastable()) {
    // Classical nucleation applies
    ClassicalNucleationTheory cnt = ...;
} else {
    // Stable single phase
}

References:

  • Cahn, J.W. and Hilliard, J.E. (1958). Free Energy of a Nonuniform System. I. Interfacial Free Energy. J. Chem. Phys. 28, 258-267.
  • Binder, K. (1987). Theory of first-order phase transitions. Rep. Prog. Phys. 50, 783-859.
  • Michelsen, M.L. (1982). The isothermal flash problem. Part I. Stability. Fluid Phase Equilib. 9, 1-19.
Version:
1.0
Author:
esol
  • Field Details

    • system

      private SystemInterface system
      The NeqSim thermodynamic system.
    • phaseIndex

      private int phaseIndex
      Phase index to analyze (default 0 = first phase).
    • stabilityState

      Stability state of the system.
    • minEigenvalue

      private double minEigenvalue
      Minimum eigenvalue of the Hessian matrix of the Helmholtz free energy.
    • hessianMatrix

      private double[][] hessianMatrix
      The Hessian matrix d2A/(dNi*dNj) — second derivatives of Helmholtz free energy with respect to mole numbers.
    • unstableComponentI

      private int unstableComponentI
      The component pair (i,j) with the most negative Hessian element.
    • unstableComponentJ

      private int unstableComponentJ
      The component pair (i,j) with the most negative Hessian element.
    • unstableComponentPair

      private String unstableComponentPair
      Name of the most unstable component pair.
    • dominantWavelength

      private double dominantWavelength
      Estimated dominant wavelength of spinodal decomposition in m. Only valid when inside the spinodal.
    • stabilityMargin

      private double stabilityMargin
      Stability margin: positive means stable, negative means unstable. Equal to the minimum eigenvalue of the Hessian.
    • analyzed

      private boolean analyzed
      Whether analysis has been performed.
  • Constructor Details

    • SpinodalDecompositionDetector

      public SpinodalDecompositionDetector(SystemInterface system)
      Creates a SpinodalDecompositionDetector for the given thermodynamic system.

      The system should be initialized (flash + initProperties) before analysis.

      Parameters:
      system - the NeqSim thermodynamic system
  • Method Details

    • setPhaseIndex

      public void setPhaseIndex(int phaseIndex)
      Sets the phase index to analyze.
      Parameters:
      phaseIndex - the phase index (0-based)
    • analyze

      public void analyze()
      Performs the spinodal stability analysis.

      Computes the Hessian matrix of the Helmholtz free energy with respect to mole numbers using the EOS component derivatives (dFdNdN). Then checks the eigenvalues to determine stability.

    • analyzePureComponent

      private void analyzePureComponent(PhaseInterface phase)
      Analyzes mechanical stability for a pure component.

      For a pure substance, the spinodal is defined by (dP/dV)_T = 0. If the system is at a density where (dP/dV)_T is positive, the phase is mechanically unstable.

      Parameters:
      phase - the phase to analyze
    • analyzeFugacityBased

      private void analyzeFugacityBased(PhaseInterface phase, int numComp)
      Performs a fugacity-based stability check as fallback when EOS derivatives are not available.

      This is a simplified check: if the system has two phases and the fugacity coefficients indicate the gas phase is significantly supersaturated relative to the liquid, the system may be inside or near the spinodal.

      Parameters:
      phase - the phase to analyze
      numComp - number of components
    • findMinEigenvalue

      private double findMinEigenvalue(double[][] matrix, int n)
      Finds the minimum eigenvalue of a symmetric matrix using the Jacobi eigenvalue algorithm.

      For small matrices (typical for thermodynamic systems with 2-20 components), this is efficient and robust.

      Parameters:
      matrix - the symmetric matrix
      n - matrix dimension
      Returns:
      the minimum eigenvalue
    • estimateDominantWavelength

      private void estimateDominantWavelength(PhaseInterface phase)
      Estimates the dominant wavelength of spinodal decomposition using the Cahn-Hilliard theory.

      The dominant wavelength is:

      $$\lambda_{max} = 2\pi \sqrt{\frac{-2\kappa}{d^2 f / dx^2}}$$

      where kappa is the gradient energy coefficient (related to surface tension and interfacial thickness) and d2f/dx2 is the second derivative of the free energy density with respect to composition.

      Parameters:
      phase - the phase to analyze
    • isInsideSpinodal

      public boolean isInsideSpinodal()
      Returns whether the system is inside the spinodal (thermodynamically unstable).
      Returns:
      true if the system is unstable (spinodal decomposition will occur)
    • isMetastable

      public boolean isMetastable()
      Returns whether the system is metastable (between binodal and spinodal).
      Returns:
      true if the system is metastable (classical nucleation applies)
    • isStable

      public boolean isStable()
      Returns whether the system is thermodynamically stable (single phase).
      Returns:
      true if the system is stable
    • getStabilityState

      Returns the stability state of the system.
      Returns:
      the stability state enum
    • getMinEigenvalue

      public double getMinEigenvalue()
      Returns the minimum eigenvalue of the Hessian matrix.

      Positive = stable, negative = inside spinodal. The magnitude indicates the distance from the spinodal boundary.

      Returns:
      minimum eigenvalue
    • getStabilityMargin

      public double getStabilityMargin()
      Returns the stability margin.

      Positive = stable (distance from spinodal), negative = unstable (depth inside spinodal).

      Returns:
      stability margin
    • getHessianMatrix

      public double[][] getHessianMatrix()
      Returns the Hessian matrix d2A/(dNi*dNj).
      Returns:
      the Hessian matrix
    • getUnstableComponentPair

      public String getUnstableComponentPair()
      Returns the name of the most unstable component pair.
      Returns:
      component pair string (e.g., "methane / n-heptane")
    • getDominantWavelength

      public double getDominantWavelength()
      Returns the estimated dominant wavelength of spinodal decomposition.

      This is the characteristic length scale of the concentration fluctuations that grow fastest during spinodal decomposition. Only valid when the system is inside the spinodal.

      Returns:
      dominant wavelength in m
    • isAnalyzed

      public boolean isAnalyzed()
      Returns whether the analysis has been performed.
      Returns:
      true if analyzed
    • getRecommendation

      public String getRecommendation()
      Returns a recommendation for which nucleation model to use.
      Returns:
      recommendation string
    • toMap

      public Map<String,Object> toMap()
      Returns all results as a Map for serialization.
      Returns:
      map of result names to values
    • toJson

      public String toJson()
      Returns a JSON report of all results.
      Returns:
      JSON string
    • toString

      public String toString()
      Overrides:
      toString in class Object