#!/usr/bin/python3
# -*- coding: utf-8 -*-
'''Pychemqt, Chemical Engineering Process simulator
Copyright (C) 2009-2025, Juan José Gómez Romera <jjgomera@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.'''
###############################################################################
# Lee-Kesler equation of state implementation
###############################################################################
from numpy import exp, r_
from numpy.lib.scimath import log
from scipy.constants import R
from scipy.optimize import fsolve
from lib.compuestos import RhoL_Costald
from lib.bip import Kij
from lib.eos import EoS
from lib.physics import R_atml, factor_acentrico_octano
# Table 1
coef = {
"b1": (0.1181193, 0.2026579),
"b2": (0.265728, 0.331511),
"b3": (0.154790, 0.027655),
"b4": (0.030323, 0.203488),
"c1": (0.0236744, 0.0313385),
"c2": (0.0186984, 0.0503618),
"c3": (0.0, 0.016901),
"c4": (0.042724, 0.041577),
"d1": (0.155488e-4, 0.48736e-4),
"d2": (0.623689e-4, 0.0740336e-4),
"beta": (0.65392, 1.226),
"gamma": (0.060167, 0.03754)}
# Table I from Plöcker
bip = {
"2-3": 1.052,
"2-22": 1.014,
"2-4": 1.113,
"2-23": 1.089,
"2-6": 1.171,
"2-5": 1.155,
"2-8": 1.240,
"2-7": 1.228,
"2-10": 1.304,
"2-38": 1.269,
"2-40": 1.234,
"2-11": 1.367,
"2-12": 1.423,
"2-13": 1.484,
"2-14": 1.533,
"3-22": 0.991,
"3-4": 1.010,
"3-23": 1.002,
"3-6": 1.029,
"3-5": 1.036,
"3-8": 1.064,
"3-7": 1.070,
"3-10": 1.106,
"3-38": 1.081,
"3-40": 1.066,
"3-11": 1.143,
"3-12": 1.165,
"3-13": 1.214,
"3-14": 1.237,
"22-6": 0.998,
"22-40": 1.094,
"22-11": 1.163,
"65-22": 0.948,
"4-23": 0.992,
"4-6": 1.003,
"4-5": 1.003,
"4-8": 1.006,
"4-7": 1.009,
"4-10": 1.047,
"4-38": 1.037,
"4-40": 1.011,
"4-11": 1.067,
"4-12": 1.090,
"4-13": 1.115,
"4-14": 1.139,
"23-6": 1.010,
"23-5": 1.009,
"23-27": 1.006,
"6-5": 1.001,
"6-8": 0.994,
"6-7": 0.998,
"6-10": 1.018,
"6-38": 1.008,
"6-40": 0.999,
"6-11": 1.027,
"6-12": 1.046,
"6-13": 1.064,
"6-14": 1.078,
"8-7": 0.987,
"8-10": 0.996,
"8-38": 0.996,
"8-40": 0.977,
"8-11": 1.004,
"8-12": 1.020,
"8-13": 1.033,
"8-14": 1.045,
"10-38": 0.998,
"10-40": 0.978,
"10-11": 1.008,
"10-12": 1.005,
"10-13": 1.015,
"10-14": 1.025,
"40-38": 0.979,
"40-11": 0.985,
"40-12": 0.987,
"40-82": 0.982,
"40-13": 1.034,
"40-14": 1.047,
"38-11": 0.999,
"38-12": 1.010,
"38-13": 1.021,
"38-14": 1.032,
"11-12": 0.993,
"11-82": 1.002,
"11-13": 1.002,
"11-14": 1.010,
"12-13": 0.993,
"12-14": 0.999,
"13-14": 0.991,
"46-2": 0.977,
"46-22": 1.032,
"46-3": 1.082,
"46-4": 1.177,
"46-23": 1.151,
"46-6": 1.276,
"46-8": 1.372,
"46-10": 1.442,
"46-47": 0.997,
"46-48": 0.987,
"46-98": 0.988,
"46-50": 0.983,
"46-49": 1.110,
"46-110": 1.073,
"46-63": 1.033,
"49-2": 0.975,
"49-3": 0.938,
"49-4": 0.925,
"49-6": 0.955,
"49-5": 0.946,
"49-8": 1.002,
"49-10": 1.018,
"49-38": 1.054,
"49-40": 1.018,
"49-11": 1.058,
"49-12": 1.090,
"49-13": 1.126,
"49-14": 1.160,
"49-50": 0.922,
"49-216": 0.969,
"49-117": 1.069,
"1-2": 1.216,
"1-3": 1.604,
"1-22": 1.498,
"1-4": 1.826,
"1-6": 2.093,
"1-8": 2.335,
"1-10": 2.456,
"1-11": 2.634,
"1-46": 1.080,
"1-48": 1.085,
"1-49": 1.624,
"98-47": 0.985,
"98-2": 1.010,
"98-63": 0.984,
"47-110": 1.057,
"48-2": 0.974,
"971-47": 0.989,
"50-5": 0.947,
"110-2": 1.017,
"62-49": 0.920,
"62-63": 1.152,
"62-117": 0.979}
[docs]
class Lee_Kesler(EoS):
r"""
Corresponding state equation of state of Lee-Kesler
.. math::
\begin{array}[t]{l}
Z = Z^{(0)} + \omega Z^{(1)}\\
Z = \frac{P_rV_r}{T_r} = 1 + \frac{B}{V_r} + \frac{C}{V_r^2} +
\frac{D}{V_r^5} + \frac{c_4}{T_r^3V_r^2}\left(\beta+\frac{\gamma}
{V_r^2}\right)\exp{\left(-\frac{\gamma}{V_r^2}\right)}\\
B = b_1 - \frac{b_2}{T_r} - \frac{b_3}{T_r^2}-\frac{b_4}{T_r^3}\\
C = c_1 - \frac{c_2}{T_r} - \frac{c_3}{T_r^3}\\
D = d_1 - \frac{d_2}{T_r}\\
\end{array}
Using the mixing rules defined by Plöcker [2]_
.. math::
\begin{array}[t]{l}
T_{CM} = \frac{1}{v_{CM}^\nu \sum_j \sum_k Z_j Z_k v_{Cjk}^\nu T_{Cjk}\\
v_{CM} = \sum_j \sum_k Z_j Z_k v_{Cjk}\\
\omega_M = \sum_j Z_j \omega_j\\
P_{CM} = \left(0.2905-0.085\omega_m\right) R \frac{T_{CM}}{v_{CM}\\
\end{array}
with the critical cross parameters
.. math::
\begin{array}[t]{l}
T_{Cjk} = \left(T_{Cj} T_{Ck}\right)^{1/2) k_{jk}\\
v_{Cjk} = \frac{1}{8} \left(v_{Cj}^{1/3} + v_{Ck}^{1/3}\right)^3\\
\end{array}
Examples
--------
Example 1.17 from [3]_, Propane compressibility
>>> from lib.mezcla import Mezcla
>>> mix = Mezcla(1, ids=[8], caudalUnitarioMasico=[1.])
>>> eq = Lee_Kesler(0.8*mix.Tc, 0.4*mix.Pc, mix)
>>> '%0.4f' % (eq.Z[0])
'0.0592'
>>> eq = Lee_Kesler(0.9*mix.Tc, 0.4*mix.Pc, mix)
>>> '%0.4f' % (eq.Z[1])
'0.7520'
>>> eq = Lee_Kesler(1*mix.Tc, 0.4*mix.Pc, mix)
>>> '%0.4f' % (eq.Z[1])
'0.8437'
>>> eq = Lee_Kesler(1.1*mix.Tc, 0.4*mix.Pc, mix)
>>> '%0.4f' % (eq.Z[1])
'0.8939'
>>> eq = Lee_Kesler(1.2*mix.Tc, 0.4*mix.Pc, mix)
>>> '%0.4f' % (eq.Z[1])
'0.9253'
"""
__title__ = "Lee Kesler"
__status__ = "LK"
__doi__ = (
{"autor": "Lee, B.I., Kesler, M.G.",
"title": "A Generalized Thermodynamic Correlation Based on "
"Three-Parameter Corresponding States",
"ref": "AIChE Journal 21(3) (1975) 510-527",
"doi": "10.1002/aic.690210313"},
{"autor": "Plöcker, U., Knapp, H., Prausnitz, J.",
"title": "Calculation of High-Pressure Vapor-Liquid Equilibria from "
"a Corresponding-States Correlation with Emphasis on "
"Asymmetric Mixtures",
"ref": "Ind. Eng. Chem. Process Des. Dev. 17(3) (1978) 324-332",
"doi": "10.1021/i260067a020"},
{"autor": "Walas, S.M.",
"title": "Phase Equilibria in Chemical Engineering",
"ref": "Butterworth, 1985",
"doi": ""},
{"autor": "Joffe, J.",
"title": "Vapor-Liquid Equilibria by the Pseudocritical Method",
"ref": "Ind. Eng. Chem. Fundam. 15(4) (1976) 298-303",
"doi": "10.1021/i160060a013"},
)
[docs]
def __init__(self, T, P, mezcla):
EoS.__init__(self, T, P, mezcla)
self.kij = Kij(mezcla.ids, "LK", bip)
self.Zci = [0.2905-0.085*cmp.f_acent for cmp in self.componente]
self.Vci = [zc*R*cmp.Tc/cmp.Pc.kPa
for zc, cmp in zip(self.Zci, self.componente)]
self.Tci = [cmp.Tc for cmp in self.componente]
self.wi = mezcla._arraylize("f_acent")
# Cross critical coefficient
# Eq 12 from Plöcker
self.Tcij = []
for tci, kiji in zip(self.Tci, self.kij):
tcij = []
for tcj, kij in zip(self.Tci, kiji):
tcij.append((tci*tcj)**0.5*kij)
self.Tcij.append(tcij)
# Eq 13 from Plöcker
self.Vcij = []
for vci in self.Vci:
vcij = []
for vcj in self.Vci:
vcij.append((vci**(1/3)+vcj**(1/3))**3/8)
self.Vcij.append(vcij)
self.Z = self._Z(self.zi, T, P)
self.V = self.Z*R_atml*self.T/self.P.atm # mol/l
self._fug(self.zi, self.zi, T, P)
# self.H_exc = r_[Hv, Hl]
self.x, self.xi, self.yi, self.Ki = self._Flash()
[docs]
def _mix(self, zi):
"""Mixing rules, Eq 20-25"""
# Using the binary interaction parameters defined in [2]_
sumV = 0
sumT = 0
for xj, Vcj, Tcj, kiji in zip(zi, self.Vci, self.Tci, self.kij):
for xk, Vck, Tck, kij in zip(zi, self.Vci, self.Tci, kiji):
sumV += xj*xk*(Vcj**(1/3)+Vck**(1/3))**3
sumT += xj*xk*(Vcj**(1/3)+Vck**(1/3))**3*(Tcj*Tck)**0.5*kij
Vc = sumV/8
Tc = sumT/8/Vc
Pc = (0.2905-0.085*self.mezcla.f_acent)*R_atml*Tc/Vc*101325
return Tc, Pc, Vc
[docs]
def _lib(self, zi=None, T=None, P=None, rho0=None):
Tc, Pc, Vc = self._mix(zi)
Tr = T/Tc
Pr = P/Pc
# Table 1
b1 = 0.1181193, 0.2026579
b2 = 0.265728, 0.331511
b3 = 0.154790, 0.027655
b4 = 0.030323, 0.203488
c1 = 0.0236744, 0.0313385
c2 = 0.0186984, 0.0503618
c3 = 0.0, 0.016901
c4 = 0.042724, 0.041577
d1 = 0.155488e-4, 0.48736e-4
d2 = 0.623689e-4, 0.0740336e-4
beta = 0.65392, 1.226
gamma = 0.060167, 0.03754
Bo = b1[0]-b2[0]/Tr-b3[0]/Tr**2-b4[0]/Tr**3
Co = c1[0]-c2[0]/Tr+c3[0]/Tr**3
Do = d1[0]+d2[0]/Tr
def Vr(V):
Vr = 1 + Bo/V + Co/V**2 + Do/V**5 + c4[0]/Tr**3/V**2 * \
(beta[0]+gamma[0]/V**2) * exp(-gamma[0]/V**2)-Pr*V/Tr
return Vr
Bh = b1[1]-b2[1]/Tr-b3[1]/Tr**2-b4[1]/Tr**3
Ch = c1[1]-c2[1]/Tr+c3[1]/Tr**3
Dh = d1[1]+d2[1]/Tr
def Vrh(V):
Vrh = 1 + Bh/V + Ch/V**2 + Dh/V**5 + c4[1]/Tr**3/V**2 * \
(beta[1]+gamma[1]/V**2) * exp(-gamma[1]/V**2)-Pr*V/Tr
return Vrh
# Used initial values for iteration
Vlo = RhoL_Costald(T, Tc, self.mezcla.f_acent, Vc)
Vgo = R_atml*T/P
vr0v = fsolve(Vr, Vgo)[0]
vrhv = fsolve(Vrh, Vgo)[0]
vr0l = fsolve(Vr, Vlo)[0]
vrhl = fsolve(Vrh, Vlo)[0]
return Tr, Pr, vr0v, vrhv, vr0l, vrhl
[docs]
def _Z(self, zi=None, T=None, P=None, rho0=None):
Tr, Pr, vr0v, vrhv, vr0l, vrhl = self._lib(zi, T, P, rho0)
z0l = Pr*vr0l/Tr
zhl = Pr*vrhl/Tr
z0v = Pr*vr0v/Tr
zhv = Pr*vrhv/Tr
return r_[z0v+self.mezcla.f_acent/factor_acentrico_octano*(zhv-z0v),
z0l+self.mezcla.f_acent/factor_acentrico_octano*(zhl-z0l)]
[docs]
def _fug(self, xi, yi, T, P):
"""Fugacities of component in mixture calculation
Parameters
----------
xi : list
Molar fraction of component in liquid phase, [-]
yi : list
Molar fraction of component in vapor phase, [-]
Returns
-------
tital : list
List with liquid phase component fugacities
titav : list
List with vapour phase component fugacities
"""
Trl, Prl, vr0v_, vrhv_, vr0l, vrhl = self._lib(xi, T, P)
Trv, Prv, vr0v, vrhv, vr0l_, vrhl_ = self._lib(yi, T, P)
Tcl, Pcl, Vcl = self._mix(xi)
Tcv, Pcv, Vcv = self._mix(yi)
z0l = Prl*vr0l/Trl
zhl = Prl*vrhl/Trl
z0v = Prv*vr0v/Trv
zhv = Prv*vrhv/Trv
zl = z0l+self.mezcla.f_acent/factor_acentrico_octano*(zhl-z0l)
zv = z0v+self.mezcla.f_acent/factor_acentrico_octano*(zhv-z0v)
f0v = self._fugacity(0, Trv, Prv, vr0v)
fhv = self._fugacity(1, Trv, Prv, vrhv)
f0l = self._fugacity(0, Trl, Prl, vr0l)
fhl = self._fugacity(1, Trl, Prl, vrhl)
fv = f0v+self.mezcla.f_acent/factor_acentrico_octano*(fhv-f0v)
fl = f0l+self.mezcla.f_acent/factor_acentrico_octano*(fhl-f0l)
# Eq A8
dfvdw = 1/factor_acentrico_octano*(fhv-f0v)
dfldw = 1/factor_acentrico_octano*(fhl-f0l)
H0v = self._Hexc_lib(0, Trv, Prv, vr0v)
Hhv = self._Hexc_lib(1, Trv, Prv, vrhv)
H0l = self._Hexc_lib(0, Trl, Prl, vr0l)
Hhl = self._Hexc_lib(1, Trl, Prl, vrhl)
hv = H0v+self.mezcla.f_acent/factor_acentrico_octano*(Hhv-H0v)
hl = H0l+self.mezcla.f_acent/factor_acentrico_octano*(Hhl-H0l)
# Eq A13
dwZ = []
dzZ = []
for wi in self.wi:
dwZi = []
dzZi = []
for wj in self.wi:
dwZi.append(wj-wi)
dzZi.append(-0.085*(wj-wi))
dwZ.append(dwZi)
dzZ.append(dzZi)
# Eq A12 for both phases
dVcx = []
dVcy = []
for vci in self.Vci:
dVcxi = 0
dVcyi = 0
for xj, yj, vcj in zip(xi, yi, self.Vci):
dVcxi += xj*(vcj-vci)
dVcyi += yj*(vcj-vci)
dVcx.append(2*dVcxi)
dVcy.append(2*dVcyi)
# Eq A9 for both phases
dTcZl = []
dTcZv = []
for x, y, vci, tci, vcij, tcij, dvcx, dvcy in \
zip(xi, yi, self.Vci, self.Tci, self.Vcij, self.Tcij, dVcx, dVcy):
suml = 0
sumv = 0
for vcj, tcj in zip(vcij, tcij):
suml += x*(vcj**0.25*tcj-vci**0.25*tci)
sumv += y*(vcj**0.25*tcj-vci**0.25*tci)
dTcZl.append((2*suml-0.25*Vcl**-0.75*dvcx*Tcl)/Vcl**0.25)
dTcZv.append((2*sumv-0.25*Vcv**-0.75*dvcy*Tcv)/Vcv**0.25)
# Eq A9 for both phases
dPcZl = []
dPcZv = []
for x, y, dzi, dTli, dTvi, dvcx, dvcy in \
zip(xi, yi, dzZ, dTcZl, dTcZv, dVcx, dVcy):
dpli = []
dpvi = []
for dz, dTl, dTv in zip(dzi, dTli, dTvi):
dPli.append(Pcl*(dz/zl+dTl/Tcl-dvcx/Vcl))
dPvi.append(Pcv*(dz/zv+dTv/Tcv-dvcy/Vcv))
dPcZl.append(dPli)
dPcZv.append(dPvi)
print("dPc", dPcZl)
sumTcx = []
sumTcy = []
for i in range(len(xi)):
sumx = 0
sumy = 0
for j, dTcl in enumerate(dTcZl):
if i != j:
sumx += xi[j]*dTcl
sumy += yi[j]*dTcZv[j]
sumTcx.append(sumx)
sumTcy.append(sumy)
sumPcx = []
sumPcy = []
for i in range(len(xi)):
sumx = 0
sumy = 0
for j, dPcl in enumerate(dPcZl):
if i != j:
sumx += xi[j]*dPcl
sumy += yi[j]*dPcZv[j]
sumPcx.append(sumx)
sumPcy.append(sumy)
# print("sumPcx", sumPcx)
sumw = []
for i in range(len(xi)):
sum = 0
for j, dw in enumerate(dwZ[i]):
if i != j:
sum += xi[j]*dw
sumw.append(sum)
# Eq A7
fil = []
for sTc, sPc, sw in zip(sumTcx, sumPcx, sumw):
fil.append(fl-hl/R/T/Tcl*sTc + (zl-1)/Pcl*sPc - dfldw*sw)
fiv = []
for sTc, sPc, sw in zip(sumTcy, sumPcy, sumw):
fiv.append(fv-hv/R/T/Tcv*sTc + (zv-1)/Pcv*sPc - dfvdw*sw)
print("fil", fil)
print("fiv", fiv)
return fil, fiv
[docs]
def _fugacity(self, ref, Tr, Pr, vr):
"""Calculate fugacity coefficient of mixture
Parameters
----------
ref : integer
Index of parameter, 0 for simple fluid and 1 for reference fluid
Tr : float
Reduced temperature
Pr : float
Reduced pressure
vr : float
Reduced volume
"""
b1 = coef["b1"][ref]
b2 = coef["b2"][ref]
b3 = coef["b3"][ref]
b4 = coef["b4"][ref]
c1 = coef["c1"][ref]
c2 = coef["c2"][ref]
c3 = coef["c3"][ref]
c4 = coef["c4"][ref]
d1 = coef["d1"][ref]
d2 = coef["d2"][ref]
gamma = coef["gamma"][ref]
beta = coef["beta"][ref]
z = Pr*vr/Tr
E = c4/(2*Tr**3*gamma)*(
beta + 1 - (beta+1+gamma/vr**2)*exp(-gamma/vr**2))
f = z - 1 - log(z) + (b1 - b2/Tr + b3/Tr**2 + b4/Tr**3)/vr \
+ (c1 - c2/Tr + c3/Tr**3)/2/vr**2 + (d1 + d2)/5/vr**5 + E
return f
[docs]
def _Hexc(self, zi, T, P):
Tr, Pr, vr0v, vrhv, vr0l, vrhl = self._lib(zi, T, P)
z0l = Pr*vr0l/Tr
zhl = Pr*vrhl/Tr
z0v = Pr*vr0v/Tr
zhv = Pr*vrhv/Tr
H0v = self._Hexc_lib(0, Tr, Pr, vr0v)
Hhv = self._Hexc_lib(1, Tr, Pr, vrhv)
H0l = self._Hexc_lib(0, Tr, Pr, vr0l)
Hhl = self._Hexc_lib(1, Tr, Pr, vrhl)
Hv = H0v+mezcla.f_acent/factor_acentrico_octano*(Hhv-H0v)
Hl = H0l+mezcla.f_acent/factor_acentrico_octano*(Hhl-H0l)
return Hv, Hl
[docs]
def _Hexc_lib(self, ref, Tr, Pr, vr):
"""Calculate enthalpy excess of mixture
Parameters
----------
ref : integer
Index of parameter, 0 for simple fluid and 1 for reference fluid
Tr : float
Reduced temperature
Pr : float
Reduced pressure
vr : float
Reduced volume
"""
b1 = coef["b1"][ref]
b2 = coef["b2"][ref]
b3 = coef["b3"][ref]
b4 = coef["b4"][ref]
c1 = coef["c1"][ref]
c2 = coef["c2"][ref]
c3 = coef["c3"][ref]
c4 = coef["c4"][ref]
d1 = coef["d1"][ref]
d2 = coef["d2"][ref]
gamma = coef["gamma"][ref]
beta = coef["beta"][ref]
z = Pr*vr/Tr
E = c4/(2*Tr**3*gamma)*(
beta + 1 - (beta+1+gamma/vr**2)*exp(-gamma/vr**2))
H0 = -Tr*(z - 1 - (b2 + 2*b3/Tr + 3*b4/Tr**2)/Tr/vr
- c2/Tr/2/vr**2 + d2/5/Tr/vr**5 + 3*E)
return H0
# def Cp_Lee_Kesler(self, T, P, fase=None):
# """Método alternativo para el cálculo de la capacidad calorífica
# Procedure API 7D3.6 Pag.711"""
# Tr=self.tr(T)
# if fase==None:
# fase=self.Fase(T, P)
# Cv0, Cvh, vr0, vrh=eos.Lee_Kesler_lib_Cp(T, P, fase)
# B=0.1181193-0.265728/Tr-0.154790/Tr**2-0.030323/Tr**3
# C=0.0236744-0.0186984/Tr
# D=0.155488e-4+0.623689e-4/Tr
# dpdt_0=1/vr0*(1+(0.1181193+0.154790/Tr**2+2*0.030323/Tr**3)/vr0+0.0236744/vr0**2+0.155488e-4/vr0**5-2*0.042724/Tr**3/vr0**2*((0.65392+0.060167/vr0**2)*exp(-0.060167/vr0**2)))
# dpdv_0=-Tr/vr0**2*(1+2*B/vr0+3*C/vr0**2+6*D/vr0**5+0.042724/Tr**3/vr0**2*(3*0.65392+(5-2*(0.65392+0.060167/vr0**2))*0.060167/vr0**2)*exp(-0.060167/vr0**2))
# Cp0=1+Tr*dpdt_0**2/dpdv_0+Cv0
# B=0.2026579-0.331511/Tr-0.027655/Tr**2-0.203488/Tr**3
# C=0.0313385-0.0503618/Tr+0.016901/Tr**3
# D=0.48736e-4+0.0740336e-4/Tr
# dpdt_h=1/vrh*(1+(0.2026579+0.027655/Tr**2+2*0.203488/Tr**3)/vrh+(0.0313385-2*0.016901/Tr**3)/vrh**2+0.48736e-4/vrh**5-2*0.041577/Tr**3/vrh**2*((1.226+0.03754/vrh**2)*exp(-0.03754/vrh**2)))
# dpdv_h=-Tr/vrh**2*(1+2*B/vrh+3*C/vrh**2+6*D/vrh**5+0.041577/Tr**3/vrh**2*(3*1.226+(5-2*(1.226+0.03754/vrh**2))*0.03754/vrh**2)*exp(-0.03754/vrh**2))
# Cph=1+Tr*dpdt_h**2/dpdv_h+Cvh
# Cp_adimensional=Cp0+self.f_acent/factor_acentrico_octano*(Cph-Cp0)
# return unidades.SpecificHeat(self._Cpo(T).JgK-R/self.M*Cp_adimensional, "JgK")
# def Cv_Lee_Kesler(self, T, P, fase=None):
# """Método de cálculo de la capacidad calorífica a volumen constante
# Procedure API 7E1.6 Pag.726"""
# #FIXME: No sale, un factor de 100 tengo que añadir no sé de donde
# Pr=P/self.Pc
# Tr=T/self.Tc
# if fase==None:
# fase=self.Fase(T, P)
# Cpo=self._Cpo(T)
# Cv0, Cvh, vr0, vrh=eos.Lee_Kesler_lib_Cp(Tr, Pr, fase)
# Cv_adimensional=Cv0+self.f_acent/factor_acentrico_octano*(Cvh-Cv0)
# return unidades.SpecificHeat(100*(Cpo.JgK-R/self.M*(1+Cv_adimensional)), "JgK")
# def Cp_Cv_Lee_Kesler(self, T, P):
# """Método de cálculo de la capacidad calorífica a volumen constante
# Procedure API 7E1.6 Pag.726"""
# Cv=self.Cv_Lee_Kesler(T, P.atm)
# Cp=self.Cp_Lee_Kesler(T, P.atm)
# # print Cp.BtulbF, Cv
# return Cp/Cv
# def Fugacidad_Lee_Kesler(self, T, P):
# """Método de cálculo de la fugacidad
# Procedure API 7G1.8 Pag.752"""
# Tr=T/self.Tc
# Pr=P/self.Pc
# f=eos.Lee_Kesler_Fugacidad_lib(Tr, Pr, self.f_acent, self.Fase(T, P))
# return unidades.Pressure(P*exp(f), "atm")
# def Entropia_Lee_Kesler(self, T, P):
# """Método de cálculo de la entropia
# Procedure API 7F1.7 Pag.739"""
# Tr=T/self.Tc
# Pr=P/self.Pc
# S0=self._so(T)
# H_adimensional=eos.Lee_Kesler_Entalpia_lib(Tr, Pr, self.f_acent, self.Fase(T, P.atm))
# f=eos.Lee_Kesler_Fugacidad_lib(Tr, Pr, self.f_acent, self.Fase(T, P.atm))
# S=H_adimensional+f+log(P/101325)
# return unidades.SpecificHeat(S0.JgK-R*S/self.M, "JgK")
# def Hv_Lee_Kesler(self, T):
# """Método alternativo para el cálculo del calor de vaporización haciendo uso de las propiedades críticas
# Procedure API 7C1.16 Pag.680
# Valor en J/mol"""
# Pv=self.Pv_DIPPR(T)
# Tr=T/self.Tc
# Pr=Pv/self.Pc
# H_adimensional_vapor=eos.Lee_Kesler_Entalpia_lib(Tr, Pr, self.f_acent, 1)
# H_adimensional_liquido=eos.Lee_Kesler_Entalpia_lib(Tr, Pr, self.f_acent, 0)
# return unidades.Enthalpy(R*self.Tc/self.M*(H_adimensional_vapor-H_adimensional_liquido), "Jg")
# def RhoG_Lee_Kesler(self, T, P):
# a, b=eos.SRK_lib(self, T)
# Z_srk=eos.Z_Cubic_EoS(T, P, b, a, b, 0, b)
# Vvo=Z_srk[0]*R_atml*T/P
# vr0v, vrhv, vr0l, vrhl=eos.Lee_Kesler_lib(T/self.Tc, P/self.Pc.atm, fase=1, Vvo=Vvo)
# z0v=P/self.Pc.atm*vr0v/T*self.Tc
# zhv=P/self.Pc.atm*vrhv/T*self.Tc
# z=z0v+self.f_acent/factor_acentrico_octano*(zhv-z0v)
# return P/z/R_atml/T
b1=0.1181193, 0.2026579
b2=0.265728, 0.331511
b3=0.154790, 0.027655
b4=0.030323, 0.203488
c1=0.0236744, 0.0313385
c2=0.0186984, 0.0503618
c3=0.0, 0.016901
c4=0.042724, 0.041577
d1=0.155488e-4, 0.48736e-4
d2=0.623689e-4, 0.0740336e-4
beta=0.65392, 1.226
gamma=0.060167, 0.03754
[docs]
def Lee_Kesler_lib(Tr, Pr, fase=2, Vvo=0.0001, Vlo=5):
"""Librería para el cálculo de la EoS de Lee-Kesler
Procedure API 6B1.8 pag 518
Perry pag 2-358
fase: fase para la que se realiza el cálculo
0 - Liquido
1 - Vapor
2 - Ambas"""
Bo=b1[0]-b2[0]/Tr-b3[0]/Tr**2-b4[0]/Tr**3
Co=c1[0]-c2[0]/Tr+c3[0]/Tr**3
Do=d1[0]+d2[0]/Tr
def Vr(V):
return 1+Bo/V+Co/V**2+Do/V**5+c4[0]/Tr**3/V**2*(beta[0]+gamma[0]/V**2)*exp(-gamma[0]/V**2)-Pr*V/Tr
Bh=b1[1]-b2[1]/Tr-b3[1]/Tr**2-b4[1]/Tr**3
Ch=c1[1]-c2[1]/Tr+c3[1]/Tr**3
Dh=d1[1]+d2[1]/Tr
def Vrh(V):
return 1+Bh/V+Ch/V**2+Dh/V**5+c4[1]/Tr**3/V**2*(beta[1]+gamma[1]/V**2)*exp(-gamma[1]/V**2)-Pr*V/Tr
vr0v=vr0l=vrhv=vrhl=None
if fase!=0:
vr0v=fsolve(Vr, Vvo)
vrhv=fsolve(Vrh, Vvo)
elif fase!=1:
vr0l=fsolve(Vr, Vlo)
vrhl=fsolve(Vrh, Vlo)
return vr0v, vrhv, vr0l, vrhl
[docs]
def Z_Lee_Kesler(T, P, mezcla):
"""Factor de compresibilidad según la ecuación de estado de Lee-Kesler"""
a, b, ai, bi, tdadt=SRK_lib(mezcla)
Z_srk=Z_Cubic_EoS(b, a, b, 0, b)
# self.titail, self.titaiv=self.Fugacidad_Cubic_EoS(Z_srk, b, a, ai, bi, 1, 0)
Vvo=Z_srk[0]*R_atml*self.T/self.P.atm
Vlo=Z_srk[1]*R_atml*self.T/self.P.atm
Tmc, Pmc, f_acent, Vmc=Mix_Lee_Kesler(mezcla.fraccion, mezcla.componentes, mezcla.f_acent)
vr0v, vrhv, vr0l, vrhl=Lee_Kesler_lib(T/Tmc, P/Pmc, Vvo, Vlo)
z0l=self.P.atm/Pmc*vr0l/self.T*Tmc
zhl=self.P.atm/Pmc*vrhl/self.T*Tmc
z0v=self.P.atm/Pmc*vr0v/self.T*Tmc
zhv=self.P.atm/Pmc*vrhv/self.T*Tmc
return z0v+f_acent/factor_acentrico_octano*(zhv-z0v), z0l+f_acent/factor_acentrico_octano*(zhl-z0l)
[docs]
def Lee_Kesler_lib_Cp(Tr, Pr, fase=1):
"""Librería para el cálculo de capacidades calorificas, usada a continuación en diferentes funciones
Procedure API 7E1.6 Pag.726"""
#FIXME: No concuerdan mucho los valores de cp y cv con los valores por DIPPR
vr0v, vrhv, vr0l, vrhl=Lee_Kesler_lib(Tr, Pr, fase)
if fase:
E=c4[0]/2/Tr**3/gamma[0]*(beta[0]+1-(beta[0]+1+gamma[0]/vr0v**2)*exp(-gamma[0]/vr0v**2))
Cv0=-2*(b3[0]+3*b4[0]/Tr)/Tr**2/vr0v+3*c3[0]/Tr**3/vr0v**2+6*E
E=c4[1]/2/Tr**3/gamma[1]*(beta[1]+1-(beta[1]+1+gamma[1]/vrhv**2)*exp(-gamma[1]/vrhv**2))
Cvh=-2*(b3[1]+3*b4[1]/Tr)/Tr**2/vrhv+3*c3[1]/Tr**3/vrhv**2+6*E
vr0=vr0v
vrh=vrhv
else:
E=c4[0]/2/Tr**3/gamma[0]*(beta[0]+1-(beta[0]+1+gamma[0]/vr0l**2)*exp(-gamma[0]/vr0l**2))
Cv0=-2*(b3[0]+3*b4[0]/Tr)/Tr**2/vr0l+3*c3[0]/Tr**3/vr0l**2+6*E
E=c4[1]/2/Tr**3/gamma[1]*(beta[1]+1-(beta[1]+1+gamma[1]/vrhl**2)*exp(-gamma[1]/vrhl**2))
Cvh=-2*(b3[1]+3*b4[1]/Tr)/Tr**2/vrhl+3*c3[1]/Tr**3/vrhl**2+6*E
vr0=vr0l
vrh=vrhl
return Cv0, Cvh, vr0, vrh
[docs]
def Lee_Kesler_Entalpia_lib(Tr, Pr, w, fase=1):
"""Librería para el cálculo del factor adimensional de influencia de la presión sobre la temperatura.
Usado en diversos métodos a continuación
eq 7B3.7-1 pag 643"""
vr0v, vrhv, vr0l, vrhl=Lee_Kesler_lib(Tr, Pr, fase)
if fase:
z0=Pr*vr0v/Tr
zh=Pr*vrhv/Tr
E=c4[0]/(2*Tr**3*gamma[0])*(beta[0]+1-(beta[0]+1+gamma[0]/vr0v**2)*exp(-gamma[0]/vr0v**2))
H0=-Tr*(z0-1-(b2[0]+2*b3[0]/Tr+3*b4[0]/Tr**2)/Tr/vr0v-c2[0]/Tr/2/vr0v**2+d2[0]/5/Tr/vr0v**5+3*E)
E=c4[1]/(2*Tr**3*gamma[1])*(beta[1]+1-(beta[1]+1+gamma[1]/vrhv**2)*exp(-gamma[1]/vrhv**2))
Hh=-Tr*(zh-1-(b2[1]+2*b3[1]/Tr+3*b4[1]/Tr**2)/Tr/vrhv-(c2[1]-3*c3[1]/Tr**2)/Tr/2/vrhv**2+d2[1]/5/Tr/vrhv**5+3*E)
H=H0+w/factor_acentrico_octano*(Hh-H0)
else:
z0=Pr*vr0l/Tr
zh=Pr*vrhl/Tr
E=c4[0]/(2*Tr**3*gamma[0])*(beta[0]+1-(beta[0]+1+gamma[0]/vr0l**2)*exp(-gamma[0]/vr0l**2))
H0=-Tr*(z0-1-(b2[0]+2*b3[0]/Tr+3*b4[0]/Tr**2)/Tr/vr0l-c2[0]/Tr/2/vr0l**2+d2[0]/5/Tr/vr0l**5+3*E)
E=c4[1]/(2*Tr**3*gamma[1])*(beta[1]+1-(beta[1]+1+gamma[1]/vrhl**2)*exp(-gamma[1]/vrhl**2))
Hh=-Tr*(zh-1-(b2[1]+2*b3[1]/Tr+3*b4[1]/Tr**2)/Tr/vrhl-(c2[1]-3*c3[1]/Tr**2)/Tr/2/vrhl**2+d2[1]/5/Tr/vrhl**5+3*E)
H=H0+w/factor_acentrico_octano*(Hh-H0)
return H
[docs]
def Lee_Kesler_Fugacidad_lib(Tr, Pr, w, fase=1):
"""Librería para el cálculo de la fugacidad, entropia...
Procedure API 7G1.8 Pag.752"""
vr0, vrh=self.Lee_Kesler_lib(Tr, Pr, fase)
z0=Pr*vr0/Tr
B=b1[0]-b2[0]/Tr-b3[0]/Tr**2-b4[0]/Tr**3
C=c1[0]-c2[0]/Tr+c3[0]/Tr**3
D=d1[0]+d2[0]/Tr
E=c4[0]/2/Tr**3/gamma[0]*(beta[0]+1-(beta[0]+1+gamma[0]/vr0**2)*exp(-gamma[0]/vr0**2))
f0=z0-1-log(z0)+B/vr0+C/2/vr0**2+D/5/vr0**5+E
zh=Pr*vrh/Tr
B=b1[1]-b2[1]/Tr-b3[1]/Tr**2-b4[1]/Tr**3
C=c1[1]-c2[1]/Tr+c3[1]/Tr**3
D=d1[1]+d2[1]/Tr
E=c4[1]/2/Tr**3/gamma[1]*(beta[1]+1-(beta[1]+1+gamma[1]/vrh**2)*exp(-gamma[1]/vrh**2))
fh=zh-1-log(zh)+B/vrh+C/2/vrh**2+D/5/vrh**5+E
return f0+w/factor_acentrico_octano*(fh-f0)
[docs]
def Entalpia_Lee_Kesler(self):
"""Librería para el cálculo del factor adimensional de influencia de la presión sobre la temperatura.
Usado en diversos métodos a continuación
eq 7B3.7-1 pag 643"""
Tmc, Pmc, f_acent, Vmc=self.mezcla.Mix_Lee_Kesler()
a, b, ai, bi, tdadt=self.SRK_lib()
Z_srk=self.Z_Cubic_EoS(b, a, b, 0, b)
Vvo=Z_srk[0]*R_atml*self.T/self.P.atm
Vlo=Z_srk[1]*R_atml*self.T/self.P.atm
vr0, vrh, vr0l, vrhl=self.Lee_Kesler_lib(Tmc, Pmc, Vmc, Vvo, Vlo)
Tr=self.T/Tmc
Pr=self.P.atm/Pmc
z0=Pr*vr0/self.T*Tmc
E=0.041724/(2*Tr**3*0.060167)*(0.65392+1-(0.65392+1+0.060167/vr0**2)*exp(-0.060167/vr0**2))
H0=-Tr*(z0-1-(0.2658728+2*0.154790/Tr+3*0.030323/Tr**2)/Tr/vr0-0.0186984/Tr/2/vr0**2+0.623689e-4/5/Tr/vr0**5+3*E)
zh=Pr*vrh/Tr
E=0.041577/(2*Tr**3*0.03754)*(1.226+1-(1.226+1+0.03754/vrh**2)*exp(-0.03754/vrh**2))
Hh=-Tr*(zh-1-(0.331511+2*0.027655/Tr+3*0.203488/Tr**2)/Tr/vrh-(0.0503618-3*0.016901/Tr**2)/Tr/2/vrh**2+0.0740336e-4/5/Tr/vrh**5+3*E)
return H0+f_acent/factor_acentrico_octano*(Hh-H0)
_all = [Lee_Kesler]
if __name__ == "__main__":
from lib.corriente import Mezcla
from lib import unidades
# mezcla = Mezcla(1, ids=[98], caudalUnitarioMasico=[1.])
# for T in [125, 135, 145, 165, 185, 205]:
# eq = Lee_Kesler(T, 1, mezcla)
# # print(eq.H_exc)
# print(eq.Z)
T = unidades.Temperature(120, "F")
P = unidades.Pressure(485, "psi")
mix = Mezcla(5, caudalMolar=5597, ids=[1, 2, 40, 41],
fraccionMolar=[0.3177, 0.5894, 0.0715, 0.0214])
eq = Lee_Kesler(T, P, mix)
print(eq.x, eq.xi, eq.yi)
# mix = Mezcla(5, caudalMolar=5597, ids=[22],
# fraccionMolar=[1])
# eq = Lee_Kesler(40+273, 9e6, mix)
# # print(eq.x, eq.xi, eq.yi)
# print(eq.Z)