Skip to content

polykin.thermo.flash¤

flash2_PT ¤

flash2_PT(
    F: float,
    z: FloatVector,
    P: float,
    T: float,
    Kcalc: Callable[
        [float, float, FloatVector, FloatVector],
        FloatVector,
    ],
    *,
    beta0: float | None = None,
    maxiter: int = 50,
    atol_inner: float = 1e-09,
    rtol_outer: float = 1e-06,
    alpha_outer: float = 1.0
) -> FlashResult

Solve a 2-phase flash problem at given pressure and temperature.

References

  • M.L. Michelsen and J. Mollerup, "Thermodynamic models: Fundamentals and computational aspects", Tie-Line publications, 2nd edition, 2007.
PARAMETER DESCRIPTION
F

Feed mole flowrate (mol/s).

TYPE: float

z

Feed mole fractions (mol/mol).

TYPE: FloatVector

T

Temperature (K).

TYPE: float

P

Pressure (Pa).

TYPE: float

Kcalc

Function to calculate K-values, with signature Kcalc(T, P, x, y).

TYPE: Callable[[float, float, FloatVector, FloatVector], FloatVector]

beta0

Initial guess for vapor phase fraction.

TYPE: float | None DEFAULT: None

maxiter

Maximum number of iterations.

TYPE: int DEFAULT: 50

atol_inner

Absolute tolerance for the inner beta-loop.

TYPE: float DEFAULT: 1e-09

rtol_outer

Relative tolerance for the outer K-values loop.

TYPE: float DEFAULT: 1e-06

alpha_outer

Relaxation factor for the outer K-values loop.

TYPE: float DEFAULT: 1.0

RETURNS DESCRIPTION
FlashResult

Flash result.

Source code in src/polykin/thermo/flash/vle.py
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
def flash2_PT(
    F: float,
    z: FloatVector,
    P: float,
    T: float,
    Kcalc: Callable[[float, float, FloatVector, FloatVector], FloatVector],
    *,
    beta0: float | None = None,
    maxiter: int = 50,
    atol_inner: float = 1e-9,
    rtol_outer: float = 1e-6,
    alpha_outer: float = 1.0,
) -> FlashResult:
    r"""Solve a 2-phase flash problem at given pressure and temperature.

    **References**

    *  M.L. Michelsen and J. Mollerup, "Thermodynamic models: Fundamentals and
       computational aspects", Tie-Line publications, 2nd edition, 2007.

    Parameters
    ----------
    F : float
        Feed mole flowrate (mol/s).
    z : FloatVector
        Feed mole fractions (mol/mol).
    T : float
        Temperature (K).
    P : float
        Pressure (Pa).
    Kcalc : Callable[[float, float, FloatVector, FloatVector], FloatVector]
        Function to calculate K-values, with signature `Kcalc(T, P, x, y)`.
    beta0 : float | None
        Initial guess for vapor phase fraction.
    maxiter : int
        Maximum number of iterations.    
    atol_inner : float
        Absolute tolerance for the inner beta-loop.
    rtol_outer : float
        Relative tolerance for the outer K-values loop.
    alpha_outer : float
        Relaxation factor for the outer K-values loop.

    Returns
    -------
    FlashResult
        Flash result.
    """

    method = "2-Phase PT Flash"
    message = ""
    success = False

    # Initial guesses
    z = z/z.sum()
    x = z
    y = z
    beta = np.nan
    K = Kcalc(T, P, z, z)

    for _ in range(maxiter):

        # Find beta
        sol = solve_Rachford_Rice(K, z, beta0, maxiter, atol_inner)
        beta = sol.beta
        if not sol.success:
            message = f"Inner Rachford-Rice loop did not converge after {maxiter} iterations. Solution: {sol}."
            break

        # Compute x, y
        x = z/(1 + beta*(K - 1))
        y = K*x
        x /= x.sum()
        y /= y.sum()

        # Update K
        K_old = K.copy()
        K_new = Kcalc(T, P, x, y)

        # Check convergence
        k0 = min(k for k in K_new if k > 0)
        if np.allclose(K_new, K_old, atol=k0*rtol_outer):
            success = True
            message = "Outer loop converged within specified tolerance."
            break
        else:
            K = exp(alpha_outer*log(K_new) + (1 - alpha_outer)*log(K_old))
            beta0 = beta

    else:
        message = f"Outer loop did not converge after {maxiter} iterations."

    # Overall balance
    V = F*beta
    L = F - V

    return FlashResult(method, success, message, T, P, F, L, V, beta, z, x, y, K)