def to(self, zs, T=None, P=None, V=None): new = self.__class__.__new__(self.__class__) new.zs = zs if T is not None: new.T = T if P is not None: new._rho_mass = rho_mass = iapws.iapws97_rho(T, P) new._V = rho_to_Vm(rho=rho_mass, MW=self._MW) new.P = P elif V is not None: new._rho_mass = rho_mass = Vm_to_rho(V, MW=self._MW) P = iapws.iapws97_P(T, rho_mass) new.V = V new.P = P elif P is not None and V is not None: new._rho_mass = rho_mass = Vm_to_rho(V, MW=self._MW) T = new.T = iapws.iapws97_T(P, rho_mass) new.V = V new.P = P else: raise ValueError("Two of T, P, or V are needed") new.region = region = iapws.iapws97_identify_region_TP(new.T, new.P) if region == 1: new.pi = P * 6.049606775559589e-08 #1/16.53E6 new.tau = 1386.0 / T new.Pref = 16.53E6 new.Tref = 1386.0 elif region == 2: new.pi = P * 1e-6 new.tau = 540.0 / T new.Pref = 1e6 new.Tref = 540.0 elif region == 3: new.tau = new.Tc / T new.Tref = new.Tc new.delta = new._rho_mass * 0.003105590062111801 # 1/322.0 new.rhoref = 322.0 elif region == 5: new.pi = P * 1e-6 new.tau = 1000.0 / T new.Tref = 1000.0 new.Pref = 1e6 new.P = P new.T = T return new
def to(self, zs, T=None, P=None, V=None): new = self.__class__.__new__(self.__class__) new.zs = zs if T is not None and P is not None: new.T = T new._rho_mass = rho_mass = iapws.iapws95_rho(T, P) new._V = rho_to_Vm(rho=rho_mass, MW=self._MW) new.P = P elif T is not None and V is not None: new.T = T new._rho_mass = rho_mass = 1e-3 * self._MW / V P = iapws.iapws95_P(T, rho_mass) new._V = V new.P = P elif P is not None and V is not None: new._rho_mass = rho_mass = Vm_to_rho(V, MW=self._MW) T = new.T = iapws.iapws95_T(P, rho_mass) new._V = V new.P = P else: raise ValueError("Two of T, P, or V are needed") new.P = P new.T = T new.tau = tau = new.Tc / T new.delta = delta = rho_mass * new.rhoc_mass_inv new.A0, new.dA0_dtau, new.d2A0_dtau2, new.d3A0_dtau3 = iapws.iapws95_A0_tau_derivatives( tau, delta) return new
def mini_sort_phases(phases, sort_method, prop, cmps, cmps_neg, reverse=True, constants=None): if sort_method == PROP_SORT: if prop == DENSITY_MASS: keys = [] MWs = constants.MWs for p in phases: zs = p.zs MW = 0.0 for i in constants.cmps: MW += zs[i] * MWs[i] keys.append(Vm_to_rho(p.V(), MW)) # for i in phases: # i.constants = constants # keys = [i.rho_mass() for i in phases] elif prop == DENSITY: keys = [i.rho() for i in phases] elif prop == ISOTHERMAL_COMPRESSIBILITY: keys = [i.isobaric_expansion() for i in phases] elif prop == HEAT_CAPACITY: keys = [i.Cp() for i in phases] phases = [p for _, p in sorted(zip(keys, phases))] if reverse: phases.reverse() elif sort_method == KEY_COMPONENTS_SORT: phases = key_cmp_sort(phases, cmps, cmps_neg) if not reverse: phases.reverse() return phases
def test_COSTALD(): V1_calc = COSTALD(298, 647.13, 55.95E-6, 0.3449) V1 = 1.8133760480018036e-05 # Propane, from API Handbook example; I have used their exact values, # but they rounded each step, getting 530.1 V2_calc = COSTALD(272.03889, 369.83333, 0.20008161E-3, 0.1532) V2 = 8.315466172295678e-05 assert_allclose([V1_calc, V2_calc], [V1, V2]) rho_ex = Vm_to_rho(COSTALD(272.03889, 369.83333, 0.20008161E-3, 0.1532), 44.097) assert_allclose(rho_ex, 530.3009967969841)
def test_VolumeLiquid_fitting2_dippr_116_ppds(): for i, CAS in enumerate(chemicals.volume.rho_data_VDI_PPDS_2.index): obj = VolumeLiquid(CASRN=CAS) Ts = linspace(obj.T_limits[VDI_PPDS][0], obj.T_limits[VDI_PPDS][1], 8) props_calc = [ Vm_to_rho(obj.calculate(T, VDI_PPDS), obj.VDI_PPDS_MW) for T in Ts ] res, stats = obj.fit_data_to_model(Ts=Ts, data=props_calc, model='DIPPR116', do_statistics=True, use_numba=False, fit_method='lm', model_kwargs={ 'Tc': obj.VDI_PPDS_Tc, 'A': obj.VDI_PPDS_rhoc }) assert stats['MAE'] < 1e-7
def calculate(self, T, method): r'''Method to calculate surface tension of a liquid at temperature `T` with a given method. This method has no exception handling; see :obj:`T_dependent_property <thermo.utils.TDependentProperty.T_dependent_property>` for that. Parameters ---------- T : float Temperature at which to calculate surface tension, [K] method : str Name of the method to use Returns ------- sigma : float Surface tension of the liquid at T, [N/m] ''' if method == STREFPROP: sigma0, n0, sigma1, n1, sigma2, n2, Tc = self.STREFPROP_coeffs sigma = REFPROP_sigma(T, Tc=Tc, sigma0=sigma0, n0=n0, sigma1=sigma1, n1=n1, sigma2=sigma2, n2=n2) elif method == VDI_PPDS: sigma = EQ106(T, self.VDI_PPDS_Tc, *self.VDI_PPDS_coeffs) elif method == SOMAYAJULU2: A, B, C = self.SOMAYAJULU2_coeffs sigma = Somayajulu(T, Tc=self.SOMAYAJULU2_Tc, A=A, B=B, C=C) elif method == SOMAYAJULU: A, B, C = self.SOMAYAJULU_coeffs sigma = Somayajulu(T, Tc=self.SOMAYAJULU_Tc, A=A, B=B, C=C) elif method == JASPER: sigma = Jasper(T, a=self.JASPER_coeffs[0], b=self.JASPER_coeffs[1]) elif method == BROCK_BIRD: sigma = Brock_Bird(T, self.Tb, self.Tc, self.Pc) elif method == SASTRI_RAO: sigma = Sastri_Rao(T, self.Tb, self.Tc, self.Pc) elif method == PITZER: sigma = Pitzer_sigma(T, self.Tc, self.Pc, self.omega) elif method == ZUO_STENBY: sigma = Zuo_Stenby(T, self.Tc, self.Pc, self.omega) elif method == MIQUEU: sigma = Miqueu(T, self.Tc, self.Vc, self.omega) elif method == ALEEM: Cpl = self.Cpl(T) if hasattr(self.Cpl, '__call__') else self.Cpl Cpl = property_molar_to_mass(Cpl, self.MW) Vml = self.Vml(T) if hasattr(self.Vml, '__call__') else self.Vml rhol = Vm_to_rho(Vml, self.MW) sigma = Aleem(T=T, MW=self.MW, Tb=self.Tb, rhol=rhol, Hvap_Tb=self.Hvap_Tb, Cpl=Cpl) else: return self._base_calculate(T, method) return sigma