Source code for lib.newComponent.wen

#!/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/>.'''


from lib import unidades
from lib.compuestos import atomic_decomposition
from lib.newComponent._base import GroupContribution


[docs] class Wen(GroupContribution): """ Group contribution for definition of unknown component using the Wen-Qiang procedure (2001). This method is able to calculate the critical properties. The resulting instance has all the necessary properties to use in PFD as a predefined compound, using general properties for calculation of other mandatory properties don't defined by the method. Parameters ---------- group : array List with group index contribution : float List with group count ocurrences M: float, optional Molecular weight, [-] Tb : float, optional Normal boiling temperature, [K] SG: float, optional Specific gravity, [-] Notes ----- Tb, M and SG are optional input, anyway know them improve the estimation Examples -------- Example 1 in [1]_, Tc of n-Butylaniline The last group containing a carbon-adjacent atom pair has a typo, must be =C<[r]/>N- >>> cmp = Wen(Tb=513.9, group=[1, 11, 18, 87, 96, 99, 135], ... contribution=[1, 5, 1, 10, 2, 1, 1]) >>> "%0.3f" % cmp.Tc '721.275' >>> cmp.formula 'C10H15N' Example 2 in [1]_, Pc of Benzoic acid >>> cmp = Wen(group=[87, 93, 96, 114], contribution=[10, 1, 1, 1]) >>> "%0.3f" % cmp.Pc.MPa '4.547' Example 3 in [1]_, Vc of chloropentafluorobenzene >>> cmp = Wen(group=[96, 101, 102], contribution=[12, 5, 1]) >>> "%0.1f" % (cmp.Vc.ccg*cmp.M) '374.6' >>> cmp.formula 'C6F5Cl' """ __title__ = "Wen-Qiang (2001)" __doi__ = { 1: {"autor": "Wen, X., Quiang, Y.", "title": "A New Group Contribution Method for Estimating Critical " "Properties of Orgnic Compounds", "ref": "Ind. Eng. Chem. Res. 40(26) (2001) 6245-6250.", "doi": "10.1021/ie010374g"}} __coeff__ = { # Table III "tc": [-2.885, 2.424, 0.048, 22.766, -3.404, 2.495, 2.275, 2.602, -1.601, 0.000, 35.848, 2.124, -0.708, 22.576, -3.085, 1.578, -0.030, 2.256, -2.322, 2.549, 13.769, 20.882, 25.177, 1.934, -3.377, 0.000, 0.000, -1.765, -3.163, -5.588, 0.830, 11.483, 2.183, -7.415, 0.007, -0.651, 0.178, -4.384, -0.502, 6.664, 9.639, 2.262, -1.648, 0.000, 5.838, 2.218, 10.659, -2.228, 0.017, 3.541, -0.748, -1.248, 9.056, 4.564, 2.737, 0.007, 1.136, -0.008, 13.166, -0.009, -2.298, 9.242, 1.143, -11.918, 0.007, -0.953, 0.000, 0.000, 5.993, 3.162, 0.000, 2.707, 3.180, 6.070, 13.625, 7.842, 5.897, 0.004, -781.237, 2.367, 0.000, -7.274, 3.798, 5.571, 2.446, -1.223, 0.754, 2.852, 2.013, 7.937, 14.661, 10.141, -0.603, 2.172, 0.000, 0.009, 4.660, -2.465, 3.701, 1.700, 6.344, -5.547, 5.600, 12.840, 28.472, 10.144, 18.220, 15.436, 20.655, 11.326, 13.047, 34.349, 35.591, 34.476, 35.009, 7.041, 9.909, 9.193, 1.933, 16.126, 23.640, 9.697, 15.542, 3.835, 11.598, 4.679, 22.777, 18.847, 8.357, 0.003, 11.032, 14.462, 16.658, 1.251, 15.982, 17.609, 16.935, 16.840, 0.001, 0.004], "Pc": [9.361, 4.035, 2.682, 7.267, 9.548, 3.297, 1.286, 2.797, 5.280, 0.000, 2.517, 1.454, 0.314, 5.065, 9.483, 2.239, 0.038, 1.497, 3.545, 1.851, 1.707, 1.517, 3.345, 0.460, 0.358, 0.000, 6.274, 1.087, 0.187, 3.501, 2.770, 1.318, -0.282, 0.141, 6.690, -0.032, -0.013, 0.214, 2.885, 2.880, 2.604, 3.648, 4.393, 0.000, 2.686, 0.731, 5.158, 3.462, 0.000, -0.290, -1.534, 3.842, 2.532, 1.624, 0.305, 0.000, 2.352, 0.000, -0.864, -0.854, 3.177, 2.036, 1.668, 0.000, -0.001, -3.595, 0.000, 0.000, -1.661, -0.802, 5.880, 1.006, 2.175, 0.535, 0.000, -0.152, -4.382, 0.000, 0.000, 0.464, 0.000, 4.682, 1.848, -5.905, 0.883, 1.355, -0.296, 0.680, 0.853, 0.275, -0.001, 0.189, 1.671, 2.011, 4.716, -0.004, -0.064, -0.225, -1.345, 5.744, -0.319, 3.029, 3.476, 4.375, 3.073, 1.662, 2.422, 1.621, 0.037, 1.516, -0.543, -2.792, 1.524, -0.406, 0.855, -0.026, 2.966, 1.840, 2.188, 1.785, -0.332, -0.622, 5.780, 0.078, 0.001, 1.800, 0.000, -1.320, 4.158, 0.005, -1.452, -2.250, -0.001, 0.000, -3.152, -4.585, -7.394, 0.000, 0.000, -0.002], "vc": [125.58, 86.72, 70.64, 105.31, 45.38, 91.08, 62.82, 113.65, 49.86, 0.00, 200.24, 28.22, 14.98, 44.98, 0.07, 46.54, 13.89, 57.95, -20.09, 81.10, 103.74, 127.10, 0.00, 5.53, 2.54, 0.00, 0.00, 16.98, 1.47, -46.51, 55.26, 84.21, -4.52, -16.38, 0.00, 0.00, -0.08, -3.45, 44.84, 75.12, 98.04, 78.05, 80.34, 0.00, 38.30, 23.00, 136.00, 28.40, 0.00, 0.00, 21.77, 68.06, 98.13, 20.29, 5.01, 0.00, 3.48, 0.00, 62.65, -99.32, 48.52, 77.32, 69.56, 0.01, -95.79, 18.23, 0.00, 0.00, 14.19, 77.52, 0.00, 27.84, 46.55, 38.22, 0.00, 50.59, -0.02, 0.00, 0.00, 34.33, 0.00, 0.00, 36.94, 0.04, 36.83, 4.71, 0.00, 23.60, 51.71, 52.22, 0.00, 45.09, -2.49, 112.28, 0.00, 0.00, 9.87, -49.16, 5.85, -64.77, 5.54, 40.93, 78.55, 95.28, 122.28, 0.00, 113.89, 0.00, 0.00, 46.35, -81.99, 0.00, 127.31, 112.99, 0.00, 74.01, 60.54, 39.13, -68.36, 0.00, -28.91, 17.46, 165.84, 94.53, -0.01, 0.00, 0.00, 58.88, 46.41, 0.01, 101.11, 59.67, 0.00, 0.00, 110.06, 138.33, 131.47, 0.00, 0.00, -0.01, ], "tc_": [-8.8072, -1.1863, 2.0695, 0.8880, 0.4312, -2.9673, -5.6886, -1.8098, -0.5794, -0.0174, 4.5913, 2.2116, 5.2478, 0.5832, 3.3562, -0.2371, -0.0296, 2.8167, 2.9084, 1.0111, -0.8130, -1.3763, -0.0022, 2.7600, 7.5553, 0.0000, 0.0000, 0.3694, 0.9548, 3.9991, 1.6760, 0.5273, 2.7770, 5.3585, -0.0076, 0.8857, -0.0093, 0.7629, 0.7647, 1.6201, 0.4661, 1.7766, 4.6760, 0.0000, -1.4353, 1.5808, -5.4993, 13.0182, -0.1973, -5.5762, -2.5308, -1.7201, -0.9027, 0.4717, 0.9585, -0.0014, 6.5524, 0.0038, -4.2721, 0.0060, 1.3320, 0.6099, -1.1118, -6.0111, -0.0038, 4.4394, 0.0000, 0.0000, -6.3639, -0.8632, 0.0000, 0.5719, 1.2736, -0.1301, -0.9306, 0.1783, 2.0133, 0.0204, 0.0000, 0.0094, 0.0000, 0.7476, 2.4465, 4.1358, -1.5784, 4.0418, -1.1378, 0.3159, -0.1566, -1.1410, 0.4046, -0.0075, 5.6200, 7.6978, 0.0000, -0.0180, 1.2080, -4.5849, 0.8675, 7.0762, 2.773, 0.7764, 1.3463, 0.2835, 0.0770, 0.6733, -1.1847, 5.4387, -4.3184, 1.0536, -3.2089, 6.8866, 12.5998, 14.3778, 10.1056, 2.6863, 5.4168, 11.107, 8.7813, 15.4803, -0.4178, 2.5145, 9.8751, 9.4595, 15.4000, 1.3670, 7.2107, 12.1779, 11.7647, 0.0013, 6.3813, -4.7655, 2.7693, -0.5727, 1.4762, 4.2350, 7.5331, 5.1503, 0.0019, 0.0590], # Name and element composition "txt": [("CH3- & H",), # 0 ("CH3- & >C<",), ("CH3- & =C<",), ("CH3- & ≡C-",), ("CH3- & >C< [r]",), ("CH3- & =C< [r]",), ("CH3- & -O-",), ("CH3- & -S-",), ("CH3- & >N-",), ("CH3- & =N-",), ("CH3- & -NO2",), # 10 ("-CH2- & >C<",), ("-CH2- & =C<",), ("-CH2- & ≡C-",), ("-CH2- & >C< [r]",), ("-CH2- & =C< [r]",), ("-CH2- & -O-",), ("-CH2- & -S-",), ("-CH2- & >N-",), ("-CH2- & F-",), ("-CH2- & Cl-",), # 20 ("-CH2- & Br-",), ("-CH2- & I-",), (">CH- & >C<",), (">CH- & =C<",), (">CH- & ≡C-",), (">CH- & >C< [r]",), (">CH- & =C< [r]",), (">CH- & -O-",), (">CH- & >N-",), (">CH- & F-",), # 30 (">CH- & Cl-",), (">C< & >C<",), (">C< & =C<",), (">C< & ≡C-",), (">C< & >C< [r]",), (">C< & =C< [r]",), (">C< & -O-",), (">C< & F-",), (">C< & Cl-",), (">C< & Br-",), # 40 ("=CH2 & =C<",), ("=CH2 & =C=",), ("=CH2 & =C< [r]",), ("=CH- & >C<",), ("=CH- & =C<",), ("=CH- & ≡C-",), ("=CH- & =C=",), ("=CH- & >C< [r]",), ("=CH- & =C< [r]",), ("=CH- & -O-",), # 50 ("=CH- & F-",), ("=CH- & Cl-",), ("=C< & >C<",), ("=C< & =C<",), ("=C< & ≡C-",), ("=C< & =C=",), ("=C< & =C< [r]",), ("=C< & =O",), ("=C< & >N-",), ("=C< & F-",), # 60 ("=C< & Cl-",), ("≡CH & ≡C-",), ("≡C- & >C<",), ("≡C- & =C<",), ("≡C- & ≡C-",), ("≡C- & >C< [r]",), ("≡C- & =C< [r]",), ("=C= [r] & =C<",), ("=C= [r] & =O",), ("=C= [r] & =N-",), # 70 ("-CH2- [r] & >C< [r]",), ("-CH2- [r] & =C< [r]",), ("-CH2- [r] & -O- [r]",), ("-CH2- [r] & -S- [r]",), ("-CH2- [r] & >N- [r]",), (">CH- [r] & >C<",), (">CH- [r] & =C<",), (">CH- [r] & ≡C-",), (">CH- [r] & >C< [r]",), (">CH- [r] & =C< [r]",), # 80 (">CH- [r] & -O-",), (">CH- [r] & -O- [r]",), (">C< [r] & >C<",), (">C< [r] & >C< [r]",), (">C< [r] & F-",), ("=CH- [r] & >C< [r]",), ("=CH- [r] & =C< [r]",), ("=CH- [r] & -O- [r]",), ("=CH- [r] & -S- [r]",), ("=CH- [r] & >N- [r]",), # 90 ("=CH- [r] & =N- [r]",), ("=C< [r] & >C<",), ("=C< [r] & =C<",), ("=C< [r] & ≡C-",), ("=C< [r] & >C< [r]",), ("=C< [r] & =C< [r]",), ("=C< [r] & -O-",), ("=C< [r] & -O- [r]",), ("=C< [r] & >N-",), ("=C< [r] & >N- [r]",), # 100 ("=C< [r] & F-",), ("=C< [r] & Cl-",), ("=C< [r] & Br-",), ("=C< [r] & I-",), ("-CHO & -H",), ("-CHO & >C<",), ("-CHO & =C<",), ("-CHO & =C< [r]",), ("-CO & >C<",), ("-CO & =C< [r]",), # 110 ("-COOH & -H",), ("-COOH & >C<",), ("-COOH & =C<",), ("-COOH & =C< [r]",), ("-COO- & -H",), ("-COO- & >C<",), ("-COO- & =C<",), ("-COO- & =C< [r]",), (">C2O3 & =C<",), (">C2O3 & =C< [r]",), # 120 (">CO [r] & >C< [r]",), ("-CN & -H",), ("-CN & >C<",), ("-CN & =C<",), ("-CN & ≡C-",), ("-CN & =C< [r]",), # Group Structural Unit Parameter ("-OH", ), ("-O-", ), ("-O- (cyclic)", ), ("-OH (Aromatic)", ), # 130 ("-SH", ), ("-S-", ), ("-S- (cyclic)", ), ("-NH2", ), (">NH", ), (">N-", ), ("=N-", ), (">NH (cyclic)", ), (">N- (cyclic)", )]} FirstOrder = 127 SecondOrder = 140
[docs] def calculo(self): """Calculation procedure""" # Use the input properties # SG is defined in base class if self.kwargs["M"]: M = self.kwargs["M"] else: M = self._M() self.M = unidades.Dimensionless(M) tc, pc, vc, tc_ = 0, 0, 0, 0 for i, c in zip(self.kwargs["group"], self.kwargs["contribution"]): tc += c*self.__coeff__["tc"][i] tc_ += c*self.__coeff__["tc_"][i] pc += c*self.__coeff__["Pc"][i] vc += c*self.__coeff__["vc"][i] if self.kwargs["Tb"]: self.Tb = unidades.Temperature(self.kwargs["Tb"]) Tc = (((127.754+tc_)/1e2)**-2+1)*self.Tb self.Tc = unidades.Temperature(Tc) else: self.Tc = unidades.Temperature(((4.72+tc)*1e6)**(1/2.747)) self.Pc = unidades.Pressure(((37.293+pc)/1e2)**-2, "MPa") self.Vc = unidades.SpecificVolume((-27.04+vc)/self.M, "ccg") GroupContribution.calculo(self)
[docs] def _group(self): """Specific procedure to calculate the molecular weight of compound from group contribution""" # TODO: Add group check coherent definition group = [] rest = {} for i, c in zip(self.kwargs["group"], self.kwargs["contribution"]): if "&" in self.__coeff__["txt"][i][0]: grp = self.__coeff__["txt"][i][0].split(" & ")[0] second = self.__coeff__["txt"][i][0].split(" & ")[1] # Discard second term with carbons and add the heteroatoms term grp2 = atomic_decomposition(second) if "H" in grp2 or "F" in grp2 or "Cl" in grp2 or \ "Br" in grp2 or "I" in grp2: for x in range(c): group.append(grp2) else: grp = self.__coeff__["txt"][i][0] for x in range(c): cmp = grp molecule = grp # Clean additional comment of group, ring flag and other, # separated of main group by spaces if " " in cmp: cmp = cmp.split(" ")[0] # Calculate the remain appeareances of group contributions # X- : X is one connected so don't appearance reamaining # -X- : X has 2 connection so must be stay in another group # -X<: X has 3 connection so must be stay in other 2 group # >X<: X has 4 connection so must be stay in other 3 group restLink = -1 if cmp[0] in ("-=≡"): restLink += 1 molecule = molecule[1:] elif cmp[0] == ">": restLink += 2 molecule = molecule[1:] if cmp[-1] in ("-=≡"): restLink += 1 molecule = molecule[:-1] elif cmp[-1] == "<": restLink += 2 molecule = molecule[:-1] if grp in rest and rest[grp]: rest[grp] -= 1 else: rest[grp] = restLink group.append(atomic_decomposition(molecule)) return group