|
48 | 48 | .. autofunction:: chemicals.volume.Amgat |
49 | 49 | .. autofunction:: chemicals.volume.Rackett_mixture |
50 | 50 | .. autofunction:: chemicals.volume.COSTALD_mixture |
| 51 | +.. autofunction:: chemicals.volume.COSTALD_mixture_compressed |
51 | 52 |
|
52 | 53 | Gas Correlations |
53 | 54 | ---------------- |
|
204 | 205 | "volume_VDI_PPDS", |
205 | 206 | ] |
206 | 207 |
|
| 208 | +from math import log1p, log10 |
207 | 209 |
|
208 | | -from fluids.constants import R, root_two |
209 | | -from fluids.numerics import exp, implementation_optimize_tck, log, np, splev, sqrt |
| 210 | +from fluids.constants import R |
| 211 | +from fluids.numerics import cbrt, exp, implementation_optimize_tck, log, np, splev, sqrt |
210 | 212 |
|
211 | 213 | from chemicals.data_reader import data_source, register_df_source |
212 | 214 | from chemicals.utils import mark_numba_incompatible, mixing_simple, os_path_join, source_path |
@@ -862,13 +864,17 @@ def COSTALD(T: float, Tc: float, Vc: float, omega: float) -> float: |
862 | 864 | Saturated Densities of Liquids and Their Mixtures." AIChE Journal |
863 | 865 | 25, no. 4 (1979): 653-663. doi:10.1002/aic.690250412 |
864 | 866 | """ |
865 | | - if T > Tc: |
866 | | - T = Tc |
867 | 867 | Tr = T/Tc |
| 868 | + if Tr > 1.0: |
| 869 | + Tr = 1.0 |
| 870 | + |
868 | 871 | tau = 1.0 - Tr |
| 872 | + if tau < 0.0: |
| 873 | + tau = 0.0 |
| 874 | + |
869 | 875 | tau_cbrt = (tau)**(1.0/3.) |
870 | | - V_delta = (-0.296123 + Tr*(Tr*(-0.0480645*Tr - 0.0427258) + 0.386914))/(Tr - 1.00001) |
871 | | - V_0 = tau_cbrt*(tau_cbrt*(tau_cbrt*(0.190454*tau_cbrt - 0.81446) + 1.43907) - 1.52816) + 1.0 |
| 876 | + V_delta = (-0.296123 + Tr*(0.386914 + Tr*(-0.0427258 - 0.0480645*Tr)))/(Tr - 1.00001) |
| 877 | + V_0 = 1.0 + tau_cbrt*(-1.52816 + tau_cbrt*(1.43907 + tau_cbrt*(-0.81446 + 0.190454*tau_cbrt))) |
872 | 878 | return Vc*V_0*(1.0 - omega*V_delta) |
873 | 879 |
|
874 | 880 |
|
@@ -1182,10 +1188,21 @@ def COSTALD_compressed(T: float, P: float, Psat: float, Tc: float, Pc: float, om |
1182 | 1188 | k = 0.0344483 |
1183 | 1189 | e = exp(f + omega*(g + h*omega)) |
1184 | 1190 | C = j + k*omega |
1185 | | - tau = 1.0 - T/Tc |
| 1191 | + |
| 1192 | + Tr = T/Tc |
| 1193 | + tau = 1.0 - Tr |
| 1194 | + if tau < 0.0: |
| 1195 | + tau = 0.0 |
| 1196 | + |
1186 | 1197 | tau13 = tau**(1.0/3.0) |
1187 | | - B = Pc*(-1.0 + a*tau13 + b*tau13*tau13 + d*tau + e*tau*tau13) |
1188 | | - return Vs*(1.0 - C*log((B + P)/(B + Psat))) |
| 1198 | + |
| 1199 | + # Optimized calculation for B using Horner-like scheme where possible |
| 1200 | + # -1 + a*t + b*t^2 + d*t^3 + e*t^4 where t = tau^(1/3) |
| 1201 | + B = Pc*(-1.0 + tau13*(a + tau13*(b + tau13*(d + e*tau13)))) |
| 1202 | + |
| 1203 | + # Use log1p for better numerical stability when P is close to Psat |
| 1204 | + # log((B+P)/(B+Psat)) == log(1 + (P-Psat)/(B+Psat)) |
| 1205 | + return Vs*(1.0 - C*log1p((P - Psat)/(B + Psat))) |
1189 | 1206 |
|
1190 | 1207 | def Tait(P, P_ref, rho_ref, B, C): |
1191 | 1208 | r"""Calculates compressed-liquid mass density using the Tait |
@@ -1418,6 +1435,57 @@ def Rackett_mixture(T: float, xs: list[float], MWs: list[float], Tcs: list[float |
1418 | 1435 | return (R*bigsum*Zr**(1.0 + (1.0 - Tr)**(2.0/7.0)))*MW |
1419 | 1436 |
|
1420 | 1437 |
|
| 1438 | +def COSTALD_mixture_parameters(xs: list[float], Tcs: list[float], Vcs: list[float], omegas: list[float]) -> tuple[float, float, float]: |
| 1439 | + r"""Shared helper to calculate the COSTALD mixture parameters |
| 1440 | + :math:`T_{cm}`, :math:`V_m`, and :math:`\omega_m` using the |
| 1441 | + COSTALD standard mixing rules. |
| 1442 | +
|
| 1443 | + Parameters |
| 1444 | + ---------- |
| 1445 | + xs : list[float] |
| 1446 | + Mole fractions of each component, [-] |
| 1447 | + Tcs : list[float] |
| 1448 | + Critical temperatures of all fluids, [K] |
| 1449 | + Vcs : list[float] |
| 1450 | + Critical volumes of all fluids (characteristic COSTALD volumes), [m^3/mol] |
| 1451 | + omegas : list[float] |
| 1452 | + Acentric factors (ideally SRK) of all fluids, [-] |
| 1453 | +
|
| 1454 | + Returns |
| 1455 | + ------- |
| 1456 | + Tcm : float |
| 1457 | + Mixture pseudo-critical temperature, [K] |
| 1458 | + Vm : float |
| 1459 | + Mixture characteristic volume, [m^3/mol] |
| 1460 | + omega : float |
| 1461 | + Mixture acentric factor, [-] |
| 1462 | + """ |
| 1463 | + sum_xV = 0.0 |
| 1464 | + sum_xV_1_3 = 0.0 |
| 1465 | + sum_xV_2_3 = 0.0 |
| 1466 | + omega = 0.0 |
| 1467 | + term_Tcm = 0.0 |
| 1468 | + |
| 1469 | + for i in range(len(xs)): |
| 1470 | + xi = xs[i] |
| 1471 | + Vci = Vcs[i] |
| 1472 | + |
| 1473 | + V_1_3 = cbrt(Vci) |
| 1474 | + V_2_3 = V_1_3*V_1_3 |
| 1475 | + |
| 1476 | + sum_xV += xi * Vci |
| 1477 | + sum_xV_1_3 += xi * V_1_3 |
| 1478 | + sum_xV_2_3 += xi * V_2_3 |
| 1479 | + |
| 1480 | + omega += xi * omegas[i] |
| 1481 | + |
| 1482 | + term_Tcm += xi * sqrt(Vci * Tcs[i]) |
| 1483 | + |
| 1484 | + Vm = 0.25 * (sum_xV + 3.0 * sum_xV_2_3 * sum_xV_1_3) |
| 1485 | + Tcm = (term_Tcm * term_Tcm) / Vm |
| 1486 | + return Tcm, Vm, omega |
| 1487 | + |
| 1488 | + |
1421 | 1489 | def COSTALD_mixture(xs: list[float], T: float, Tcs: list[float], Vcs: list[float], omegas: list[float]) -> float: |
1422 | 1490 | r"""Calculate mixture liquid density using the COSTALD CSP method. |
1423 | 1491 |
|
@@ -1468,38 +1536,157 @@ def COSTALD_mixture(xs: list[float], T: float, Tcs: list[float], Vcs: list[float |
1468 | 1536 | Examples |
1469 | 1537 | -------- |
1470 | 1538 | >>> COSTALD_mixture([0.4576, 0.5424], 298., [512.58, 647.29], [0.000117, 5.6e-05], [0.559,0.344]) |
1471 | | - 2.7065887732713534e-05 |
| 1539 | + 2.706589e-05 |
1472 | 1540 |
|
1473 | 1541 | References |
1474 | 1542 | ---------- |
1475 | 1543 | .. [1] Hankinson, Risdon W., and George H. Thomson. "A New Correlation for |
1476 | 1544 | Saturated Densities of Liquids and Their Mixtures." AIChE Journal |
1477 | 1545 | 25, no. 4 (1979): 653-663. doi:10.1002/aic.690250412 |
1478 | 1546 | """ |
1479 | | - N = len(xs) |
1480 | | - sum1, sum2, sum3, omega = 0.0, 0.0, 0.0, 0.0 |
1481 | | - for i in range(N): |
1482 | | - sum1 += xs[i]*Vcs[i] |
1483 | | - p = Vcs[i]**(1.0/3.) |
1484 | | - v = xs[i]*p |
1485 | | - sum2 += v |
1486 | | - sum3 += v*p |
1487 | | - omega += xs[i]*omegas[i] |
1488 | | - |
1489 | | - Vm = 0.25*(sum1 + 3.0*sum2*sum3) |
1490 | | - Vm_inv_root = root_two*(Vm)**-0.5 |
1491 | | - vec = [0.0]*N |
1492 | | - for i in range(N): |
1493 | | - vec[i] = (Tcs[i]*Vcs[i])**0.5*xs[i]*Vm_inv_root |
1494 | | - |
1495 | | - Tcm = 0.0 |
1496 | | - for i in range(N): |
1497 | | - for j in range(i): |
1498 | | - Tcm += vec[i]*vec[j] |
1499 | | - Tcm += 0.5*vec[i]*vec[i] |
| 1547 | + Tcm, Vm, omega = COSTALD_mixture_parameters(xs, Tcs, Vcs, omegas) |
1500 | 1548 | return COSTALD(T, Tcm, Vm, omega) |
1501 | 1549 |
|
1502 | 1550 |
|
| 1551 | +def COSTALD_mixture_compressed(xs: list[float], T: float, Tcs: list[float], Vcs: list[float], omegas: list[float], P: float, Psat: float | None = None) -> float: |
| 1552 | + r"""Calculate compressed mixture liquid density using the COSTALD-Tait CSP method, |
| 1553 | + by Hankinson, Brobst, and Thomson [1]_, corresponding to API Technical Data Book Procedure 6A3.4 [2]_. |
| 1554 | +
|
| 1555 | + The molar volume of the compressed liquid mixture is calculated using the |
| 1556 | + Tait equation, where the saturation volume :math:`V_s` is obtained via the |
| 1557 | + standard COSTALD mixture rules (API Procedure 6A3.2). |
| 1558 | +
|
| 1559 | + .. math:: |
| 1560 | + V = V_s \left( 1 - C \ln \frac{B + P}{B + P_{sat}}\right) |
| 1561 | +
|
| 1562 | + The parameters :math:`B` and :math:`C` are generalized functions of the |
| 1563 | + mixture acentric factor :math:`\omega_m` and reduced temperature :math:`T_r = T/T_{cm}`: |
| 1564 | +
|
| 1565 | + .. math:: |
| 1566 | + \frac{B}{P_{cm}} = -1 + a(1-T_r)^{1/3} + b(1-T_r)^{2/3} + d(1-T_r) + e(1-T_r)^{4/3} |
| 1567 | +
|
| 1568 | + .. math:: |
| 1569 | + e = \exp(f + g\omega_{m} + h \omega_{m}^2) |
| 1570 | +
|
| 1571 | + .. math:: |
| 1572 | + C = j + k \omega_{m} |
| 1573 | +
|
| 1574 | + If the saturation pressure :math:`P_{sat}` is not provided, it is estimated |
| 1575 | + using the Generalized Riedel vapor pressure equation using mixture critical properties: |
| 1576 | +
|
| 1577 | + .. math:: |
| 1578 | + \log_{10} \frac{P_{sat}}{P_{cm}} = P_{rm}^{(0)} + \omega_m P_{rm}^{(1)} |
| 1579 | +
|
| 1580 | + .. math:: |
| 1581 | + P_{rm}^{(0)} = 5.8031817 \log_{10} T_r + 0.07608141 \alpha |
| 1582 | +
|
| 1583 | + .. math:: |
| 1584 | + P_{rm}^{(1)} = 4.86601 \beta |
| 1585 | +
|
| 1586 | + .. math:: |
| 1587 | + \alpha = 35.0 - \frac{36.0}{T_r} - 96.736 \log_{10} T_r + T_r^6 |
| 1588 | +
|
| 1589 | + .. math:: |
| 1590 | + \beta = \log_{10} T_r + 0.03721754 \alpha |
| 1591 | +
|
| 1592 | + The mixture critical properties :math:`T_{cm}`, :math:`V_{m}`, and :math:`\omega_m` |
| 1593 | + are calculated using the COSTALD mixing rules: |
| 1594 | +
|
| 1595 | + .. math:: |
| 1596 | + V_m = 0.25\left[ \sum_i x_i V_i^* + 3\left(\sum_i x_i (V_i^*)^{2/3}\right)\left(\sum_i x_i (V_i^*)^{1/3}\right)\right] |
| 1597 | +
|
| 1598 | + .. math:: |
| 1599 | + V_{ij}^* T_{cij} = \sqrt{V_i^* T_{ci} V_j^* T_{cj}} |
| 1600 | +
|
| 1601 | + .. math:: |
| 1602 | + T_{cm} = \frac{\sum_i\sum_j x_i x_j (V_{ij}^* T_{cij})}{V_m} |
| 1603 | +
|
| 1604 | + .. math:: |
| 1605 | + \omega_m = \sum_i x_i \omega_i |
| 1606 | +
|
| 1607 | + .. math:: |
| 1608 | + P_{cm} = \frac{(0.291 - 0.080\omega_m)RT_{cm}}{V_m} |
| 1609 | +
|
| 1610 | + Parameters |
| 1611 | + ---------- |
| 1612 | + xs : list |
| 1613 | + Mole fractions of each component [-] |
| 1614 | + T : float |
| 1615 | + Temperature of fluid [K] |
| 1616 | + Tcs : list |
| 1617 | + Critical temperature of fluids [K] |
| 1618 | + Vcs : list |
| 1619 | + Critical volumes of fluids (characteristic COSTALD volume) [m^3/mol] |
| 1620 | + omegas : list |
| 1621 | + Acentric factor (ideally SRK) of all fluids [-] |
| 1622 | + P : float |
| 1623 | + Pressure of fluid [Pa] |
| 1624 | + Psat : float, optional |
| 1625 | + Saturation pressure of the mixture [Pa]. If not provided, it is estimated |
| 1626 | + using the Generalized Riedel equation. |
| 1627 | +
|
| 1628 | + Returns |
| 1629 | + ------- |
| 1630 | + V_dense : float |
| 1631 | + Compressed liquid mixture molar volume [m^3/mol] |
| 1632 | +
|
| 1633 | + Notes |
| 1634 | + ----- |
| 1635 | + The constants for the Tait parameter correlations are: |
| 1636 | + a = -9.070217, b = 62.45326, d = -135.1102, f = 4.79594, |
| 1637 | + g = 0.250047, h = 1.14188, j = 0.0861488, k = 0.0344483. |
| 1638 | +
|
| 1639 | + This method is generally accurate to within 1% for defined hydrocarbon mixtures |
| 1640 | + below Tr = 0.95. |
| 1641 | +
|
| 1642 | + Examples |
| 1643 | + -------- |
| 1644 | + >>> Tcs = [305.3278, 617.594] |
| 1645 | + >>> Vcs = [0.00014576928794529767, 0.0006192229409547785] |
| 1646 | + >>> omegas = [0.0983, 0.4916] |
| 1647 | + >>> xs = [0.2, 0.8] |
| 1648 | + >>> T = 344.26111 |
| 1649 | + >>> P = 20684271.8795 |
| 1650 | + >>> COSTALD_mixture_compressed(xs, T, Tcs, Vcs, omegas, P) |
| 1651 | + 0.0001716710 |
| 1652 | +
|
| 1653 | + References |
| 1654 | + ---------- |
| 1655 | + .. [1] Thomson, G. H., K. R. Brobst, and R. W. Hankinson. "An Improved |
| 1656 | + Correlation for Densities of Compressed Liquids and Liquid Mixtures." |
| 1657 | + AIChE Journal 28, no. 4 (July 1, 1982): 671-76. doi:10.1002/aic.690280420 |
| 1658 | + .. [2] API Technical Data Book, Procedure 6A3.4 "Computer Method for the |
| 1659 | + Liquid Densities of Compressed Hydrocarbon Mixtures of Defined Composition." |
| 1660 | + """ |
| 1661 | + Tcm, Vm, omega = COSTALD_mixture_parameters(xs, Tcs, Vcs, omegas) |
| 1662 | + Vs = COSTALD(T, Tcm, Vm, omega) |
| 1663 | + |
| 1664 | + # Calculate Pcm and then Psat if needed |
| 1665 | + Zcm = 0.291 - 0.080 * omega |
| 1666 | + Pcm = Zcm * R * Tcm / Vm |
| 1667 | + |
| 1668 | + if Psat is None: |
| 1669 | + Trm = T / Tcm |
| 1670 | + |
| 1671 | + # Generalized Riedel Vapor Pressure Equation (API 6A3.4-12 to 16) |
| 1672 | + if Trm > 0: |
| 1673 | + log_Trm = log10(Trm) |
| 1674 | + alpha = 35.0 - 36.0 / Trm - 96.736 * log_Trm + Trm**6 |
| 1675 | + beta = log_Trm + 0.03721754 * alpha |
| 1676 | + |
| 1677 | + Prm_0 = 5.8031817 * log_Trm + 0.07608141 * alpha |
| 1678 | + Prm_1 = 4.86601 * beta |
| 1679 | + |
| 1680 | + log_Prm = Prm_0 + omega * Prm_1 |
| 1681 | + Prm = 10.0**log_Prm |
| 1682 | + |
| 1683 | + Psat = Prm * Pcm |
| 1684 | + else: |
| 1685 | + Psat = 0.0 |
| 1686 | + |
| 1687 | + return COSTALD_compressed(T, P, Psat, Tcm, Pcm, omega, Vs) |
| 1688 | + |
| 1689 | + |
1503 | 1690 | ### Gases |
1504 | 1691 |
|
1505 | 1692 |
|
|
0 commit comments