def omega_definition(Psat, Pc): r'''Returns the acentric factor of a fluid according to its fundamental definition using the vapor pressure at a reduced temperature of 0.7Tc. .. math:: \omega \equiv -\log_{10}\left[\lim_{T/T_c=0.7}(P^{sat}/P_c)\right]-1.0 Parameters ---------- Psat : float Vapor pressure of the fluid at a reduced temperature of 0.7 [Pa] Pc : float Critical pressure of the fluid [Pa] Returns ------- omega : float Acentric factor of the fluid [-] Notes ----- Examples -------- Water >>> omega_definition(999542, 22048320.0) 0.3435744558761711 References ---------- .. [1] Poling, Bruce E. The Properties of Gases and Liquids. 5th edition. New York: McGraw-Hill Professional, 2000. ''' return -log10(Psat / Pc) - 1.0
def Stiel_polar_factor(Psat, Pc, omega): r'''This function handles the calculation of a chemical's Stiel Polar factor, directly through the definition of Stiel-polar factor. Requires the vapor pressure `Psat` at a reduced temperature of 0.6, the critical pressure `Pc`, and the acentric factor `omega`. .. math:: x = \log P_r|_{T_r=0.6} + 1.70 \omega + 1.552 Parameters ---------- Psat : float Vapor pressure of fluid at a reduced temperature of 0.6 [Pa] Pc : float Critical pressure of fluid [Pa] omega : float Acentric factor of the fluid [-] Returns ------- factor : float Stiel polar factor of compound Notes ----- A few points have also been published in [2]_, which may be used for comparison. Currently this is only used for a surface tension correlation. Examples -------- Calculating the factor for water: >>> Stiel_polar_factor(Psat=169745, Pc=22048321.0, omega=0.344) 0.02322146744772713 References ---------- .. [1] Halm, Roland L., and Leonard I. Stiel. "A Fourth Parameter for the Vapor Pressure and Entropy of Vaporization of Polar Fluids." AIChE Journal 13, no. 2 (1967): 351-355. doi:10.1002/aic.690130228. .. [2] D, Kukoljac Miloš, and Grozdanić Dušan K. "New Values of the Polarity Factor." Journal of the Serbian Chemical Society 65, no. 12 (January 1, 2000). http://www.shd.org.rs/JSCS/Vol65/No12-Pdf/JSCS12-07.pdf ''' Pr = Psat / Pc factor = log10(Pr) + 1.70 * omega + 1.552 return factor
def nus(self): T, P = self.T, self.P Tcs, Pcs, omegas = self._Tcs, self._Pcs, self._omegas regular, CASs = self.regular, self._CASs nus = [] limit_Tr = self.version > 0 for i in range(self.N): # TODO validate and take T, P derivatives; n derivatives are from regular solution only Tr = T / Tcs[i] Pr = P / Pcs[i] if regular[i]: coeffs = self.simple_coeffs elif CASs[i] == '1333-74-0': coeffs = self.hydrogen_coeffs elif CASs[i] == '74-82-8': coeffs = self.methane_coeffs else: raise ValueError("Fail") A0, A1, A2, A3, A4, A5, A6, A7, A8, A9 = coeffs log10_v0 = A0 + A1 / Tr + A2 * Tr + A3 * Tr**2 + A4 * Tr**3 + ( A5 + A6 * Tr + A7 * Tr**2) * Pr + (A8 + A9 * Tr) * Pr**2 - log10(Pr) log10_v1 = -4.23893 + 8.65808 * Tr - 1.2206 / Tr - 3.15224 * Tr**3 - 0.025 * ( Pr - 0.6) if Tr > 1.0 and limit_Tr: log10_v1 = 1.0 if regular[i]: v = 10.0**(log10_v0 + omegas[i] * log10_v1) else: # Chao Seader mentions v = 10.0**(log10_v0) nus.append(v) return nus
def balance_stoichiometry(matrix, rounding=9, allow_fractional=False): r'''This function balances a chemical reaction. Parameters ---------- matrix : list[list[float]] Chemical reaction matrix for further processing; rows contain element counts of each compound, and the columns represent each chemical, [-] Returns ------- coefficients : list[float] Balanced coefficients; all numbers are positive, [-] Notes ----- Balance the reaction 4 NH3 + 5 O2 = 4 NO + 6 H2O, without knowing the coefficients: >>> matrix = stoichiometric_matrix([{'N': 1, 'H': 3}, {'O': 2}, {'N': 1, 'O': 1}, {'H': 2, 'O': 1}], [True, True, False, False]) >>> matrix [[3, 0, 0, -2], [1, 0, -1, 0], [0, 2, -1, -1]] >>> balance_stoichiometry(matrix) [4.0, 5.0, 4.0, 6.0] >>> balance_stoichiometry(matrix, allow_fractional=True) [1.0, 1.25, 1.0, 1.5] This algorithm relies on `scipy`. The behavior of this function for inputs which do not have a unique solution is undefined. This algorithm may suffer from floating point issues. If you believe there is an error in the result, please report your reaction to the developers. References ---------- .. [1] Sen, S. K., Hans Agarwal, and Sagar Sen. "Chemical Equation Balancing: An Integer Programming Approach." Mathematical and Computer Modelling 44, no. 7 (October 1, 2006): 678-91. https://doi.org/10.1016/j.mcm.2006.02.004. .. [2] URAVNOTE, NOVOODKRITI PARADOKSI V. TEORIJI, and ENJA KEMIJSKIH REAKCIJ. "New Discovered Paradoxes in Theory of Balancing Chemical Reactions." Materiali in Tehnologije 45, no. 6 (2011): 503-22. ''' import scipy.linalg done = scipy.linalg.null_space(matrix) if len(done[0]) > 1: raise ValueError("No solution") d = done[:, 0].tolist() min_value_inv = 1.0 / min(d) d = [i * min_value_inv for i in d] if not allow_fractional: from fractions import Fraction max_denominator = 10**rounding fs = [ Fraction(x).limit_denominator(max_denominator=max_denominator) for x in d ] all_denominators = set([i.denominator for i in fs]) if 1 in all_denominators: all_denominators.remove(1) for den in sorted(list(all_denominators), reverse=True): fs = [num * den for num in fs] if all(i.denominator == 1 for i in fs): break # May have gone too far return [float(i) for i in fs] # done = False # for i in range(100): # for c in d: # ratio = c.as_integer_ratio()[1] # if ratio != 1: # d = [di*ratio for di in d] # break # done = True # if done: # break # # d_as_int = [int(i) for i in d] # for i, j in zip(d, d_as_int): # if i != j: # raise ValueError("Could not find integer coefficients (%s, %s)" %(i, j)) # return d_as_int else: d = [round(i, rounding + int(ceil(log10(abs(i))))) for i in d] return d