From 77b6afa7c3c8ce77397e05f3a4177a953b32a55f Mon Sep 17 00:00:00 2001 From: Enrique Cintron Date: Wed, 24 May 2017 16:52:12 -0400 Subject: [PATCH 1/4] Auto delete spaces - committing so actual changes are legible --- thermo/chemical.py | 1512 ++++++++++++++++++++++---------------------- 1 file changed, 756 insertions(+), 756 deletions(-) diff --git a/thermo/chemical.py b/thermo/chemical.py index 89766ea5..d7efa53e 100644 --- a/thermo/chemical.py +++ b/thermo/chemical.py @@ -68,7 +68,7 @@ from rdkit import Chem from rdkit.Chem import Descriptors from rdkit.Chem import AllChem -except: +except: # pragma: no cover pass @@ -89,10 +89,10 @@ CHEMSEP = (298., 101325, 'g', 0, 0, True) # It has an option to add Hf to the reference PRO_II = (298.15, 101325, 'gas', 0, 0, True) HYSYS = (298.15, 101325, 'calc', 'Hf', 0, True) -UNISIM = HYSYS # +UNISIM = HYSYS # SUPERPRO = (298.15, 101325, 'calc', 0, 0, True) # No support for entropy found, 0 assumed -reference_states = [IAPWS, ASHRAE, IIR, REFPROP, CHEMSEP, PRO_II, HYSYS, +reference_states = [IAPWS, ASHRAE, IIR, REFPROP, CHEMSEP, PRO_II, HYSYS, UNISIM, SUPERPRO] _chemical_cache = {} @@ -118,8 +118,8 @@ class Chemical(object): # pragma: no cover CAS : str The CAS number of the chemical. PubChem : int - PubChem Compound identifier (CID) of the chemical; all chemicals are - sourced from their database. Chemicals can be looked at online at + PubChem Compound identifier (CID) of the chemical; all chemicals are + sourced from their database. Chemicals can be looked at online at ``_. MW : float Molecular weight of the compound, g/mol. @@ -129,15 +129,15 @@ class Chemical(object): # pragma: no cover dictionary of counts of individual atoms, indexed by symbol with proper capitalization, [-] similarity_variable : float - Similarity variable, see :obj:`thermo.elements.similarity_variable` + Similarity variable, see :obj:`thermo.elements.similarity_variable` for the definition, [mol/g] smiles : str - Simplified molecular-input line-entry system representation of the + Simplified molecular-input line-entry system representation of the compound. InChI : str IUPAC International Chemical Identifier of the compound. InChI_Key : str - 25-character hash of the compound's InChI. + 25-character hash of the compound's InChI. IUPAC_name : str Preferred IUPAC name for a compound. synonyms : list[str] @@ -161,7 +161,7 @@ class Chemical(object): # pragma: no cover omega : float Acentric factor [-] StielPolar : float - Stiel Polar factor, see :obj:`thermo.acentric.StielPolar` for + Stiel Polar factor, see :obj:`thermo.acentric.StielPolar` for the definition [-] Tt : float Triple temperature, [K] @@ -226,32 +226,32 @@ class Chemical(object): # pragma: no cover methods loaded for the chemical; performs the actual calculations of vapor pressure of the chemical. EnthalpyVaporization : object - Instance of :obj:`thermo.phase_change.EnthalpyVaporization`, with data - and methods loaded for the chemical; performs the actual calculations + Instance of :obj:`thermo.phase_change.EnthalpyVaporization`, with data + and methods loaded for the chemical; performs the actual calculations of molar enthalpy of vaporization of the chemical. VolumeSolid : object Instance of :obj:`thermo.volume.VolumeSolid`, with data and methods - loaded for the chemical; performs the actual calculations of molar + loaded for the chemical; performs the actual calculations of molar volume of the solid phase of the chemical. VolumeLiquid : object Instance of :obj:`thermo.volume.VolumeLiquid`, with data and methods - loaded for the chemical; performs the actual calculations of molar + loaded for the chemical; performs the actual calculations of molar volume of the liquid phase of the chemical. VolumeGas : object Instance of :obj:`thermo.volume.VolumeGas`, with data and methods - loaded for the chemical; performs the actual calculations of molar + loaded for the chemical; performs the actual calculations of molar volume of the gas phase of the chemical. HeatCapacitySolid : object - Instance of :obj:`thermo.heat_capacity.HeatCapacitySolid`, with data and - methods loaded for the chemical; performs the actual calculations of + Instance of :obj:`thermo.heat_capacity.HeatCapacitySolid`, with data and + methods loaded for the chemical; performs the actual calculations of molar heat capacity of the solid phase of the chemical. HeatCapacityLiquid : object - Instance of :obj:`thermo.heat_capacity.HeatCapacityLiquid`, with data and - methods loaded for the chemical; performs the actual calculations of + Instance of :obj:`thermo.heat_capacity.HeatCapacityLiquid`, with data and + methods loaded for the chemical; performs the actual calculations of molar heat capacity of the liquid phase of the chemical. HeatCapacityGas : object - Instance of :obj:`thermo.heat_capacity.HeatCapacityGas`, with data and - methods loaded for the chemical; performs the actual calculations of + Instance of :obj:`thermo.heat_capacity.HeatCapacityGas`, with data and + methods loaded for the chemical; performs the actual calculations of molar heat capacity of the gas phase of the chemical. ViscosityLiquid : object Instance of :obj:`thermo.viscosity.ViscosityLiquid`, with data and @@ -263,12 +263,12 @@ class Chemical(object): # pragma: no cover viscosity of the gas phase of the chemical. ThermalConductivityLiquid : object Instance of :obj:`thermo.thermal_conductivity.ThermalConductivityLiquid`, - with data and methods loaded for the chemical; performs the actual - calculations of thermal conductivity of the liquid phase of the + with data and methods loaded for the chemical; performs the actual + calculations of thermal conductivity of the liquid phase of the chemical. ThermalConductivityGas : object Instance of :obj:`thermo.thermal_conductivity.ThermalConductivityGas`, - with data and methods loaded for the chemical; performs the actual + with data and methods loaded for the chemical; performs the actual calculations of thermal conductivity of the gas phase of the chemical. SurfaceTension : object Instance of :obj:`thermo.interface.SurfaceTension`, with data and @@ -369,7 +369,7 @@ class Chemical(object): # pragma: no cover Zl Zs ''' - + __atom_fractions = None __mass_fractions = None __UNIFAC_groups = None @@ -382,7 +382,7 @@ class Chemical(object): # pragma: no cover __economic_status = None def __repr__(self): return '' %(self.name, self.T, self.P) - + def __init__(self, ID, T=298.15, P=101325): if isinstance(ID, dict): self.CAS = ID['CASRN'] @@ -399,7 +399,7 @@ def __init__(self, ID, T=298.15, P=101325): # Identification self.CAS = CASfromAny(ID) - + if self.CAS in _chemical_cache and caching: self.__dict__.update(_chemical_cache[self.CAS].__dict__) self.calculate(T, P) @@ -414,10 +414,10 @@ def __init__(self, ID, T=298.15, P=101325): self.IUPAC_name = IUPAC_name(self.CAS).lower() self.name = name(self.CAS).lower() self.synonyms = synonyms(self.CAS) - + self.atoms = simple_formula_parser(self.formula) self.similarity_variable = similarity_variable(self.atoms, self.MW) - + self.eos_in_a_box = [] self.set_constant_sources() self.set_constants() @@ -427,8 +427,8 @@ def __init__(self, ID, T=298.15, P=101325): if len(_chemical_cache) < 1000: self.calculate(T, P) _chemical_cache[self.CAS] = self - - + + def calculate(self, T=None, P=None): if (hasattr(self, 'T') and T == self.T and hasattr(self, 'P') and P == self.P): @@ -447,12 +447,12 @@ def calculate(self, T=None, P=None): self.eos = self.eos.to_TP(T=self.T, P=self.P) self.eos_in_a_box[0] = self.eos self.set_thermo() - + def draw_2d(self, width=300, height=300, Hs=False): # pragma: no cover - r'''Interface for drawing a 2D image of the molecule. - Requires an HTML5 browser, and the libraries RDKit and - IPython. An exception is raised if either of these libraries is + r'''Interface for drawing a 2D image of the molecule. + Requires an HTML5 browser, and the libraries RDKit and + IPython. An exception is raised if either of these libraries is absent. Parameters @@ -480,11 +480,11 @@ def draw_2d(self, width=300, height=300, Hs=False): # pragma: no cover return 'Rdkit is required for this feature.' def draw_3d(self, width=300, height=500, style='stick', Hs=True): # pragma: no cover - r'''Interface for drawing an interactive 3D view of the molecule. - Requires an HTML5 browser, and the libraries RDKit, pymol3D, and - IPython. An exception is raised if all three of these libraries are + r'''Interface for drawing an interactive 3D view of the molecule. + Requires an HTML5 browser, and the libraries RDKit, pymol3D, and + IPython. An exception is raised if all three of these libraries are absent. - + Parameters ---------- width : int @@ -538,7 +538,7 @@ def set_constant_sources(self): self.Tt_source = self.Tt_sources[0] self.Pt_sources = Pt(self.CAS, AvailableMethods=True) self.Pt_source = self.Pt_sources[0] - + # Enthalpy self.Hfus_methods = Hfus(MW=self.MW, AvailableMethods=True, CASRN=self.CAS) self.Hfus_method = self.Hfus_methods[0] @@ -597,7 +597,7 @@ def set_constants(self): self.Pc = Pc(self.CAS, Method=self.Pc_method) self.Vc = Vc(self.CAS, Method=self.Vc_method) self.omega = omega(self.CAS, Method=self.omega_method) - + self.StielPolar_methods = StielPolar(Tc=self.Tc, Pc=self.Pc, omega=self.omega, CASRN=self.CAS, AvailableMethods=True) self.StielPolar_method = self.StielPolar_methods[0] self.StielPolar = StielPolar(Tc=self.Tc, Pc=self.Pc, omega=self.omega, CASRN=self.CAS, Method=self.StielPolar_method) @@ -613,10 +613,10 @@ def set_constants(self): # Enthalpy self.Hfus = Hfus(MW=self.MW, Method=self.Hfus_method, CASRN=self.CAS) self.Hfusm = property_mass_to_molar(self.Hfus, self.MW) if self.Hfus else None - + self.Hsub = Hsub(MW=self.MW, Method=self.Hsub_method, CASRN=self.CAS) self.Hsubm = property_mass_to_molar(self.Hsub, self.MW) - + # Chemistry self.Hf = Hf(CASRN=self.CAS, Method=self.Hf_source) self.Hc = Hcombustion(atoms=self.atoms, Hf=self.Hf) @@ -664,9 +664,9 @@ def set_eos(self, T, P, eos=PR): def eos(self): r'''Equation of state object held by the chemical; used to calculate excess thermodynamic quantities, and also provides a vapor pressure - curve, enthalpy of vaporization curve, fugacity, thermodynamic partial + curve, enthalpy of vaporization curve, fugacity, thermodynamic partial derivatives, and more; see :obj:`thermo.eos` for a full listing. - + Examples -------- >>> Chemical('methane').eos.V_g @@ -678,32 +678,32 @@ def eos(self): def eos(self, eos): if self.eos_in_a_box: self.eos_in_a_box.pop() - # Pass this mutable list to objects so if it is changed, it gets + # Pass this mutable list to objects so if it is changed, it gets # changed in the property method too - self.eos_in_a_box.append(eos) - + self.eos_in_a_box.append(eos) + def set_TP_sources(self): # Tempearture and Pressure Denepdence # Get and choose initial methods - self.VaporPressure = VaporPressure(Tb=self.Tb, Tc=self.Tc, Pc=self.Pc, - omega=self.omega, CASRN=self.CAS, + self.VaporPressure = VaporPressure(Tb=self.Tb, Tc=self.Tc, Pc=self.Pc, + omega=self.omega, CASRN=self.CAS, eos=self.eos_in_a_box) self.Psat_298 = self.VaporPressure.T_dependent_property(298.15) self.phase_STP = identify_phase(T=298.15, P=101325., Tm=self.Tm, Tb=self.Tb, Tc=self.Tc, Psat=self.Psat_298) self.VolumeLiquid = VolumeLiquid(MW=self.MW, Tb=self.Tb, Tc=self.Tc, Pc=self.Pc, Vc=self.Vc, Zc=self.Zc, omega=self.omega, - dipole=self.dipole, - Psat=self.VaporPressure.T_dependent_property, + dipole=self.dipole, + Psat=self.VaporPressure.T_dependent_property, eos=self.eos_in_a_box, CASRN=self.CAS) self.Vml_Tb = self.VolumeLiquid.T_dependent_property(self.Tb) if self.Tb else None self.Vml_Tm = self.VolumeLiquid.T_dependent_property(self.Tm) if self.Tm else None self.Vml_STP = self.VolumeLiquid.T_dependent_property(298.15) - self.VolumeGas = VolumeGas(MW=self.MW, Tc=self.Tc, Pc=self.Pc, - omega=self.omega, dipole=self.dipole, + self.VolumeGas = VolumeGas(MW=self.MW, Tc=self.Tc, Pc=self.Pc, + omega=self.omega, dipole=self.dipole, eos=self.eos_in_a_box, CASRN=self.CAS) self.Vmg_STP = self.VolumeGas.TP_dependent_property(298.15, 101325) @@ -719,9 +719,9 @@ def set_TP_sources(self): self.EnthalpyVaporization = EnthalpyVaporization(CASRN=self.CAS, Tb=self.Tb, Tc=self.Tc, Pc=self.Pc, omega=self.omega, similarity_variable=self.similarity_variable) self.Hvap_Tbm = self.EnthalpyVaporization.T_dependent_property(self.Tb) if self.Tb else None self.Hvap_Tb = property_molar_to_mass(self.Hvap_Tbm, self.MW) - + self.ViscosityLiquid = ViscosityLiquid(CASRN=self.CAS, MW=self.MW, Tm=self.Tm, Tc=self.Tc, Pc=self.Pc, Vc=self.Vc, omega=self.omega, Psat=self.VaporPressure.T_dependent_property, Vml=self.VolumeLiquid.T_dependent_property) - + Vmg_atm_T_dependent = lambda T : self.VolumeGas.TP_dependent_property(T, 101325) self.ViscosityGas = ViscosityGas(CASRN=self.CAS, MW=self.MW, Tc=self.Tc, Pc=self.Pc, Zc=self.Zc, dipole=self.dipole, Vmg=Vmg_atm_T_dependent) @@ -751,7 +751,7 @@ def set_ref(self, T_ref=298.15, P_ref=101325, phase_ref='calc', H_ref=0, S_ref=0 self.H_ref = getattr(self, H_ref) if isinstance(H_ref, str) else H_ref self.S_ref = getattr(self, S_ref) if isinstance(S_ref, str) else S_ref self.phase_ref = self.phase_STP if phase_ref == 'calc' else phase_ref - + integrators = {'s': self.HeatCapacitySolid.T_dependent_property_integral, 'l': self.HeatCapacityLiquid.T_dependent_property_integral, 'g': self.HeatCapacityGas.T_dependent_property_integral} @@ -759,7 +759,7 @@ def set_ref(self, T_ref=298.15, P_ref=101325, phase_ref='calc', H_ref=0, S_ref=0 integrators_T = {'s': self.HeatCapacitySolid.T_dependent_property_integral_over_T, 'l': self.HeatCapacityLiquid.T_dependent_property_integral_over_T, 'g': self.HeatCapacityGas.T_dependent_property_integral_over_T} - + # Integrals stored to avoid recalculation, all from T_low to T_high try: # Enthalpy integrals @@ -772,7 +772,7 @@ def set_ref(self, T_ref=298.15, P_ref=101325, phase_ref='calc', H_ref=0, S_ref=0 if self.phase_ref == 'l' and self.Tm and self.Tb: self.H_int_l_T_ref_l_to_Tb = integrators['l'](self.T_ref, self.Tb) self.H_int_l_Tm_to_T_ref_l = integrators['l'](self.Tm, self.T_ref) - + # Entropy integrals if self.phase_ref != 'l' and self.Tm and self.Tb: self.S_int_l_Tm_to_Tb = integrators_T['l'](self.Tm, self.Tb) @@ -785,40 +785,40 @@ def set_ref(self, T_ref=298.15, P_ref=101325, phase_ref='calc', H_ref=0, S_ref=0 self.S_int_l_Tm_to_T_ref_l = integrators_T['l'](self.Tm, self.T_ref) except: pass - + # Excess properties stored try: if self.phase_ref == 'g': self.eos_phase_ref = self.eos.to_TP(self.T_ref, self.P_ref) self.H_dep_ref_g = self.eos_phase_ref.H_dep_g self.S_dep_ref_g = self.eos_phase_ref.S_dep_g - - + + elif self.phase_ref == 'l': self.eos_phase_ref = self.eos.to_TP(self.T_ref, self.P_ref) self.H_dep_ref_l = self.eos_phase_ref.H_dep_l self.S_dep_ref_l = self.eos_phase_ref.S_dep_l - + self.H_dep_T_ref_Pb = self.eos.to_TP(self.T_ref, 101325).H_dep_l self.S_dep_T_ref_Pb = self.eos.to_TP(self.T_ref, 101325).S_dep_l - + if self.Tb: self.eos_Tb = self.eos.to_TP(self.Tb, 101325) self.H_dep_Tb_Pb_g = self.eos_Tb.H_dep_g self.H_dep_Tb_Pb_l = self.eos_Tb.H_dep_l - + self.H_dep_Tb_P_ref_g = self.eos.to_TP(self.Tb, self.P_ref).H_dep_g self.S_dep_Tb_P_ref_g = self.eos.to_TP(self.Tb, self.P_ref).S_dep_g - + self.S_dep_Tb_Pb_g = self.eos_Tb.S_dep_g self.S_dep_Tb_Pb_l = self.eos_Tb.S_dep_l - + # if self.Tt and self.Pt: # self.eos_Tt = self.eos.to_TP(self.Tt, self.Pt) # self.H_dep_Tt_g = self.eos_Tt.H_dep_g ## self.H_dep_Tt_l = self.eos_Tt.H_dep_l -# +# # self.S_dep_Tt_g = self.eos_Tt.S_dep_g ## self.S_dep_Tt_l = self.eos_Tt.S_dep_l except: @@ -833,22 +833,22 @@ def calc_H(self, T, P): H = self.H_ref if self.phase == self.phase_ref: H += integrators[self.phase](self.T_ref, T) - + elif self.phase_ref == 's' and self.phase == 'l': H += self.H_int_T_ref_s_to_Tm + self.Hfusm + integrators['l'](self.Tm, T) - + elif self.phase_ref == 'l' and self.phase == 's': H += -self.H_int_l_Tm_to_T_ref_l - self.Hfusm + integrators['s'](self.Tm, T) - + elif self.phase_ref == 'l' and self.phase == 'g': H += self.H_int_l_T_ref_l_to_Tb + self.Hvap_Tbm + integrators['g'](self.Tb, T) - + elif self.phase_ref == 'g' and self.phase == 'l': H += -self.H_int_Tb_to_T_ref_g - self.Hvap_Tbm + integrators['l'](self.Tb, T) - + elif self.phase_ref == 's' and self.phase == 'g': H += self.H_int_T_ref_s_to_Tm + self.Hfusm + self.H_int_l_Tm_to_Tb + self.Hvap_Tbm + integrators['g'](self.Tb, T) - + elif self.phase_ref == 'g' and self.phase == 's': H += -self.H_int_Tb_to_T_ref_g - self.Hvap_Tbm - self.H_int_l_Tm_to_Tb - self.Hfusm + integrators['s'](self.Tm, T) else: @@ -861,17 +861,17 @@ def calc_H_excess(self, T, P): H_dep = 0 if self.phase_ref == 'g' and self.phase == 'g': H_dep += self.eos.to_TP(T, P).H_dep_g - self.H_dep_ref_g - + elif self.phase_ref == 'l' and self.phase == 'l': try: H_dep += self.eos.to_TP(T, P).H_dep_l - self._eos_T_101325.H_dep_l except: H_dep += 0 - + elif self.phase_ref == 'g' and self.phase == 'l': H_dep += self.H_dep_Tb_Pb_g - self.H_dep_Tb_P_ref_g H_dep += (self.eos.to_TP(T, P).H_dep_l - self._eos_T_101325.H_dep_l) - + elif self.phase_ref == 'l' and self.phase == 'g': H_dep += self.H_dep_T_ref_Pb - self.H_dep_ref_l H_dep += (self.eos.to_TP(T, P).H_dep_g - self.H_dep_Tb_Pb_g) @@ -881,17 +881,17 @@ def calc_S_excess(self, T, P): S_dep = 0 if self.phase_ref == 'g' and self.phase == 'g': S_dep += self.eos.to_TP(T, P).S_dep_g - self.S_dep_ref_g - + elif self.phase_ref == 'l' and self.phase == 'l': try: S_dep += self.eos.to_TP(T, P).S_dep_l - self._eos_T_101325.S_dep_l except: S_dep += 0 - + elif self.phase_ref == 'g' and self.phase == 'l': S_dep += self.S_dep_Tb_Pb_g - self.S_dep_Tb_P_ref_g S_dep += (self.eos.to_TP(T, P).S_dep_l - self._eos_T_101325.S_dep_l) - + elif self.phase_ref == 'l' and self.phase == 'g': S_dep += self.S_dep_T_ref_Pb - self.S_dep_ref_l S_dep += (self.eos.to_TP(T, P).S_dep_g - self.S_dep_Tb_Pb_g) @@ -908,23 +908,23 @@ def calc_S(self, T, P): if self.phase == self.phase_ref: S += integrators_T[self.phase](self.T_ref, T) if self.phase in ['l', 'g']: - S += -R*log(P/self.P_ref) - + S += -R*log(P/self.P_ref) + elif self.phase_ref == 's' and self.phase == 'l': S += self.S_int_T_ref_s_to_Tm + self.Hfusm/self.Tm + integrators_T['l'](self.Tm, T) - + elif self.phase_ref == 'l' and self.phase == 's': S += - self.S_int_l_Tm_to_T_ref_l - self.Hfusm/self.Tm + integrators_T['s'](self.Tm, T) - + elif self.phase_ref == 'l' and self.phase == 'g': S += self.S_int_l_T_ref_l_to_Tb + self.Hvap_Tbm/self.Tb + integrators_T['g'](self.Tb, T) -R*log(P/self.P_ref) # TODO add to other states - + elif self.phase_ref == 'g' and self.phase == 'l': S += - self.S_int_Tb_to_T_ref_g - self.Hvapm/self.Tb + integrators_T['l'](self.Tb, T) - + elif self.phase_ref == 's' and self.phase == 'g': S += self.S_int_T_ref_s_to_Tm + self.Hfusm/self.Tm + self.S_int_l_Tm_to_Tb + self.Hvap_Tbm/self.Tb + integrators_T['g'](self.Tb, T) - + elif self.phase_ref == 'g' and self.phase == 's': S += - self.S_int_Tb_to_T_ref_g - self.Hvap_Tbm/self.Tb - self.S_int_l_Tm_to_Tb - self.Hfusm/self.Tm + integrators_T['s'](self.Tm, T) else: @@ -960,76 +960,76 @@ def to_solve(T): def set_thermo(self): try: self._eos_T_101325 = self.eos.to_TP(self.T, 101325) - - + + self.Hm = self.calc_H(self.T, self.P) self.Hm += self.calc_H_excess(self.T, self.P) self.H = property_molar_to_mass(self.Hm, self.MW) if (self.Hm is not None) else None - - self.Sm = self.calc_S(self.T, self.P) + + self.Sm = self.calc_S(self.T, self.P) self.Sm += self.calc_S_excess(self.T, self.P) self.S = property_molar_to_mass(self.Sm, self.MW) if (self.Sm is not None) else None - - self.G = self.H - self.T*self.S if (self.H is not None and self.S is not None) else None - self.Gm = self.Hm - self.T*self.Sm if (self.Hm is not None and self.Sm is not None) else None + + self.G = self.H - self.T*self.S if (self.H is not None and self.S is not None) else None + self.Gm = self.Hm - self.T*self.Sm if (self.Hm is not None and self.Sm is not None) else None except: pass @property def Um(self): r'''Internal energy of the chemical at its current temperature and - pressure, in units of J/mol. - + pressure, in units of J/mol. + This property requires that :obj:`thermo.chemical.set_thermo` ran successfully to be accurate. It also depends on the molar volume of the chemical at its current conditions. ''' return self.Hm - self.P*self.Vm if (self.Vm and self.Hm is not None) else None - + @property def U(self): r'''Internal energy of the chemical at its current temperature and - pressure, in units of J/kg. - + pressure, in units of J/kg. + This property requires that :obj:`thermo.chemical.set_thermo` ran successfully to be accurate. It also depends on the molar volume of the chemical at its current conditions. ''' return property_molar_to_mass(self.Um, self.MW) if (self.Um is not None) else None - + @property def Am(self): r'''Helmholtz energy of the chemical at its current temperature and - pressure, in units of J/mol. - + pressure, in units of J/mol. + This property requires that :obj:`thermo.chemical.set_thermo` ran successfully to be accurate. It also depends on the molar volume of the chemical at its current conditions. ''' return self.Um - self.T*self.Sm if (self.Um is not None and self.Sm is not None) else None - + @property def A(self): r'''Helmholtz energy of the chemical at its current temperature and - pressure, in units of J/kg. - + pressure, in units of J/kg. + This property requires that :obj:`thermo.chemical.set_thermo` ran successfully to be accurate. It also depends on the molar volume of the chemical at its current conditions. ''' return self.U - self.T*self.S if (self.U is not None and self.S is not None) else None - - + + ### Temperature independent properties - calculate lazily @property def charge(self): r'''Charge of a chemical, computed with RDKit from a chemical's SMILES. If RDKit is not available, holds None. - + Examples -------- >>> Chemical('sodium ion').charge @@ -1039,12 +1039,12 @@ def charge(self): return Chem.GetFormalCharge(self.rdkitmol) except: return None - + @property def rings(self): - r'''Number of rings in a chemical, computed with RDKit from a + r'''Number of rings in a chemical, computed with RDKit from a chemical's SMILES. If RDKit is not available, holds None. - + Examples -------- >>> Chemical('Paclitaxel').rings @@ -1057,9 +1057,9 @@ def rings(self): @property def aromatic_rings(self): - r'''Number of aromatic rings in a chemical, computed with RDKit from a + r'''Number of aromatic rings in a chemical, computed with RDKit from a chemical's SMILES. If RDKit is not available, holds None. - + Examples -------- >>> Chemical('Paclitaxel').aromatic_rings @@ -1069,12 +1069,12 @@ def aromatic_rings(self): return Chem.Descriptors.NumAromaticRings(self.rdkitmol) except: return None - + @property def rdkitmol(self): - r'''RDKit object of the chemical, without hydrogen. If RDKit is not + r'''RDKit object of the chemical, without hydrogen. If RDKit is not available, holds None. - + For examples of what can be done with RDKit, see `their website `_. ''' @@ -1089,9 +1089,9 @@ def rdkitmol(self): @property def rdkitmol_Hs(self): - r'''RDKit object of the chemical, with hydrogen. If RDKit is not + r'''RDKit object of the chemical, with hydrogen. If RDKit is not available, holds None. - + For examples of what can be done with RDKit, see `their website `_. ''' @@ -1108,7 +1108,7 @@ def rdkitmol_Hs(self): def Hill(self): r'''Hill formula of a compound. For a description of the Hill system, see :obj:`thermo.elements.atoms_to_Hill`. - + Examples -------- >>> Chemical('furfuryl alcohol').Hill @@ -1122,10 +1122,10 @@ def Hill(self): @property def atom_fractions(self): - r'''Dictionary of atom:fractional occurence of the elements in a - chemical. Useful when performing element balances. For mass-fraction + r'''Dictionary of atom:fractional occurence of the elements in a + chemical. Useful when performing element balances. For mass-fraction occurences, see :obj:`mass_fractions`. - + Examples -------- >>> Chemical('Ammonium aluminium sulfate').atom_fractions @@ -1139,10 +1139,10 @@ def atom_fractions(self): @property def mass_fractions(self): - r'''Dictionary of atom:mass-weighted fractional occurence of elements. + r'''Dictionary of atom:mass-weighted fractional occurence of elements. Useful when performing mass balances. For atom-fraction occurences, see :obj:`atom_fractions`. - + Examples -------- >>> Chemical('water').mass_fractions @@ -1157,7 +1157,7 @@ def mass_fractions(self): @property def legal_status(self): r'''Dictionary of legal status indicators for the chemical. - + Examples -------- >>> pprint(Chemical('benzene').legal_status) @@ -1176,7 +1176,7 @@ def legal_status(self): @property def economic_status(self): r'''Dictionary of economic status indicators for the chemical. - + Examples -------- >>> pprint(Chemical('benzene').economic_status) @@ -1191,12 +1191,12 @@ def economic_status(self): self.__economic_status = economic_status(self.CAS, Method='Combined') return self.__economic_status - + @property def UNIFAC_groups(self): r'''Dictionary of UNIFAC subgroup: count groups for the original UNIFAC subgroups, as determined by `DDBST's online service `_. - + Examples -------- >>> pprint(Chemical('Cumene').UNIFAC_groups) @@ -1216,7 +1216,7 @@ def UNIFAC_groups(self): def UNIFAC_Dortmund_groups(self): r'''Dictionary of Dortmund UNIFAC subgroup: count groups for the Dortmund UNIFAC subgroups, as determined by `DDBST's online service `_. - + Examples -------- >>> pprint(Chemical('Cumene').UNIFAC_Dortmund_groups) @@ -1234,9 +1234,9 @@ def UNIFAC_Dortmund_groups(self): @property def PSRK_groups(self): - r'''Dictionary of PSRK subgroup: count groups for the PSRK subgroups, + r'''Dictionary of PSRK subgroup: count groups for the PSRK subgroups, as determined by `DDBST's online service `_. - + Examples -------- >>> pprint(Chemical('Cumene').PSRK_groups) @@ -1256,7 +1256,7 @@ def PSRK_groups(self): def UNIFAC_R(self): r'''UNIFAC `R` (normalized Van der Waals volume), dimensionless. Used in the UNIFAC model. - + Examples -------- >>> Chemical('benzene').UNIFAC_R @@ -1270,7 +1270,7 @@ def UNIFAC_R(self): def UNIFAC_Q(self): r'''UNIFAC `Q` (normalized Van der Waals area), dimensionless. Used in the UNIFAC model. - + Examples -------- >>> Chemical('decane').UNIFAC_Q @@ -1309,12 +1309,12 @@ def Van_der_Waals_area(self): ### One phase properties - calculate lazily @property def Psat(self): - r'''Vapor pressure of the chemical at its current temperature, in units - of Pa. For calculation of this property at other temperatures, - or specifying manually the method used to calculate it, and more - see + r'''Vapor pressure of the chemical at its current temperature, in units + of Pa. For calculation of this property at other temperatures, + or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.vapor_pressure.VaporPressure`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- >>> Chemical('water', T=320).Psat @@ -1328,13 +1328,13 @@ def Psat(self): @property def Hvapm(self): - r'''Enthalpy of vaporization of the chemical at its current temperature, - in units of J/mol. For calculation of this property at other - temperatures, or specifying manually the method used to calculate it, + r'''Enthalpy of vaporization of the chemical at its current temperature, + in units of J/mol. For calculation of this property at other + temperatures, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.phase_change.EnthalpyVaporization`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- >>> Chemical('water', T=320).Hvapm @@ -1345,16 +1345,16 @@ def Hvapm(self): set(['VDI_PPDS', 'MORGAN_KOBAYASHI', 'VETERE', 'VELASCO', 'LIU', 'COOLPROP', 'CRC_HVAP_298', 'CLAPEYRON', 'SIVARAMAN_MAGEE_KOBAYASHI', 'ALIBAKHSHI', 'DIPPR_PERRY_8E', 'RIEDEL', 'CHEN', 'PITZER', 'CRC_HVAP_TB']) ''' return self.EnthalpyVaporization(self.T) - + @property def Hvap(self): - r'''Enthalpy of vaporization of the chemical at its current temperature, - in units of J/kg. - - This property uses the object-oriented interface - :obj:`thermo.phase_change.EnthalpyVaporization`, but converts its + r'''Enthalpy of vaporization of the chemical at its current temperature, + in units of J/kg. + + This property uses the object-oriented interface + :obj:`thermo.phase_change.EnthalpyVaporization`, but converts its results from molar to mass units. - + Examples -------- >>> Chemical('water', T=320).Hvap @@ -1367,13 +1367,13 @@ def Hvap(self): @property def Cpsm(self): - r'''Solid-phase heat capacity of the chemical at its current temperature, - in units of J/mol/K. For calculation of this property at other - temperatures, or specifying manually the method used to calculate it, + r'''Solid-phase heat capacity of the chemical at its current temperature, + in units of J/mol/K. For calculation of this property at other + temperatures, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.heat_capacity.HeatCapacitySolid`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- >>> Chemical('palladium').Cpsm @@ -1384,24 +1384,24 @@ def Cpsm(self): set(["Perry's Table 2-151", 'CRC Standard Thermodynamic Properties of Chemical Substances', 'Lastovka, Fulem, Becerra and Shaw (2008)']) ''' return self.HeatCapacitySolid(self.T) - + @property def Cplm(self): - r'''Liquid-phase heat capacity of the chemical at its current temperature, - in units of J/mol/K. For calculation of this property at other - temperatures, or specifying manually the method used to calculate it, + r'''Liquid-phase heat capacity of the chemical at its current temperature, + in units of J/mol/K. For calculation of this property at other + temperatures, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.heat_capacity.HeatCapacityLiquid`; each Chemical instance creates one to actually perform the calculations. - + Notes ----- Some methods give heat capacity along the saturation line, some at - 1 atm but only up to the normal boiling point, and some give heat + 1 atm but only up to the normal boiling point, and some give heat capacity at 1 atm up to the normal boiling point and then along the - saturation line. Real-liquid heat capacity is pressure dependent, but + saturation line. Real-liquid heat capacity is pressure dependent, but this interface is not. - + Examples -------- >>> Chemical('water').Cplm @@ -1412,16 +1412,16 @@ def Cplm(self): 1505.0619005000553 ''' return self.HeatCapacityLiquid(self.T) - + @property def Cpgm(self): - r'''Gas-phase ideal gas heat capacity of the chemical at its current - temperature, in units of J/mol/K. For calculation of this property at - other temperatures, or specifying manually the method used to calculate + r'''Gas-phase ideal gas heat capacity of the chemical at its current + temperature, in units of J/mol/K. For calculation of this property at + other temperatures, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.heat_capacity.HeatCapacityGas`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- >>> Chemical('water').Cpgm @@ -1432,17 +1432,17 @@ def Cpgm(self): 672.6480417835064 ''' return self.HeatCapacityGas(self.T) - + @property def Cps(self): - r'''Solid-phase heat capacity of the chemical at its current temperature, - in units of J/kg/K. For calculation of this property at other - temperatures, or specifying manually the method used to calculate it, + r'''Solid-phase heat capacity of the chemical at its current temperature, + in units of J/kg/K. For calculation of this property at other + temperatures, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.heat_capacity.HeatCapacitySolid`; each Chemical instance - creates one to actually perform the calculations. Note that that + creates one to actually perform the calculations. Note that that interface provides output in molar units. - + Examples -------- >>> Chemical('palladium', T=400).Cps @@ -1459,22 +1459,22 @@ def Cps(self): @property def Cpl(self): - r'''Liquid-phase heat capacity of the chemical at its current temperature, - in units of J/kg/K. For calculation of this property at other - temperatures, or specifying manually the method used to calculate it, + r'''Liquid-phase heat capacity of the chemical at its current temperature, + in units of J/kg/K. For calculation of this property at other + temperatures, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.heat_capacity.HeatCapacityLiquid`; each Chemical instance - creates one to actually perform the calculations. Note that that + creates one to actually perform the calculations. Note that that interface provides output in molar units. - + Examples -------- >>> Chemical('water', T=320).Cpl 4177.518996988284 - + Ideal entropy change of water from 280 K to 340 K, output converted back to mass-based units of J/kg/K. - + >>> dSm = Chemical('water').HeatCapacityLiquid.T_dependent_property_integral_over_T(280, 340) >>> property_molar_to_mass(dSm, Chemical('water').MW) 812.1024585274956 @@ -1486,16 +1486,16 @@ def Cpl(self): @property def Cpg(self): - r'''Gas-phase heat capacity of the chemical at its current temperature, - in units of J/kg/K. For calculation of this property at other - temperatures, or specifying manually the method used to calculate it, + r'''Gas-phase heat capacity of the chemical at its current temperature, + in units of J/kg/K. For calculation of this property at other + temperatures, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.heat_capacity.HeatCapacityGas`; each Chemical instance - creates one to actually perform the calculations. Note that that + creates one to actually perform the calculations. Note that that interface provides output in molar units. - + Examples - -------- + -------- >>> w = Chemical('water', T=520) >>> w.Cpg 1967.6698314620658 @@ -1504,14 +1504,14 @@ def Cpg(self): if Cpgm: return property_molar_to_mass(Cpgm, self.MW) return None - + @property def Cvgm(self): - r'''Gas-phase ideal-gas contant-volume heat capacity of the chemical at + r'''Gas-phase ideal-gas contant-volume heat capacity of the chemical at its current temperature, in units of J/mol/K. Subtracts R from - the ideal-gas heat capacity; does not include pressure-compensation + the ideal-gas heat capacity; does not include pressure-compensation from an equation of state. - + Examples -------- >>> w = Chemical('water', T=520) @@ -1522,14 +1522,14 @@ def Cvgm(self): if Cpgm: return Cpgm - R return None - + @property def Cvg(self): - r'''Gas-phase ideal-gas contant-volume heat capacity of the chemical at + r'''Gas-phase ideal-gas contant-volume heat capacity of the chemical at its current temperature, in units of J/kg/K. Subtracts R from - the ideal-gas heat capacity; does not include pressure-compensation + the ideal-gas heat capacity; does not include pressure-compensation from an equation of state. - + Examples -------- >>> w = Chemical('water', T=520) @@ -1540,13 +1540,13 @@ def Cvg(self): if Cvgm: return property_molar_to_mass(Cvgm, self.MW) return None - + @property def isentropic_exponent(self): - r'''Gas-phase ideal-gas isentropic exponent of the chemical at its - current temperature, dimensionless. Does not include + r'''Gas-phase ideal-gas isentropic exponent of the chemical at its + current temperature, dimensionless. Does not include pressure-compensation from an equation of state. - + Examples -------- >>> Chemical('hydrogen').isentropic_exponent @@ -1556,53 +1556,53 @@ def isentropic_exponent(self): if all((Cp, Cv)): return isentropic_exponent(Cp, Cv) return None - + @property def Vms(self): r'''Solid-phase molar volume of the chemical at its current - temperature, in units of mol/m^3. For calculation of this property at - other temperatures, or specifying manually the method used to calculate + temperature, in units of mol/m^3. For calculation of this property at + other temperatures, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.volume.VolumeSolid`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- >>> Chemical('iron').Vms 7.09593392630242e-06 ''' return self.VolumeSolid(self.T) - + @property def Vml(self): r'''Liquid-phase molar volume of the chemical at its current - temperature and pressure, in units of mol/m^3. For calculation of this + temperature and pressure, in units of mol/m^3. For calculation of this property at other temperatures or pressures, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.volume.VolumeLiquid`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- >>> Chemical('cyclobutane', T=225).Vml 7.42395423425395e-05 ''' return self.VolumeLiquid(self.T, self.P) - + @property def Vmg(self): r'''Gas-phase molar volume of the chemical at its current - temperature and pressure, in units of mol/m^3. For calculation of this + temperature and pressure, in units of mol/m^3. For calculation of this property at other temperatures or pressures, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.volume.VolumeGas`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- Estimate the molar volume of the core of the sun, at 15 million K and 26.5 PetaPascals, assuming pure helium (actually 68% helium): - + >>> Chemical('helium', T=15E6, P=26.5E15).Vmg 4.805464238181197e-07 ''' @@ -1611,15 +1611,15 @@ def Vmg(self): @property def rhos(self): r'''Solid-phase mass density of the chemical at its current temperature, - in units of kg/m^3. For calculation of this property at + in units of kg/m^3. For calculation of this property at other temperatures, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.volume.VolumeSolid`; each Chemical instance - creates one to actually perform the calculations. Note that that + creates one to actually perform the calculations. Note that that interface provides output in molar units. - + Examples - -------- + -------- >>> Chemical('iron').rhos 7869.999999999994 ''' @@ -1630,16 +1630,16 @@ def rhos(self): @property def rhol(self): - r'''Liquid-phase mass density of the chemical at its current - temperature and pressure, in units of kg/m^3. For calculation of this - property at other temperatures and pressures, or specifying manually - the method used to calculate it, and more - see the object oriented + r'''Liquid-phase mass density of the chemical at its current + temperature and pressure, in units of kg/m^3. For calculation of this + property at other temperatures and pressures, or specifying manually + the method used to calculate it, and more - see the object oriented interface :obj:`thermo.volume.VolumeLiquid`; each Chemical instance - creates one to actually perform the calculations. Note that that + creates one to actually perform the calculations. Note that that interface provides output in molar units. - + Examples - -------- + -------- >>> Chemical('o-xylene', T=297).rhol 876.9946785618097 ''' @@ -1647,34 +1647,34 @@ def rhol(self): if Vml: return Vm_to_rho(Vml, self.MW) return None - + @property def rhog(self): r'''Gas-phase mass density of the chemical at its current temperature - and pressure, in units of kg/m^3. For calculation of this property at + and pressure, in units of kg/m^3. For calculation of this property at other temperatures or pressures, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.volume.VolumeGas`; each Chemical instance - creates one to actually perform the calculations. Note that that + creates one to actually perform the calculations. Note that that interface provides output in molar units. - + Examples - -------- + -------- Estimate the density of the core of the sun, at 15 million K and 26.5 PetaPascals, assuming pure helium (actually 68% helium): - + >>> Chemical('helium', T=15E6, P=26.5E15).rhog 8329.27226509739 - - Compared to a result on - `Wikipedia `_ of 150000 + + Compared to a result on + `Wikipedia `_ of 150000 kg/m^3, the fundamental equation of state performs poorly. - + >>> He = Chemical('helium', T=15E6, P=26.5E15) >>> He.VolumeGas.set_user_methods_P(['IDEAL']); He.rhog 850477.8065477367 - - The ideal-gas law performs somewhat better, but vastly overshoots + + The ideal-gas law performs somewhat better, but vastly overshoots the density prediction. ''' Vmg = self.Vmg @@ -1686,11 +1686,11 @@ def rhog(self): def rhosm(self): r'''Molar density of the chemical in the solid phase at the current temperature and pressure, in units of mol/m^3. - - Utilizes the object oriented interface and - :obj:`thermo.volume.VolumeSolid` to perform the actual calculation of + + Utilizes the object oriented interface and + :obj:`thermo.volume.VolumeSolid` to perform the actual calculation of molar volume. - + Examples -------- >>> Chemical('palladium').rhosm @@ -1705,11 +1705,11 @@ def rhosm(self): def rholm(self): r'''Molar density of the chemical in the liquid phase at the current temperature and pressure, in units of mol/m^3. - - Utilizes the object oriented interface and - :obj:`thermo.volume.VolumeLiquid` to perform the actual calculation of + + Utilizes the object oriented interface and + :obj:`thermo.volume.VolumeLiquid` to perform the actual calculation of molar volume. - + Examples -------- >>> Chemical('nitrogen', T=70).rholm @@ -1717,18 +1717,18 @@ def rholm(self): ''' Vml = self.Vml if Vml: - return 1./Vml + return 1./Vml return None @property def rhogm(self): r'''Molar density of the chemical in the gas phase at the current temperature and pressure, in units of mol/m^3. - - Utilizes the object oriented interface and - :obj:`thermo.volume.VolumeGas` to perform the actual calculation of + + Utilizes the object oriented interface and + :obj:`thermo.volume.VolumeGas` to perform the actual calculation of molar volume. - + Examples -------- >>> Chemical('tungsten hexafluoride').rhogm @@ -1743,11 +1743,11 @@ def rhogm(self): def Zs(self): r'''Compressibility factor of the chemical in the solid phase at the current temperature and pressure, dimensionless. - - Utilizes the object oriented interface and - :obj:`thermo.volume.VolumeSolid` to perform the actual calculation of + + Utilizes the object oriented interface and + :obj:`thermo.volume.VolumeSolid` to perform the actual calculation of molar volume. - + Examples -------- >>> Chemical('palladium').Z @@ -1762,11 +1762,11 @@ def Zs(self): def Zl(self): r'''Compressibility factor of the chemical in the liquid phase at the current temperature and pressure, dimensionless. - - Utilizes the object oriented interface and - :obj:`thermo.volume.VolumeLiquid` to perform the actual calculation of + + Utilizes the object oriented interface and + :obj:`thermo.volume.VolumeLiquid` to perform the actual calculation of molar volume. - + Examples -------- >>> Chemical('water').Zl @@ -1776,16 +1776,16 @@ def Zl(self): if Vml: return Z(self.T, self.P, Vml) return None - + @property def Zg(self): r'''Compressibility factor of the chemical in the gas phase at the current temperature and pressure, dimensionless. - - Utilizes the object oriented interface and - :obj:`thermo.volume.VolumeGas` to perform the actual calculation of + + Utilizes the object oriented interface and + :obj:`thermo.volume.VolumeGas` to perform the actual calculation of molar volume. - + Examples -------- >>> Chemical('sulfur hexafluoride', T=700, P=1E9).Zg @@ -1798,13 +1798,13 @@ def Zg(self): @property def Bvirial(self): - r'''Second virial coefficient of the gas phase of the chemical at its - current temperature and pressure, in units of mol/m^3. - - This property uses the object-oriented interface - :obj:`thermo.volume.VolumeGas`, converting its result with + r'''Second virial coefficient of the gas phase of the chemical at its + current temperature and pressure, in units of mol/m^3. + + This property uses the object-oriented interface + :obj:`thermo.volume.VolumeGas`, converting its result with :obj:`thermo.utils.B_from_Z`. - + Examples -------- >>> Chemical('water').Bvirial @@ -1816,16 +1816,16 @@ def Bvirial(self): @property def isobaric_expansion_l(self): - r'''Isobaric (constant-pressure) expansion of the liquid phase of the + r'''Isobaric (constant-pressure) expansion of the liquid phase of the chemical at its current temperature and pressure, in units of 1/K. - + .. math:: \beta = \frac{1}{V}\left(\frac{\partial V}{\partial T} \right)_P - Utilizes the temperature-derivative method of + Utilizes the temperature-derivative method of :obj:`thermo.volume.VolumeLiquid` to perform the actual calculation. The derivatives are all numerical. - + Examples -------- >>> Chemical('dodecane', T=400).isobaric_expansion_l @@ -1835,19 +1835,19 @@ def isobaric_expansion_l(self): Vm = self.Vml if dV_dT and Vm: return isobaric_expansion(V=Vm, dV_dT=dV_dT) - + @property def isobaric_expansion_g(self): - r'''Isobaric (constant-pressure) expansion of the gas phase of the + r'''Isobaric (constant-pressure) expansion of the gas phase of the chemical at its current temperature and pressure, in units of 1/K. - + .. math:: \beta = \frac{1}{V}\left(\frac{\partial V}{\partial T} \right)_P - Utilizes the temperature-derivative method of + Utilizes the temperature-derivative method of :obj:`thermo.VolumeGas` to perform the actual calculation. The derivatives are all numerical. - + Examples -------- >>> Chemical('Hexachlorobenzene', T=900).isobaric_expansion_g @@ -1861,14 +1861,14 @@ def isobaric_expansion_g(self): @property def mul(self): r'''Viscosity of the chemical in the liquid phase at its current - temperature and pressure, in units of Pa*s. - + temperature and pressure, in units of Pa*s. + For calculation of this property at other temperatures and pressures, - or specifying manually the method used to calculate it, and more - see + or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.viscosity.ViscosityLiquid`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- >>> Chemical('water', T=320).mul @@ -1879,14 +1879,14 @@ def mul(self): @property def mug(self): r'''Viscosity of the chemical in the gas phase at its current - temperature and pressure, in units of Pa*s. - + temperature and pressure, in units of Pa*s. + For calculation of this property at other temperatures and pressures, - or specifying manually the method used to calculate it, and more - see + or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.viscosity.ViscosityGas`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- >>> Chemical('water', T=320, P=100).mug @@ -1896,15 +1896,15 @@ def mug(self): @property def kl(self): - r'''Thermal conductivity of the chemical in the liquid phase at its - current temperature and pressure, in units of W/m/K. - + r'''Thermal conductivity of the chemical in the liquid phase at its + current temperature and pressure, in units of W/m/K. + For calculation of this property at other temperatures and pressures, - or specifying manually the method used to calculate it, and more - see + or specifying manually the method used to calculate it, and more - see the object oriented interface - :obj:`thermo.thermal_conductivity.ThermalConductivityLiquid`; each + :obj:`thermo.thermal_conductivity.ThermalConductivityLiquid`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- >>> Chemical('water', T=320).kl @@ -1914,15 +1914,15 @@ def kl(self): @property def kg(self): - r'''Thermal conductivity of the chemical in the gas phase at its - current temperature and pressure, in units of W/m/K. - + r'''Thermal conductivity of the chemical in the gas phase at its + current temperature and pressure, in units of W/m/K. + For calculation of this property at other temperatures and pressures, - or specifying manually the method used to calculate it, and more - see + or specifying manually the method used to calculate it, and more - see the object oriented interface - :obj:`thermo.thermal_conductivity.ThermalConductivityGas`; each + :obj:`thermo.thermal_conductivity.ThermalConductivityGas`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- >>> Chemical('water', T=320).kg @@ -1932,14 +1932,14 @@ def kg(self): @property def sigma(self): - r'''Surface tension of the chemical at its current temperature, in - units of N/m. - + r'''Surface tension of the chemical at its current temperature, in + units of N/m. + For calculation of this property at other temperatures, - or specifying manually the method used to calculate it, and more - see - the object oriented interface :obj:`thermo.interface.SurfaceTension`; + or specifying manually the method used to calculate it, and more - see + the object oriented interface :obj:`thermo.interface.SurfaceTension`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- >>> Chemical('water', T=320).sigma @@ -1951,14 +1951,14 @@ def sigma(self): @property def permittivity(self): - r'''Relative permittivity of the chemical at its current temperature, + r'''Relative permittivity of the chemical at its current temperature, dimensionless. - + For calculation of this property at other temperatures, - or specifying manually the method used to calculate it, and more - see - the object oriented interface :obj:`thermo.permittivity.Permittivity`; + or specifying manually the method used to calculate it, and more - see + the object oriented interface :obj:`thermo.permittivity.Permittivity`; each Chemical instance creates one to actually perform the calculations. - + Examples -------- >>> Chemical('toluene', T=250).permittivity @@ -1970,17 +1970,17 @@ def permittivity(self): def JTl(self): r'''Joule Thomson coefficient of the chemical in the liquid phase at its current temperature and pressure, in units of K/Pa. - + .. math:: \mu_{JT} = \left(\frac{\partial T}{\partial P}\right)_H = \frac{1}{C_p} \left[T \left(\frac{\partial V}{\partial T}\right)_P - V\right] = \frac{V}{C_p}\left(\beta T-1\right) - Utilizes the temperature-derivative method of - :obj:`thermo.volume.VolumeLiquid` and the temperature-dependent heat + Utilizes the temperature-derivative method of + :obj:`thermo.volume.VolumeLiquid` and the temperature-dependent heat capacity method :obj:`thermo.heat_capacity.HeatCapacityLiquid` to obtain the properties required for the actual calculation. - + Examples -------- >>> Chemical('dodecane', T=400).JTl @@ -1990,22 +1990,22 @@ def JTl(self): if all((Vml, Cplm, isobaric_expansion_l)): return Joule_Thomson(T=self.T, V=Vml, Cp=Cplm, beta=isobaric_expansion_l) return None - + @property def JTg(self): r'''Joule Thomson coefficient of the chemical in the gas phase at its current temperature and pressure, in units of K/Pa. - + .. math:: \mu_{JT} = \left(\frac{\partial T}{\partial P}\right)_H = \frac{1}{C_p} \left[T \left(\frac{\partial V}{\partial T}\right)_P - V\right] = \frac{V}{C_p}\left(\beta T-1\right) - Utilizes the temperature-derivative method of - :obj:`thermo.volume.VolumeGas` and the temperature-dependent heat + Utilizes the temperature-derivative method of + :obj:`thermo.volume.VolumeGas` and the temperature-dependent heat capacity method :obj:`thermo.heat_capacity.HeatCapacityGas` to obtain the properties required for the actual calculation. - + Examples -------- >>> Chemical('dodecane', T=400, P=1000).JTg @@ -2018,17 +2018,17 @@ def JTg(self): @property def nul(self): - r'''Kinematic viscosity of the liquid phase of the chemical at its + r'''Kinematic viscosity of the liquid phase of the chemical at its current temperature and pressure, in units of m^2/s. - + .. math:: \nu = \frac{\mu}{\rho} Utilizes the temperature and pressure dependent object oriented - interfaces :obj:`thermo.volume.VolumeLiquid`, - :obj:`thermo.viscosity.ViscosityLiquid` to calculate the + interfaces :obj:`thermo.volume.VolumeLiquid`, + :obj:`thermo.viscosity.ViscosityLiquid` to calculate the actual properties. - + Examples -------- >>> Chemical('methane', T=110).nul @@ -2041,17 +2041,17 @@ def nul(self): @property def nug(self): - r'''Kinematic viscosity of the gas phase of the chemical at its + r'''Kinematic viscosity of the gas phase of the chemical at its current temperature and pressure, in units of m^2/s. - + .. math:: \nu = \frac{\mu}{\rho} Utilizes the temperature and pressure dependent object oriented - interfaces :obj:`thermo.volume.VolumeGas`, - :obj:`thermo.viscosity.ViscosityGas` to calculate the + interfaces :obj:`thermo.volume.VolumeGas`, + :obj:`thermo.viscosity.ViscosityGas` to calculate the actual properties. - + Examples -------- >>> Chemical('methane', T=115).nug @@ -2064,18 +2064,18 @@ def nug(self): @property def alphal(self): - r'''Thermal diffusivity of the liquid phase of the chemical at its + r'''Thermal diffusivity of the liquid phase of the chemical at its current temperature and pressure, in units of m^2/s. - + .. math:: \alpha = \frac{k}{\rho Cp} Utilizes the temperature and pressure dependent object oriented - interfaces :obj:`thermo.volume.VolumeLiquid`, + interfaces :obj:`thermo.volume.VolumeLiquid`, :obj:`thermo.thermal_conductivity.ThermalConductivityLiquid`, - and :obj:`thermo.heat_capacity.HeatCapacityLiquid` to calculate the + and :obj:`thermo.heat_capacity.HeatCapacityLiquid` to calculate the actual properties. - + Examples -------- >>> Chemical('nitrogen', T=70).alphal @@ -2085,21 +2085,21 @@ def alphal(self): if all([kl, rhol, Cpl]): return thermal_diffusivity(k=kl, rho=rhol, Cp=Cpl) return None - + @property def alphag(self): - r'''Thermal diffusivity of the gas phase of the chemical at its + r'''Thermal diffusivity of the gas phase of the chemical at its current temperature and pressure, in units of m^2/s. - + .. math:: \alpha = \frac{k}{\rho Cp} Utilizes the temperature and pressure dependent object oriented - interfaces :obj:`thermo.volume.VolumeGas`, + interfaces :obj:`thermo.volume.VolumeGas`, :obj:`thermo.thermal_conductivity.ThermalConductivityGas`, - and :obj:`thermo.heat_capacity.HeatCapacityGas` to calculate the + and :obj:`thermo.heat_capacity.HeatCapacityGas` to calculate the actual properties. - + Examples -------- >>> Chemical('ammonia').alphag @@ -2112,18 +2112,18 @@ def alphag(self): @property def Prl(self): - r'''Prandtl number of the liquid phase of the chemical at its + r'''Prandtl number of the liquid phase of the chemical at its current temperature and pressure, dimensionless. - + .. math:: Pr = \frac{C_p \mu}{k} - + Utilizes the temperature and pressure dependent object oriented interfaces :obj:`thermo.viscosity.ViscosityLiquid`, :obj:`thermo.thermal_conductivity.ThermalConductivityLiquid`, - and :obj:`thermo.heat_capacity.HeatCapacityLiquid` to calculate the + and :obj:`thermo.heat_capacity.HeatCapacityLiquid` to calculate the actual properties. - + Examples -------- >>> Chemical('nitrogen', T=70).Prl @@ -2136,18 +2136,18 @@ def Prl(self): @property def Prg(self): - r'''Prandtl number of the gas phase of the chemical at its + r'''Prandtl number of the gas phase of the chemical at its current temperature and pressure, dimensionless. - + .. math:: Pr = \frac{C_p \mu}{k} - + Utilizes the temperature and pressure dependent object oriented interfaces :obj:`thermo.viscosity.ViscosityGas`, :obj:`thermo.thermal_conductivity.ThermalConductivityGas`, - and :obj:`thermo.heat_capacity.HeatCapacityGas` to calculate the + and :obj:`thermo.heat_capacity.HeatCapacityGas` to calculate the actual properties. - + Examples -------- >>> Chemical('NH3').Prg @@ -2160,37 +2160,37 @@ def Prg(self): @property def solubility_parameter(self): - r'''Solubility parameter of the chemical at its + r'''Solubility parameter of the chemical at its current temperature and pressure, in units of Pa^0.5. - + .. math:: \delta = \sqrt{\frac{\Delta H_{vap} - RT}{V_m}} - + Calculated based on enthalpy of vaporization and molar volume. Normally calculated at STP. For uses of this property, see :obj:`thermo.solubility.solubility_parameter`. - + Examples -------- >>> Chemical('NH3').solubility_parameter 24766.329043856073 ''' - return solubility_parameter(T=self.T, Hvapm=self.Hvapm, Vml=self.Vml, - Method=self.solubility_parameter_method, + return solubility_parameter(T=self.T, Hvapm=self.Hvapm, Vml=self.Vml, + Method=self.solubility_parameter_method, CASRN=self.CAS) - @property + @property def Parachor(self): - r'''Parachor of the chemical at its + r'''Parachor of the chemical at its current temperature and pressure, in units of N^0.25*m^2.75/mol. - + .. math:: P = \frac{\sigma^{0.25} MW}{\rho_L - \rho_V} - + Calculated based on surface tension, density of the liquid and gas phase, and molecular weight. For uses of this property, see :obj:`thermo.utils.Parachor`. - + Examples -------- >>> Chemical('octane').Parachor @@ -2200,21 +2200,21 @@ def Parachor(self): if all((sigma, rhol, rhog, self.MW)): return Parachor(sigma=sigma, MW=self.MW, rhol=rhol, rhog=rhog) return None - - + + ### Single-phase properties @property def Cp(self): r'''Mass heat capacity of the chemical at its current phase and temperature, in units of J/kg/K. - - Utilizes the object oriented interfaces + + Utilizes the object oriented interfaces :obj:`thermo.heat_capacity.HeatCapacitySolid`, :obj:`thermo.heat_capacity.HeatCapacityLiquid`, - and :obj:`thermo.heat_capacity.HeatCapacityGas` to perform the + and :obj:`thermo.heat_capacity.HeatCapacityGas` to perform the actual calculation of each property. Note that those interfaces provide output in molar units (J/mol/K). - + Examples -------- >>> w = Chemical('water') @@ -2224,18 +2224,18 @@ def Cp(self): 234.26767209171211 ''' return phase_select_property(phase=self.phase, s=self.Cps, l=self.Cpl, g=self.Cpg) - + @property def Cpm(self): r'''Molar heat capacity of the chemical at its current phase and temperature, in units of J/mol/K. - - Utilizes the object oriented interfaces + + Utilizes the object oriented interfaces :obj:`thermo.heat_capacity.HeatCapacitySolid`, :obj:`thermo.heat_capacity.HeatCapacityLiquid`, - and :obj:`thermo.heat_capacity.HeatCapacityGas` to perform the + and :obj:`thermo.heat_capacity.HeatCapacityGas` to perform the actual calculation of each property. - + Examples -------- >>> Chemical('cubane').Cpm @@ -2249,63 +2249,63 @@ def Cpm(self): def Vm(self): r'''Molar volume of the chemical at its current phase and temperature and pressure, in units of m^3/mol. - - Utilizes the object oriented interfaces + + Utilizes the object oriented interfaces :obj:`thermo.volume.VolumeSolid`, :obj:`thermo.volume.VolumeLiquid`, - and :obj:`thermo.volume.VolumeGas` to perform the + and :obj:`thermo.volume.VolumeGas` to perform the actual calculation of each property. - + Examples -------- >>> Chemical('ethylbenzene', T=550, P=3E6).Vm 0.00017758024401627633 ''' return phase_select_property(phase=self.phase, s=self.Vms, l=self.Vml, g=self.Vmg) - + @property def rho(self): r'''Mass density of the chemical at its current phase and temperature and pressure, in units of kg/m^3. - - Utilizes the object oriented interfaces + + Utilizes the object oriented interfaces :obj:`thermo.volume.VolumeSolid`, :obj:`thermo.volume.VolumeLiquid`, - and :obj:`thermo.volume.VolumeGas` to perform the + and :obj:`thermo.volume.VolumeGas` to perform the actual calculation of each property. Note that those interfaces provide output in units of m^3/mol. - + Examples -------- >>> Chemical('decane', T=550, P=2E6).rho 498.6549441720744 ''' return phase_select_property(phase=self.phase, s=self.rhos, l=self.rhol, g=self.rhog) - + @property def rhom(self): r'''Molar density of the chemical at its current phase and temperature and pressure, in units of mol/m^3. - - Utilizes the object oriented interfaces + + Utilizes the object oriented interfaces :obj:`thermo.volume.VolumeSolid`, :obj:`thermo.volume.VolumeLiquid`, - and :obj:`thermo.volume.VolumeGas` to perform the + and :obj:`thermo.volume.VolumeGas` to perform the actual calculation of each property. Note that those interfaces provide output in units of m^3/mol. - + Examples -------- >>> Chemical('1-hexanol').rhom 7983.414573003429 ''' return phase_select_property(phase=self.phase, s=self.rhosm, l=self.rholm, g=self.rhogm) - + @property def Z(self): r'''Compressibility factor of the chemical at its current phase and temperature and pressure, dimensionless. - + Examples -------- >>> Chemical('MTBE', T=900, P=1E-2).Z @@ -2315,20 +2315,20 @@ def Z(self): if Vm: return Z(self.T, self.P, Vm) return None - + @property def isobaric_expansion(self): r'''Isobaric (constant-pressure) expansion of the chemical at its current phase and temperature, in units of 1/K. - + .. math:: \beta = \frac{1}{V}\left(\frac{\partial V}{\partial T} \right)_P - + Examples -------- Radical change in value just above and below the critical temperature of water: - + >>> Chemical('water', T=647.1, P=22048320.0).isobaric_expansion 0.34074205839222449 @@ -2336,12 +2336,12 @@ def isobaric_expansion(self): 0.18143324022215077 ''' return phase_select_property(phase=self.phase, l=self.isobaric_expansion_l, g=self.isobaric_expansion_g) - + @property def JT(self): r'''Joule Thomson coefficient of the chemical at its current phase and temperature, in units of K/Pa. - + .. math:: \mu_{JT} = \left(\frac{\partial T}{\partial P}\right)_H = \frac{1}{C_p} \left[T \left(\frac{\partial V}{\partial T}\right)_P - V\right] @@ -2358,12 +2358,12 @@ def JT(self): def mu(self): r'''Viscosity of the chemical at its current phase, temperature, and pressure in units of Pa*s. - - Utilizes the object oriented interfaces - :obj:`thermo.viscosity.ViscosityLiquid` and - :obj:`thermo.viscosity.ViscosityGas` to perform the + + Utilizes the object oriented interfaces + :obj:`thermo.viscosity.ViscosityLiquid` and + :obj:`thermo.viscosity.ViscosityGas` to perform the actual calculation of each property. - + Examples -------- >>> Chemical('ethanol', T=300).mu @@ -2377,12 +2377,12 @@ def mu(self): def k(self): r'''Thermal conductivity of the chemical at its current phase, temperature, and pressure in units of W/m/K. - - Utilizes the object oriented interfaces - :obj:`thermo.thermal_conductivity.ThermalConductivityLiquid` and - :obj:`thermo.thermal_conductivity.ThermalConductivityGas` to perform + + Utilizes the object oriented interfaces + :obj:`thermo.thermal_conductivity.ThermalConductivityLiquid` and + :obj:`thermo.thermal_conductivity.ThermalConductivityGas` to perform the actual calculation of each property. - + Examples -------- >>> Chemical('ethanol', T=300).kl @@ -2391,27 +2391,27 @@ def k(self): 0.026019924109310026 ''' return phase_select_property(phase=self.phase, s=None, l=self.kl, g=self.kg) - + @property def nu(self): r'''Kinematic viscosity of the the chemical at its current temperature, pressure, and phase in units of m^2/s. - + .. math:: \nu = \frac{\mu}{\rho} - + Examples -------- >>> Chemical('argon').nu 1.3846930410865003e-05 ''' return phase_select_property(phase=self.phase, l=self.nul, g=self.nug) - + @property def alpha(self): - r'''Thermal diffusivity of the chemical at its current temperature, + r'''Thermal diffusivity of the chemical at its current temperature, pressure, and phase in units of m^2/s. - + .. math:: \alpha = \frac{k}{\rho Cp} @@ -2421,15 +2421,15 @@ def alpha(self): 7.672866198927953e-08 ''' return phase_select_property(phase=self.phase, l=self.alphal, g=self.alphag) - + @property def Pr(self): - r'''Prandtl number of the chemical at its current temperature, + r'''Prandtl number of the chemical at its current temperature, pressure, and phase; dimensionless. - + .. math:: Pr = \frac{C_p \mu}{k} - + Examples -------- >>> Chemical('acetone').Pr @@ -2439,30 +2439,30 @@ def Pr(self): @property def Poynting(self): - r'''Poynting correction factor for use in phase equilibria + r'''Poynting correction factor for use in phase equilibria methods based on activity coefficients or other reference states. Performs the shortcut calculation assuming molar volume is independent of pressure. - + .. math:: \text{Poy} = \exp\left[\frac{V_l (P-P^{sat})}{RT}\right] - + The full calculation normally returns values very close to the approximate ones. This property is defined in terms of pure components only. - + Examples -------- >>> Chemical('pentane', T=300, P=1E7).Poynting 1.5743051250679803 - + Notes ----- The full equation shown below can be used as follows: - + .. math:: \text{Poy} = \exp\left[\frac{\int_{P_i^{sat}}^P V_i^l dP}{RT}\right] - + >>> from scipy.integrate import quad >>> c = Chemical('pentane', T=300, P=1E7) >>> exp(quad(lambda P : c.VolumeLiquid(c.T, P), c.Psat, c.P)[0]/R/c.T) @@ -2472,7 +2472,7 @@ def Poynting(self): if Vml and Psat: return exp(Vml*(self.P-Psat)/R/self.T) return None - + def Tsat(self, P): return self.VaporPressure.solve_prop(P) @@ -2510,7 +2510,7 @@ class Mixture(object): # pragma: no cover Default initialization is for 298.15 K, 1 atm. ''' eos_in_a_box = [] - + def __repr__(self): return '' % (self.names, [round(i,4) for i in self.zs], self.T, self.P) @@ -2544,11 +2544,11 @@ def __init__(self, IDs, zs=None, ws=None, Vfls=None, Vfgs=None, self.names = [i.name for i in self.Chemicals] self.MWs = [i.MW for i in self.Chemicals] self.CASs = [i.CAS for i in self.Chemicals] - + # Required for densities for volume fractions before setting fractions self.set_chemical_constants() self.set_chemical_TP() - + if zs: self.zs = zs if sum(zs) == 1 else [zi/sum(zs) for zi in zs] self.ws = zs_to_ws(zs, self.MWs) @@ -2620,7 +2620,7 @@ def set_chemical_constants(self): # Chemistry self.Hfs = [i.Hf for i in self.Chemicals] self.Hcs = [i.Hc for i in self.Chemicals] - + # Fire Safety Limits self.Tflashs = [i.Tflash for i in self.Chemicals] self.Tautoignitions = [i.Tautoignition for i in self.Chemicals] @@ -2644,7 +2644,7 @@ def set_chemical_constants(self): self.ODPs = [i.ODP for i in self.Chemicals] self.logPs = [i.logP for i in self.Chemicals] - + # Analytical self.RIs = [i.RI for i in self.Chemicals] self.conductivities = [i.conductivity for i in self.Chemicals] @@ -2663,7 +2663,7 @@ def set_chemical_TP(self): try: self.Hs = [i.H for i in self.Chemicals] self.Hms = [i.Hm for i in self.Chemicals] - + self.Ss = [i.S for i in self.Chemicals] self.Sms = [i.Sm for i in self.Chemicals] # Ignore G, A, U - which depend on molar volume @@ -2726,7 +2726,7 @@ def set_eos(self, T, P, eos=PRMIX): def eos(self): r'''Equation of state object held by the mixture. See : obj:`thermo.eos_mix` for a full listing. - + Examples -------- ''' @@ -2751,7 +2751,7 @@ def set_TP_sources(self): self.ThermalConductivityGases = [i.ThermalConductivityGas for i in self.Chemicals] self.SurfaceTensions = [i.SurfaceTension for i in self.Chemicals] self.Permittivities = [i.Permittivity for i in self.Chemicals] - + self.VaporPressures = [i.VaporPressure for i in self.Chemicals] self.EnthalpyVaporizations = [i.EnthalpyVaporization for i in self.Chemicals] @@ -2765,12 +2765,12 @@ def set_TP_sources(self): self.ViscosityLiquidMixture = ViscosityLiquidMixture(CASs=self.CASs, ViscosityLiquids=self.ViscosityLiquids) self.ViscosityGasMixture = ViscosityGasMixture(MWs=self.MWs, molecular_diameters=self.molecular_diameters, Stockmayers=self.Stockmayers, CASs=self.CASs, ViscosityGases=self.ViscosityGases) - + self.ThermalConductivityLiquidMixture = ThermalConductivityLiquidMixture(CASs=self.CASs, ThermalConductivityLiquids=self.ThermalConductivityLiquids) self.ThermalConductivityGasMixture = ThermalConductivityGasMixture(MWs=self.MWs, Tbs=self.Tbs, CASs=self.CASs, ThermalConductivityGases=self.ThermalConductivityGases, ViscosityGases=self.ViscosityGases) - + self.SurfaceTensionMixture = SurfaceTensionMixture(MWs=self.MWs, Tbs=self.Tbs, Tcs=self.Tcs, CASs=self.CASs, SurfaceTensions=self.SurfaceTensions, VolumeLiquids=self.VolumeLiquids) - + def set_TP(self, T=None, P=None): if T: self.T = T @@ -2788,18 +2788,18 @@ def set_phase(self): if self.phase == 'two-phase': self.wsl = zs_to_ws(self.xs, self.MWs) self.wsg = zs_to_ws(self.ys, self.MWs) - + self.Pbubble_methods = Pbubble_mixture(T=self.T, zs=self.zs, Psats=self.Psats, CASRNs=self.CASs, AvailableMethods=True) self.Pbubble_method = self.Pbubble_methods[0] self.Pbubble = Pbubble_mixture(T=self.T, zs=self.zs, Psats=self.Psats, CASRNs=self.CASs, Method=self.Pbubble_method) - + self.Pdew_methods = Pdew_mixture(T=self.T, zs=self.zs, Psats=self.Psats, CASRNs=self.CASs, AvailableMethods=True) self.Pdew_method = self.Pdew_methods[0] self.Pdew = Pdew_mixture(T=self.T, zs=self.zs, Psats=self.Psats, CASRNs=self.CASs, Method=self.Pdew_method) if not None in self.Hs: self.H = mixing_simple(self.Hs, self.ws) self.Hm = property_mass_to_molar(self.H, self.MW) - + if not None in self.Ss: # Ideal gas contribution self.Sm = mixing_simple(self.Sms, self.zs) - R*sum([zi*log(zi) for zi in self.zs if zi > 0]) @@ -2847,7 +2847,7 @@ def Vfls(self): r'''Volume fractions of all species in the liquid phase at the current temperature and pressure. Note this is a method, not a property. Volume fractions are calculated based on pure species volumes only. - + Examples -------- >>> Mixture(['hexane', 'pentane'], zs=[.5, .5], T=315).Vfls() @@ -2862,7 +2862,7 @@ def Vfgs(self): r'''Volume fractions of all species in the gas phase at the current temperature and pressure. Note this is a method, not a property. Volume fractions are calculated based on pure species volumes only. - + Examples -------- >>> Mixture(['sulfur hexafluoride', 'methane'], zs=[.2, .9], T=315).Vfgs() @@ -2877,7 +2877,7 @@ def Vfgs(self): @property def PubChems(self): r'''PubChem Component ID numbers for all chemicals in the mixture. - + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5]).PubChems @@ -2888,10 +2888,10 @@ def PubChems(self): @property def formulas(self): r'''Chemical formulas for all chemicals in the mixture. - + Examples -------- - >>> Mixture(['ethanol', 'trichloroethylene', 'furfuryl alcohol'], + >>> Mixture(['ethanol', 'trichloroethylene', 'furfuryl alcohol'], ... ws=[0.5, 0.2, 0.3]).formulas ['C2H6O', 'C2HCl3', 'C5H6O2'] ''' @@ -2900,10 +2900,10 @@ def formulas(self): @property def smiless(self): r'''SMILES strings for all chemicals in the mixture. - + Examples -------- - >>> Mixture(['methane', 'ethane', 'propane', 'butane'], + >>> Mixture(['methane', 'ethane', 'propane', 'butane'], ... zs=[0.25, 0.25, 0.25, 0.25]).smiless ['C', 'CC', 'CCC', 'CCCC'] ''' @@ -2912,10 +2912,10 @@ def smiless(self): @property def InChIs(self): r'''InChI strings for all chemicals in the mixture. - + Examples -------- - >>> Mixture(['methane', 'ethane', 'propane', 'butane'], + >>> Mixture(['methane', 'ethane', 'propane', 'butane'], ... zs=[0.25, 0.25, 0.25, 0.25]).InChIs ['CH4/h1H4', 'C2H6/c1-2/h1-2H3', 'C3H8/c1-3-2/h3H2,1-2H3', 'C4H10/c1-3-4-2/h3-4H2,1-2H3'] ''' @@ -2924,7 +2924,7 @@ def InChIs(self): @property def InChI_Keys(self): r'''InChI keys for all chemicals in the mixture. - + Examples -------- >>> Mixture(['1-nonene'], zs=[1]).InChI_Keys @@ -2935,7 +2935,7 @@ def InChI_Keys(self): @property def IUPAC_names(self): r'''IUPAC names for all chemicals in the mixture. - + Examples -------- >>> Mixture(['1-hexene', '1-nonene'], zs=[.7, .3]).IUPAC_names @@ -2946,7 +2946,7 @@ def IUPAC_names(self): @property def synonymss(self): r'''Lists of synonyms for all chemicals in the mixture. - + Examples -------- >>> Mixture(['Tetradecene', 'Pentadecene'], zs=[.1, .9]).synonymss @@ -2957,7 +2957,7 @@ def synonymss(self): @property def charges(self): r'''Charges for all chemicals in the mixture. - + Examples -------- >>> Mixture(['water', 'sodium ion', 'chloride ion'], zs=[.9, .05, .05]).charges @@ -2968,7 +2968,7 @@ def charges(self): @property def atomss(self): r'''List of dictionaries of atom counts for all chemicals in the mixture. - + Examples -------- >>> Mixture(['nitrogen', 'oxygen'], zs=[.01, .99]).atomss @@ -2979,19 +2979,19 @@ def atomss(self): @property def ringss(self): r'''List of ring counts for all chemicals in the mixture. - + Examples -------- >>> Mixture(['Docetaxel', 'Paclitaxel'], zs=[.5, .5]).ringss [6, 7] ''' return [i.rings for i in self.Chemicals] - + @property def atom_fractionss(self): - r'''List of dictionaries of atomic fractions for all chemicals in the + r'''List of dictionaries of atomic fractions for all chemicals in the mixture. - + Examples -------- >>> Mixture(['oxygen', 'nitrogen'], zs=[.5, .5]).atom_fractionss @@ -3002,7 +3002,7 @@ def atom_fractionss(self): @property def atom_fractions(self): r'''Dictionary of atomic fractions for each atom in the mixture. - + Examples -------- >>> Mixture(['CO2', 'O2'], zs=[0.5, 0.5]).atom_fractions @@ -3015,14 +3015,14 @@ def atom_fractions(self): things[atom] += zi*count else: things[atom] = zi*count - + tot = sum(things.values()) return {atom : value/tot for atom, value in things.iteritems()} @property def mass_fractionss(self): r'''List of dictionaries of mass fractions for all chemicals in the mixture. - + Examples -------- >>> Mixture(['oxygen', 'nitrogen'], zs=[.5, .5]).mass_fractionss @@ -3033,7 +3033,7 @@ def mass_fractionss(self): @property def mass_fractions(self): r'''Dictionary of mass fractions for each atom in the mixture. - + Examples -------- >>> Mixture(['CO2', 'O2'], zs=[0.5, 0.5]).mass_fractions @@ -3051,9 +3051,9 @@ def mass_fractions(self): @property def legal_statuses(self): - r'''List of dictionaries of the legal status for all chemicals in the + r'''List of dictionaries of the legal status for all chemicals in the mixture. - + Examples -------- >>> pprint(Mixture(['oxygen', 'nitrogen'], zs=[.5, .5]).legal_statuses) @@ -3072,9 +3072,9 @@ def legal_statuses(self): @property def economic_statuses(self): - r'''List of dictionaries of the economic status for all chemicals in + r'''List of dictionaries of the economic status for all chemicals in the mixture. - + Examples -------- >>> pprint(Mixture(['o-xylene', 'm-xylene'], zs=[.5, .5]).economic_statuses) @@ -3091,7 +3091,7 @@ def economic_statuses(self): def UNIFAC_groups(self): r'''List of dictionaries of UNIFAC subgroup: count groups for each chemical in the mixture. Uses the original UNIFAC subgroups, as determined by `DDBST's online service `_. - + Examples -------- >>> pprint(Mixture(['1-pentanol', 'decane'], ws=[0.5, 0.5]).UNIFAC_groups) @@ -3103,7 +3103,7 @@ def UNIFAC_groups(self): def UNIFAC_Dortmund_groups(self): r'''List of dictionaries of Dortmund UNIFAC subgroup: count groups for each chemcial in the mixture. Uses the Dortmund UNIFAC subgroups, as determined by `DDBST's online service `_. - + Examples -------- >>> pprint(Mixture(['1-pentanol', 'decane'], ws=[0.5, 0.5]).UNIFAC_Dortmund_groups) @@ -3113,9 +3113,9 @@ def UNIFAC_Dortmund_groups(self): @property def PSRK_groups(self): - r'''List of dictionaries of PSRK subgroup: count groups for each chemical in the mixture. Uses the PSRK subgroups, + r'''List of dictionaries of PSRK subgroup: count groups for each chemical in the mixture. Uses the PSRK subgroups, as determined by `DDBST's online service `_. - + Examples -------- >>> pprint(Mixture(['1-pentanol', 'decane'], ws=[0.5, 0.5]).PSRK_groups) @@ -3127,7 +3127,7 @@ def PSRK_groups(self): ### One phase properties - calculate lazily @property def Psats(self): - r'''Pure component vapor pressures of the chemicals in the mixture at + r'''Pure component vapor pressures of the chemicals in the mixture at its current temperature, in units of Pa. Examples @@ -3139,9 +3139,9 @@ def Psats(self): @property def Hvapms(self): - r'''Pure component enthalpies of vaporization of the chemicals in the - mixture at its current temperature, in units of J/mol. - + r'''Pure component enthalpies of vaporization of the chemicals in the + mixture at its current temperature, in units of J/mol. + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Hvapms @@ -3151,9 +3151,9 @@ def Hvapms(self): @property def Hvaps(self): - r'''Enthalpy of vaporization of the chemicals in the mixture at its - current temperature, in units of J/kg. - + r'''Enthalpy of vaporization of the chemicals in the mixture at its + current temperature, in units of J/kg. + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Hvaps @@ -3163,21 +3163,21 @@ def Hvaps(self): @property def Cpsms(self): - r'''Solid-phase pure component heat capacity of the chemicals in the - mixture at its current temperature, in units of J/mol/K. - + r'''Solid-phase pure component heat capacity of the chemicals in the + mixture at its current temperature, in units of J/mol/K. + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Cpsms [109.77384365511931, 135.22614707678474] ''' return [i.Cpsm for i in self.Chemicals] - + @property def Cplms(self): r'''Liquid-phase pure component heat capacity of the chemicals in the - mixture at its current temperature, in units of J/mol/K. - + mixture at its current temperature, in units of J/mol/K. + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Cplms @@ -3187,9 +3187,9 @@ def Cplms(self): @property def Cpgms(self): - r'''Gas-phase ideal gas heat capacity of the chemicals at its current - temperature, in units of J/mol/K. - + r'''Gas-phase ideal gas heat capacity of the chemicals at its current + temperature, in units of J/mol/K. + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Cpgms @@ -3200,7 +3200,7 @@ def Cpgms(self): @property def Cpss(self): r'''Solid-phase pure component heat capacity of the chemicals in the - mixture at its current temperature, in units of J/kg/K. + mixture at its current temperature, in units of J/kg/K. Examples -------- @@ -3213,7 +3213,7 @@ def Cpss(self): def Cpls(self): r'''Liquid-phase pure component heat capacity of the chemicals in the mixture at its current temperature, in units of J/kg/K. - + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Cpls @@ -3223,11 +3223,11 @@ def Cpls(self): @property def Cpgs(self): - r'''Gas-phase pure component heat capacity of the chemicals in the + r'''Gas-phase pure component heat capacity of the chemicals in the mixture at its current temperature, in units of J/kg/K. - + Examples - -------- + -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Cpgs [1146.5360555565146, 1212.3488046342566] ''' @@ -3235,11 +3235,11 @@ def Cpgs(self): @property def Cvgms(self): - r'''Gas-phase pure component ideal-gas contant-volume heat capacities + r'''Gas-phase pure component ideal-gas contant-volume heat capacities of the chemicals in the mixture at its current temperature, in units - of J/mol/K. Subtracts R from the ideal-gas heat capacities; does not + of J/mol/K. Subtracts R from the ideal-gas heat capacities; does not include pressure-compensation from an equation of state. - + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Cvgms @@ -3249,11 +3249,11 @@ def Cvgms(self): @property def Cvgs(self): - r'''Gas-phase pure component ideal-gas contant-volume heat capacities - of the chemicals in the mixture at its current temperature, in units of - J/kg/K. Subtracts R from the ideal-gas heat capacity; does not include + r'''Gas-phase pure component ideal-gas contant-volume heat capacities + of the chemicals in the mixture at its current temperature, in units of + J/kg/K. Subtracts R from the ideal-gas heat capacity; does not include pressure-compensation from an equation of state. - + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Cvgs @@ -3263,22 +3263,22 @@ def Cvgs(self): @property def isentropic_exponents(self): - r'''Gas-phase pure component ideal-gas isentropic exponent of the + r'''Gas-phase pure component ideal-gas isentropic exponent of the chemicals in the mixture at its current temperature, dimensionless. Does not include pressure-compensation from an equation of state. - + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).isentropic_exponents [1.1023398979313739, 1.080418846592871] ''' return [i.isentropic_exponent for i in self.Chemicals] - + @property def Vmss(self): r'''Pure component solid-phase molar volumes of the chemicals in the - mixture at its current temperature, in units of mol/m^3. - + mixture at its current temperature, in units of mol/m^3. + Examples -------- >>> Mixture(['iron'], ws=[1], T=320).Vmss @@ -3288,9 +3288,9 @@ def Vmss(self): @property def Vmls(self): - r'''Pure component liquid-phase molar volumes of the chemicals in the - mixture at its current temperature and pressure, in units of mol/m^3. - + r'''Pure component liquid-phase molar volumes of the chemicals in the + mixture at its current temperature and pressure, in units of mol/m^3. + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Vmls @@ -3300,11 +3300,11 @@ def Vmls(self): @property def Vmgs(self): - r'''Pure component gas-phase molar volumes of the chemicals in the + r'''Pure component gas-phase molar volumes of the chemicals in the mixture at its current temperature and pressure, in units of mol/m^3. - + Examples - -------- + -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Vmgs [0.024929001982294974, 0.024150186467130488] ''' @@ -3312,11 +3312,11 @@ def Vmgs(self): @property def rhoss(self): - r'''Pure component solid-phase mass density of the chemicals in the - mixture at its current temperature, in units of kg/m^3. - + r'''Pure component solid-phase mass density of the chemicals in the + mixture at its current temperature, in units of kg/m^3. + Examples - -------- + -------- >>> Mixture(['iron'], ws=[1], T=320).rhoss [7869.999999999994] ''' @@ -3325,10 +3325,10 @@ def rhoss(self): @property def rhols(self): r'''Pure-component liquid-phase mass density of the chemicals in the - mixture at its current temperature and pressure, in units of kg/m^3. - + mixture at its current temperature and pressure, in units of kg/m^3. + Examples - -------- + -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).rhols [850.0676666084917, 841.7389069631628] ''' @@ -3336,11 +3336,11 @@ def rhols(self): @property def rhogs(self): - r'''Pure-component gas-phase mass densities of the chemicals in the - mixture at its current temperature and pressure, in units of kg/m^3. - + r'''Pure-component gas-phase mass densities of the chemicals in the + mixture at its current temperature and pressure, in units of kg/m^3. + Examples - -------- + -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).rhogs [3.1333721283939258, 3.8152260283954584] ''' @@ -3348,7 +3348,7 @@ def rhogs(self): @property def rhosms(self): - r'''Pure component molar densities of the chemicals in the solid phase + r'''Pure component molar densities of the chemicals in the solid phase at the current temperature and pressure, in units of mol/m^3. Examples @@ -3360,10 +3360,10 @@ def rhosms(self): @property def rholms(self): - r'''Pure component molar densities of the chemicals in the mixture in - the liquid phase at the current temperature and pressure, in units of + r'''Pure component molar densities of the chemicals in the mixture in + the liquid phase at the current temperature and pressure, in units of mol/m^3. - + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).rholms @@ -3375,7 +3375,7 @@ def rholms(self): def rhogms(self): r'''Pure component molar densities of the chemicals in the gas phase at the current temperature and pressure, in units of mol/m^3. - + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).rhogms @@ -3386,10 +3386,10 @@ def rhogms(self): @property def Zss(self): - r'''Pure component compressibility factors of the chemicals in the + r'''Pure component compressibility factors of the chemicals in the mixture in the solid phase at the current temperature and pressure, dimensionless. - + Examples -------- >>> Mixture(['palladium'], ws=[1]).Zss @@ -3399,9 +3399,9 @@ def Zss(self): @property def Zls(self): - r'''Pure component compressibility factors of the chemicals in the + r'''Pure component compressibility factors of the chemicals in the liquid phase at the current temperature and pressure, dimensionless. - + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Zls @@ -3411,10 +3411,10 @@ def Zls(self): @property def Zgs(self): - r'''Pure component compressibility factors of the chemicals in the - mixture in the gas phase at the current temperature and pressure, + r'''Pure component compressibility factors of the chemicals in the + mixture in the gas phase at the current temperature and pressure, dimensionless. - + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).Zgs @@ -3424,13 +3424,13 @@ def Zgs(self): @property def isobaric_expansion_ls(self): - r'''Pure component isobaric (constant-pressure) expansions of the - chemicals in the mixture in the liquid phase at its current temperature + r'''Pure component isobaric (constant-pressure) expansions of the + chemicals in the mixture in the liquid phase at its current temperature and pressure, in units of 1/K. - + .. math:: \beta = \frac{1}{V}\left(\frac{\partial V}{\partial T} \right)_P - + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).isobaric_expansion_ls @@ -3440,13 +3440,13 @@ def isobaric_expansion_ls(self): @property def isobaric_expansion_gs(self): - r'''Pure component isobaric (constant-pressure) expansions of the - chemicals in the mixture in the gas phase at its current temperature + r'''Pure component isobaric (constant-pressure) expansions of the + chemicals in the mixture in the gas phase at its current temperature and pressure, in units of 1/K. - + .. math:: \beta = \frac{1}{V}\left(\frac{\partial V}{\partial T} \right)_P - + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).isobaric_expansion_gs @@ -3456,9 +3456,9 @@ def isobaric_expansion_gs(self): @property def muls(self): - r'''Pure component viscosities of the chemicals in the mixture in the - liquid phase at its current temperature and pressure, in units of Pa*s. - + r'''Pure component viscosities of the chemicals in the mixture in the + liquid phase at its current temperature and pressure, in units of Pa*s. + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).muls @@ -3468,9 +3468,9 @@ def muls(self): @property def mugs(self): - r'''Pure component viscosities of the chemicals in the mixture in the - gas phase at its current temperature and pressure, in units of Pa*s. - + r'''Pure component viscosities of the chemicals in the mixture in the + gas phase at its current temperature and pressure, in units of Pa*s. + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).mugs @@ -3480,10 +3480,10 @@ def mugs(self): @property def kls(self): - r'''Pure component thermal conductivities of the chemicals in the + r'''Pure component thermal conductivities of the chemicals in the mixture in the liquid phase at its current temperature and pressure, in - units of W/m/K. - + units of W/m/K. + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).kls @@ -3496,8 +3496,8 @@ def kls(self): def kgs(self): r'''Pure component thermal conductivies of the chemicals in the mixture in the gas phase at its current temperature and pressure, in units of - W/m/K. - + W/m/K. + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).kgs @@ -3507,9 +3507,9 @@ def kgs(self): @property def sigmas(self): - r'''Pure component surface tensions of the chemicals in the mixture at - its current temperature, in units of N/m. - + r'''Pure component surface tensions of the chemicals in the mixture at + its current temperature, in units of N/m. + Examples -------- >>> Mixture(['benzene', 'toluene'], ws=[0.5, 0.5], T=320).sigmas @@ -3519,9 +3519,9 @@ def sigmas(self): @property def permittivites(self): - r'''Pure component relative permittivities of the chemicals in the + r'''Pure component relative permittivities of the chemicals in the mixture at its current temperature, dimensionless. - + Examples -------- >>> Mixture(['benzene', 'hexane'], ws=[0.5, 0.5], T=320).permittivites @@ -3534,12 +3534,12 @@ def JTls(self): r'''Pure component Joule Thomson coefficients of the chemicals in the mixture in the liquid phase at its current temperature and pressure, in units of K/Pa. - + .. math:: \mu_{JT} = \left(\frac{\partial T}{\partial P}\right)_H = \frac{1}{C_p} \left[T \left(\frac{\partial V}{\partial T}\right)_P - V\right] = \frac{V}{C_p}\left(\beta T-1\right) - + Examples -------- >>> Mixture(['benzene', 'hexane'], ws=[0.5, 0.5], T=320).JTls @@ -3552,12 +3552,12 @@ def JTgs(self): r'''Pure component Joule Thomson coefficients of the chemicals in the mixture in the gas phase at its current temperature and pressure, in units of K/Pa. - + .. math:: \mu_{JT} = \left(\frac{\partial T}{\partial P}\right)_H = \frac{1}{C_p} \left[T \left(\frac{\partial V}{\partial T}\right)_P - V\right] = \frac{V}{C_p}\left(\beta T-1\right) - + Examples -------- >>> Mixture(['benzene', 'hexane'], ws=[0.5, 0.5], T=320).JTgs @@ -3567,13 +3567,13 @@ def JTgs(self): @property def nuls(self): - r'''Pure component kinematic viscosities of the liquid phase of the - chemicals in the mixture at its current temperature and pressure, in + r'''Pure component kinematic viscosities of the liquid phase of the + chemicals in the mixture at its current temperature and pressure, in units of m^2/s. - + .. math:: \nu = \frac{\mu}{\rho} - + Examples -------- >>> Mixture(['benzene', 'hexane'], ws=[0.5, 0.5], T=320).nuls @@ -3583,13 +3583,13 @@ def nuls(self): @property def nugs(self): - r'''Pure component kinematic viscosities of the gas phase of the - chemicals in the mixture at its current temperature and pressure, in + r'''Pure component kinematic viscosities of the gas phase of the + chemicals in the mixture at its current temperature and pressure, in units of m^2/s. - + .. math:: \nu = \frac{\mu}{\rho} - + Examples -------- >>> Mixture(['benzene', 'hexane'], ws=[0.5, 0.5], T=320).nugs @@ -3599,10 +3599,10 @@ def nugs(self): @property def alphals(self): - r'''Pure component thermal diffusivities of the chemicals in the + r'''Pure component thermal diffusivities of the chemicals in the mixture in the liquid phase at the current temperature and pressure, in units of m^2/s. - + .. math:: \alpha = \frac{k}{\rho Cp} @@ -3615,10 +3615,10 @@ def alphals(self): @property def alphags(self): - r'''Pure component thermal diffusivities of the chemicals in the + r'''Pure component thermal diffusivities of the chemicals in the mixture in the gas phase at the current temperature and pressure, in units of m^2/s. - + .. math:: \alpha = \frac{k}{\rho Cp} @@ -3631,12 +3631,12 @@ def alphags(self): @property def Prls(self): - r'''Pure component Prandtl numbers of the liquid phase of the chemicals + r'''Pure component Prandtl numbers of the liquid phase of the chemicals in the mixture at its current temperature and pressure, dimensionless. - + .. math:: Pr = \frac{C_p \mu}{k} - + Examples -------- >>> Mixture(['benzene', 'hexane'], ws=[0.5, 0.5], T=320).Prls @@ -3646,12 +3646,12 @@ def Prls(self): @property def Prgs(self): - r'''Pure component Prandtl numbers of the gas phase of the chemicals + r'''Pure component Prandtl numbers of the gas phase of the chemicals in the mixture at its current temperature and pressure, dimensionless. - + .. math:: Pr = \frac{C_p \mu}{k} - + Examples -------- >>> Mixture(['benzene', 'hexane'], ws=[0.5, 0.5], T=320).Prgs @@ -3661,12 +3661,12 @@ def Prgs(self): @property def solubility_parameters(self): - r'''Pure component solubility parameters of the chemicals in the + r'''Pure component solubility parameters of the chemicals in the mixture at its current temperature and pressure, in units of Pa^0.5. - + .. math:: \delta = \sqrt{\frac{\Delta H_{vap} - RT}{V_m}} - + Examples -------- >>> Mixture(['benzene', 'hexane'], ws=[0.5, 0.5], T=320).solubility_parameters @@ -3677,17 +3677,17 @@ def solubility_parameters(self): ### Overall mixture properties @property def rhol(self): - r'''Liquid-phase mass density of the mixture at its current - temperature, pressure, and composition in units of kg/m^3. For - calculation of this property at other temperatures, pressures, - compositions or specifying manually the method used to calculate it, - and more - see the object oriented interface + r'''Liquid-phase mass density of the mixture at its current + temperature, pressure, and composition in units of kg/m^3. For + calculation of this property at other temperatures, pressures, + compositions or specifying manually the method used to calculate it, + and more - see the object oriented interface :obj:`thermo.volume.VolumeLiquidMixture`; each Mixture instance - creates one to actually perform the calculations. Note that that + creates one to actually perform the calculations. Note that that interface provides output in molar units. - + Examples - -------- + -------- >>> Mixture(['o-xylene'], ws=[1], T=297).rhol 876.9946785618097 ''' @@ -3695,19 +3695,19 @@ def rhol(self): if Vml: return Vm_to_rho(Vml, self.MW) return None - + @property def rhog(self): r'''Gas-phase mass density of the mixture at its current temperature, - pressure, and composition in units of kg/m^3. For calculation of this - property at other temperatures, pressures, or compositions or - specifying manually the method used to calculate it, and more - see the - object oriented interface :obj:`thermo.volume.VolumeGasMixture`; each - Mixture instance creates one to actually perform the calculations. Note + pressure, and composition in units of kg/m^3. For calculation of this + property at other temperatures, pressures, or compositions or + specifying manually the method used to calculate it, and more - see the + object oriented interface :obj:`thermo.volume.VolumeGasMixture`; each + Mixture instance creates one to actually perform the calculations. Note that that interface provides output in molar units. - + Examples - -------- + -------- >>> Mixture(['hexane'], ws=[1], T=300, P=2E5).rhog 7.914205150685313 ''' @@ -3720,11 +3720,11 @@ def rhog(self): def rholm(self): r'''Molar density of the mixture in the liquid phase at the current temperature, pressure, and composition in units of mol/m^3. - - Utilizes the object oriented interface and - :obj:`thermo.volume.VolumeLiquidMixture` to perform the actual + + Utilizes the object oriented interface and + :obj:`thermo.volume.VolumeLiquidMixture` to perform the actual calculation of molar volume. - + Examples -------- >>> Mixture(['water'], ws=[1], T=300).rholm @@ -3732,18 +3732,18 @@ def rholm(self): ''' Vml = self.Vml if Vml: - return 1./Vml + return 1./Vml return None @property def rhogm(self): r'''Molar density of the mixture in the gas phase at the current temperature, pressure, and composition in units of mol/m^3. - - Utilizes the object oriented interface and - :obj:`thermo.volume.VolumeGasMixture` to perform the actual + + Utilizes the object oriented interface and + :obj:`thermo.volume.VolumeGasMixture` to perform the actual calculation of molar volume. - + Examples -------- >>> Mixture(['water'], ws=[1], T=500).rhogm @@ -3759,11 +3759,11 @@ def rhogm(self): def Zl(self): r'''Compressibility factor of the mixture in the liquid phase at the current temperature, pressure, and composition, dimensionless. - - Utilizes the object oriented interface and - :obj:`thermo.volume.VolumeLiquidMixture` to perform the actual + + Utilizes the object oriented interface and + :obj:`thermo.volume.VolumeLiquidMixture` to perform the actual calculation of molar volume. - + Examples -------- >>> Mixture(['water'], ws=[1]).Zl @@ -3773,16 +3773,16 @@ def Zl(self): if Vml: return Z(self.T, self.P, Vml) return None - + @property def Zg(self): r'''Compressibility factor of the mixture in the gas phase at the current temperature, pressure, and composition, dimensionless. - - Utilizes the object oriented interface and - :obj:`thermo.volume.VolumeGasMixture` to perform the actual calculation + + Utilizes the object oriented interface and + :obj:`thermo.volume.VolumeGasMixture` to perform the actual calculation of molar volume. - + Examples -------- >>> Mixture(['hexane'], ws=[1], T=300, P=1E5).Zg @@ -3795,13 +3795,13 @@ def Zg(self): @property def Cpsm(self): - r'''Solid-phase heat capacity of the mixture at its current temperature - and composition, in units of J/mol/K. For calculation of this property - at other temperatures or compositions, or specifying manually the - method used to calculate it, and more - see the object oriented - interface :obj:`thermo.heat_capacity.HeatCapacitySolidMixture`; each + r'''Solid-phase heat capacity of the mixture at its current temperature + and composition, in units of J/mol/K. For calculation of this property + at other temperatures or compositions, or specifying manually the + method used to calculate it, and more - see the object oriented + interface :obj:`thermo.heat_capacity.HeatCapacitySolidMixture`; each Mixture instance creates one to actually perform the calculations. - + Examples -------- >>> Mixture(['silver', 'platinum'], ws=[0.95, 0.05]).Cpsm @@ -3811,13 +3811,13 @@ def Cpsm(self): @property def Cplm(self): - r'''Liquid-phase heat capacity of the mixture at its current - temperature and composition, in units of J/mol/K. For calculation of - this property at other temperatures or compositions, or specifying - manually the method used to calculate it, and more - see the object - oriented interface :obj:`thermo.heat_capacity.HeatCapacityLiquidMixture`; + r'''Liquid-phase heat capacity of the mixture at its current + temperature and composition, in units of J/mol/K. For calculation of + this property at other temperatures or compositions, or specifying + manually the method used to calculate it, and more - see the object + oriented interface :obj:`thermo.heat_capacity.HeatCapacityLiquidMixture`; each Mixture instance creates one to actually perform the calculations. - + Examples -------- >>> Mixture(['toluene', 'decane'], ws=[.9, .1], T=300).Cplm @@ -3827,13 +3827,13 @@ def Cplm(self): @property def Cpgm(self): - r'''Gas-phase heat capacity of the mixture at its current temperature + r'''Gas-phase heat capacity of the mixture at its current temperature and composition, in units of J/mol/K. For calculation of this property - at other temperatures or compositions, or specifying manually the - method used to calculate it, and more - see the object oriented - interface :obj:`thermo.heat_capacity.HeatCapacityGasMixture`; each + at other temperatures or compositions, or specifying manually the + method used to calculate it, and more - see the object oriented + interface :obj:`thermo.heat_capacity.HeatCapacityGasMixture`; each Mixture instance creates one to actually perform the calculations. - + Examples -------- >>> Mixture(['oxygen', 'nitrogen'], ws=[.4, .6], T=350, P=1E6).Cpgm @@ -3843,14 +3843,14 @@ def Cpgm(self): @property def Cps(self): - r'''Solid-phase heat capacity of the mixture at its current temperature - and composition, in units of J/kg/K. For calculation of this property - at other temperatures or compositions, or specifying manually the - method used to calculate it, and more - see the object oriented - interface :obj:`thermo.heat_capacity.HeatCapacitySolidMixture`; each + r'''Solid-phase heat capacity of the mixture at its current temperature + and composition, in units of J/kg/K. For calculation of this property + at other temperatures or compositions, or specifying manually the + method used to calculate it, and more - see the object oriented + interface :obj:`thermo.heat_capacity.HeatCapacitySolidMixture`; each Mixture instance creates one to actually perform the calculations. Note that that interface provides output in molar units. - + Examples -------- >>> Mixture(['silver', 'platinum'], ws=[0.95, 0.05]).Cps @@ -3863,14 +3863,14 @@ def Cps(self): @property def Cpl(self): - r'''Liquid-phase heat capacity of the mixture at its current - temperature and composition, in units of J/kg/K. For calculation of - this property at other temperatures or compositions, or specifying - manually the method used to calculate it, and more - see the object - oriented interface :obj:`thermo.heat_capacity.HeatCapacityLiquidMixture`; - each Mixture instance creates one to actually perform the calculations. + r'''Liquid-phase heat capacity of the mixture at its current + temperature and composition, in units of J/kg/K. For calculation of + this property at other temperatures or compositions, or specifying + manually the method used to calculate it, and more - see the object + oriented interface :obj:`thermo.heat_capacity.HeatCapacityLiquidMixture`; + each Mixture instance creates one to actually perform the calculations. Note that that interface provides output in molar units. - + Examples -------- >>> Mixture(['water', 'sodium chloride'], ws=[.9, .1], T=301.5).Cpl @@ -3884,13 +3884,13 @@ def Cpl(self): @property def Cpg(self): r'''Gas-phase heat capacity of the mixture at its current temperature , - and composition in units of J/kg/K. For calculation of this property at - other temperatures or compositions, or specifying manually the method + and composition in units of J/kg/K. For calculation of this property at + other temperatures or compositions, or specifying manually the method used to calculate it, and more - see the object oriented interface - :obj:`thermo.heat_capacity.HeatCapacityGasMixture`; each Mixture - instance creates one to actually perform the calculations. Note that + :obj:`thermo.heat_capacity.HeatCapacityGasMixture`; each Mixture + instance creates one to actually perform the calculations. Note that that interface provides output in molar units. - + Examples -------- >>> Mixture(['oxygen', 'nitrogen'], ws=[.4, .6], T=350, P=1E6).Cpg @@ -3903,11 +3903,11 @@ def Cpg(self): @property def Cvgm(self): - r'''Gas-phase ideal-gas contant-volume heat capacity of the mixture at + r'''Gas-phase ideal-gas contant-volume heat capacity of the mixture at its current temperature and composition, in units of J/mol/K. Subtracts R from - the ideal-gas heat capacity; does not include pressure-compensation + the ideal-gas heat capacity; does not include pressure-compensation from an equation of state. - + Examples -------- >>> Mixture(['water'], ws=[1], T=520).Cvgm @@ -3917,14 +3917,14 @@ def Cvgm(self): if Cpgm: return Cpgm - R return None - + @property def Cvg(self): - r'''Gas-phase ideal-gas contant-volume heat capacity of the mixture at + r'''Gas-phase ideal-gas contant-volume heat capacity of the mixture at its current temperature, in units of J/kg/K. Subtracts R from - the ideal-gas heat capacity; does not include pressure-compensation + the ideal-gas heat capacity; does not include pressure-compensation from an equation of state. - + Examples -------- >>> Mixture(['water'], ws=[1], T=520).Cvg @@ -3937,10 +3937,10 @@ def Cvg(self): @property def isentropic_exponent(self): - r'''Gas-phase ideal-gas isentropic exponent of the mixture at its - current temperature, dimensionless. Does not include + r'''Gas-phase ideal-gas isentropic exponent of the mixture at its + current temperature, dimensionless. Does not include pressure-compensation from an equation of state. - + Examples -------- >>> Mixture(['hydrogen'], ws=[1]).isentropic_exponent @@ -3953,13 +3953,13 @@ def isentropic_exponent(self): @property def Bvirial(self): - r'''Second virial coefficient of the gas phase of the mixture at its - current temperature, pressure, and composition in units of mol/m^3. - - This property uses the object-oriented interface - :obj:`thermo.volume.VolumeGasMixture`, converting its result with + r'''Second virial coefficient of the gas phase of the mixture at its + current temperature, pressure, and composition in units of mol/m^3. + + This property uses the object-oriented interface + :obj:`thermo.volume.VolumeGasMixture`, converting its result with :obj:`thermo.utils.B_from_Z`. - + Examples -------- >>> Mixture(['hexane'], ws=[1], T=300, P=1E5).Bvirial @@ -3968,17 +3968,17 @@ def Bvirial(self): if self.Vmg: return B_from_Z(self.Zg, self.T, self.P) return None - + @property def JTl(self): - r'''Joule Thomson coefficient of the liquid phase of the mixture if one + r'''Joule Thomson coefficient of the liquid phase of the mixture if one exists at its current temperature and pressure, in units of K/Pa. - + .. math:: \mu_{JT} = \left(\frac{\partial T}{\partial P}\right)_H = \frac{1}{C_p} \left[T \left(\frac{\partial V}{\partial T}\right)_P - V\right] = \frac{V}{C_p}\left(\beta T-1\right) - + Examples -------- >>> Mixture(['dodecane'], ws=[1], T=400).JTl @@ -3988,17 +3988,17 @@ def JTl(self): if all((Vml, Cplm, isobaric_expansion_l)): return Joule_Thomson(T=self.T, V=Vml, Cp=Cplm, beta=isobaric_expansion_l) return None - + @property def JTg(self): - r'''Joule Thomson coefficient of the gas phase of the mixture if one + r'''Joule Thomson coefficient of the gas phase of the mixture if one exists at its current temperature and pressure, in units of K/Pa. - + .. math:: \mu_{JT} = \left(\frac{\partial T}{\partial P}\right)_H = \frac{1}{C_p} \left[T \left(\frac{\partial V}{\partial T}\right)_P - V\right] = \frac{V}{C_p}\left(\beta T-1\right) - + Examples -------- >>> Mixture(['dodecane'], ws=[1], T=400, P=1000).JTg @@ -4011,12 +4011,12 @@ def JTg(self): @property def nul(self): - r'''Kinematic viscosity of the liquid phase of the mixture if one + r'''Kinematic viscosity of the liquid phase of the mixture if one exists at its current temperature and pressure, in units of m^2/s. - + .. math:: \nu = \frac{\mu}{\rho} - + Examples -------- >>> Mixture(['methane'], ws=[1], T=110).nul @@ -4029,12 +4029,12 @@ def nul(self): @property def nug(self): - r'''Kinematic viscosity of the gas phase of the mixture if one exists + r'''Kinematic viscosity of the gas phase of the mixture if one exists at its current temperature and pressure, in units of m^2/s. - + .. math:: \nu = \frac{\mu}{\rho} - + Examples -------- >>> Mixture(['methane'], ws=[1], T=115).nug @@ -4047,12 +4047,12 @@ def nug(self): @property def alphal(self): - r'''Thermal diffusivity of the liquid phase of the mixture if one + r'''Thermal diffusivity of the liquid phase of the mixture if one exists at its current temperature and pressure, in units of m^2/s. - + .. math:: \alpha = \frac{k}{\rho Cp} - + Examples -------- >>> Mixture(['nitrogen'], ws=[1], T=70).alphal @@ -4062,15 +4062,15 @@ def alphal(self): if all([kl, rhol, Cpl]): return thermal_diffusivity(k=kl, rho=rhol, Cp=Cpl) return None - + @property def alphag(self): - r'''Thermal diffusivity of the gas phase of the mixture if one exists + r'''Thermal diffusivity of the gas phase of the mixture if one exists at its current temperature and pressure, in units of m^2/s. - + .. math:: \alpha = \frac{k}{\rho Cp} - + Examples -------- >>> Mixture(['ammonia'], ws=[1]).alphag @@ -4083,12 +4083,12 @@ def alphag(self): @property def Prl(self): - r'''Prandtl number of the liquid phase of the mixture if one exists at + r'''Prandtl number of the liquid phase of the mixture if one exists at its current temperature and pressure, dimensionless. - + .. math:: Pr = \frac{C_p \mu}{k} - + Examples -------- >>> Mixture(['nitrogen'], ws=[1], T=70).Prl @@ -4101,12 +4101,12 @@ def Prl(self): @property def Prg(self): - r'''Prandtl number of the gas phase of the mixture if one exists at its + r'''Prandtl number of the gas phase of the mixture if one exists at its current temperature and pressure, dimensionless. - + .. math:: Pr = \frac{C_p \mu}{k} - + Examples -------- >>> Mixture(['NH3'], ws=[1]).Prg @@ -4116,71 +4116,71 @@ def Prg(self): if all([Cpg, mug, kg]): return Prandtl(Cp=Cpg, mu=mug, k=kg) return None - + ### Properties from Mixture objects @property def Vml(self): r'''Liquid-phase molar volume of the mixture at its current - temperature, pressure, and composition in units of mol/m^3. For - calculation of this property at other temperatures or pressures or + temperature, pressure, and composition in units of mol/m^3. For + calculation of this property at other temperatures or pressures or compositions, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.volume.VolumeLiquidMixture`; each Mixture instance creates one to actually perform the calculations. - + Examples -------- >>> Mixture(['cyclobutane'], ws=[1], T=225).Vml 7.42395423425395e-05 ''' return self.VolumeLiquidMixture(T=self.T, P=self.P, zs=self.zs, ws=self.ws) - + @property def Vmg(self): r'''Gas-phase molar volume of the mixture at its current - temperature, pressure, and composition in units of mol/m^3. For - calculation of this property at other temperatures or pressures or - compositions, or specifying manually the method used to calculate it, + temperature, pressure, and composition in units of mol/m^3. For + calculation of this property at other temperatures or pressures or + compositions, or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.volume.VolumeGasMixture`; each Mixture instance creates one to actually perform the calculations. - + Examples -------- >>> Mixture(['hexane'], ws=[1], T=300, P=2E5).Vmg 0.010888694235142216 ''' return self.VolumeGasMixture(T=self.T, P=self.P, zs=self.zs, ws=self.ws) - + @property def mul(self): r'''Viscosity of the mixture in the liquid phase at its current - temperature, pressure, and composition in units of Pa*s. - + temperature, pressure, and composition in units of Pa*s. + For calculation of this property at other temperatures and pressures, - or specifying manually the method used to calculate it, and more - see + or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.viscosity.ViscosityLiquidMixture`; each Mixture instance creates one to actually perform the calculations. - + Examples -------- >>> Mixture(['water'], ws=[1], T=320).mul 0.0005767262693751547 ''' return self.ViscosityLiquidMixture(self.T, self.P, self.zs, self.ws) - + @property def mug(self): r'''Viscosity of the mixture in the gas phase at its current - temperature, pressure, and composition in units of Pa*s. - + temperature, pressure, and composition in units of Pa*s. + For calculation of this property at other temperatures and pressures, - or specifying manually the method used to calculate it, and more - see + or specifying manually the method used to calculate it, and more - see the object oriented interface :obj:`thermo.viscosity.ViscosityGasMixture`; each Mixture instance creates one to actually perform the calculations. - + Examples -------- >>> Mixture(['water'], ws=[1], T=500).mug @@ -4190,14 +4190,14 @@ def mug(self): @property def sigma(self): - r'''Surface tension of the mixture at its current temperature and - composition, in units of N/m. - + r'''Surface tension of the mixture at its current temperature and + composition, in units of N/m. + For calculation of this property at other temperatures, - or specifying manually the method used to calculate it, and more - see - the object oriented interface :obj:`thermo.interface.SurfaceTensionMixture`; + or specifying manually the method used to calculate it, and more - see + the object oriented interface :obj:`thermo.interface.SurfaceTensionMixture`; each Mixture instance creates one to actually perform the calculations. - + Examples -------- >>> Mixture(['water'], ws=[1], T=300, P=1E5).sigma @@ -4208,14 +4208,14 @@ def sigma(self): @property def kl(self): r'''Thermal conductivity of the mixture in the liquid phase at its current - temperature, pressure, and composition in units of Pa*s. - + temperature, pressure, and composition in units of Pa*s. + For calculation of this property at other temperatures and pressures, - or specifying manually the method used to calculate it, and more - see + or specifying manually the method used to calculate it, and more - see the object oriented interface - :obj:`thermo.thermal_conductivity.ThermalConductivityLiquidMixture`; + :obj:`thermo.thermal_conductivity.ThermalConductivityLiquidMixture`; each Mixture instance creates one to actually perform the calculations. - + Examples -------- >>> Mixture(['water'], ws=[1], T=320).kl @@ -4226,14 +4226,14 @@ def kl(self): @property def kg(self): r'''Thermal conductivity of the mixture in the gas phase at its current - temperature, pressure, and composition in units of Pa*s. - + temperature, pressure, and composition in units of Pa*s. + For calculation of this property at other temperatures and pressures, - or specifying manually the method used to calculate it, and more - see + or specifying manually the method used to calculate it, and more - see the object oriented interface - :obj:`thermo.thermal_conductivity.ThermalConductivityGasMixture`; + :obj:`thermo.thermal_conductivity.ThermalConductivityGasMixture`; each Mixture instance creates one to actually perform the calculations. - + Examples -------- >>> Mixture(['water'], ws=[1], T=500).kg @@ -4242,12 +4242,12 @@ def kg(self): return self.ThermalConductivityGasMixture(self.T, self.P, self.zs, self.ws) ### Single-phase properties - + @property def Cp(self): r'''Mass heat capacity of the mixture at its current phase and temperature, in units of J/kg/K. - + Examples -------- >>> w = Mixture(['water'], ws=[1]) @@ -4258,12 +4258,12 @@ def Cp(self): (234.26767209171211, 's') ''' return phase_select_property(phase=self.phase, s=self.Cps, l=self.Cpl, g=self.Cpg) - + @property def Cpm(self): r'''Molar heat capacity of the mixture at its current phase and temperature, in units of J/mol/K. Available only if single phase. - + Examples -------- >>> Mixture(['ethylbenzene'], ws=[1], T=550, P=3E6).Cpm @@ -4276,40 +4276,40 @@ def Vm(self): r'''Molar volume of the mixture at its current phase and temperature and pressure, in units of m^3/mol. Available only if single phase. - + Examples -------- >>> Mixture(['ethylbenzene'], ws=[1], T=550, P=3E6).Vm 0.00017758024401627633 ''' return phase_select_property(phase=self.phase, s=self.Vms, l=self.Vml, g=self.Vmg) - + @property def rho(self): r'''Mass density of the mixture at its current phase and temperature and pressure, in units of kg/m^3. Available only if single phase. - + Examples -------- >>> Mixture(['decane'], ws=[1], T=550, P=2E6).rho 498.6549441720744 ''' return phase_select_property(phase=self.phase, s=self.rhos, l=self.rhol, g=self.rhog) - + @property def rhom(self): r'''Molar density of the mixture at its current phase and temperature and pressure, in units of mol/m^3. Available only if single phase. - + Examples -------- >>> Mixture(['1-hexanol'], ws=[1]).rhom 7853.086232143972 ''' return phase_select_property(phase=self.phase, s=self.rhosm, l=self.rholm, g=self.rhogm) - + @property def Z(self): r'''Compressibility factor of the mixture at its current phase and @@ -4327,7 +4327,7 @@ def Z(self): return None ### Single-phase properties - + @property def isobaric_expansion(self): r'''Isobaric (constant-pressure) expansion of the mixture at its @@ -4336,14 +4336,14 @@ def isobaric_expansion(self): .. math:: \beta = \frac{1}{V}\left(\frac{\partial V}{\partial T} \right)_P - + Examples -------- >>> Mixture(['water'], ws=[1], T=647.1, P=22048320.0).isobaric_expansion 0.34074205839222449 ''' return phase_select_property(phase=self.phase, l=self.isobaric_expansion_l, g=self.isobaric_expansion_g) - + @property def JT(self): r'''Joule Thomson coefficient of the mixture at its @@ -4387,7 +4387,7 @@ def k(self): 0.16313594741877802 ''' return phase_select_property(phase=self.phase, s=None, l=self.kl, g=self.kg) - + @property def nu(self): r'''Kinematic viscosity of the the mixture at its current temperature, @@ -4396,17 +4396,17 @@ def nu(self): .. math:: \nu = \frac{\mu}{\rho} - + Examples -------- >>> Mixture(['argon'], ws=[1]).nu 1.3846930410865003e-05 ''' return phase_select_property(phase=self.phase, l=self.nul, g=self.nug) - + @property def alpha(self): - r'''Thermal diffusivity of the mixture at its current temperature, + r'''Thermal diffusivity of the mixture at its current temperature, pressure, and phase in units of m^2/s. Available only if single phase. @@ -4419,16 +4419,16 @@ def alpha(self): 7.672866198927953e-08 ''' return phase_select_property(phase=self.phase, l=self.alphal, g=self.alphag) - + @property def Pr(self): - r'''Prandtl number of the mixture at its current temperature, + r'''Prandtl number of the mixture at its current temperature, pressure, and phase; dimensionless. Available only if single phase. .. math:: Pr = \frac{C_p \mu}{k} - + Examples -------- >>> Mixture(['acetone'], ws=[1]).Pr @@ -4437,11 +4437,11 @@ def Pr(self): return phase_select_property(phase=self.phase, l=self.Prl, g=self.Prg) ### Standard state properties - + @property def Vml_STP(self): r'''Liquid-phase molar volume of the mixture at 298.15 K and 101.325 kPa, - and the current composition in units of mol/m^3. + and the current composition in units of mol/m^3. Examples -------- @@ -4453,7 +4453,7 @@ def Vml_STP(self): @property def Vmg_STP(self): r'''Gas-phase molar volume of the mixture at 298.15 K and 101.325 kPa, - and the current composition in units of mol/m^3. + and the current composition in units of mol/m^3. Examples -------- @@ -4465,7 +4465,7 @@ def Vmg_STP(self): @property def rhol_STP(self): r'''Liquid-phase mass density of the mixture at 298.15 K and 101.325 kPa, - and the current composition in units of kg/m^3. + and the current composition in units of kg/m^3. Examples -------- @@ -4480,7 +4480,7 @@ def rhol_STP(self): @property def rhog_STP(self): r'''Gas-phase mass density of the mixture at 298.15 K and 101.325 kPa, - and the current composition in units of kg/m^3. + and the current composition in units of kg/m^3. Examples -------- @@ -4495,7 +4495,7 @@ def rhog_STP(self): @property def Zl_STP(self): r'''Liquid-phase compressibility factor of the mixture at 298.15 K and 101.325 kPa, - and the current composition, dimensionless. + and the current composition, dimensionless. Examples -------- @@ -4510,7 +4510,7 @@ def Zl_STP(self): @property def Zg_STP(self): r'''Gas-phase compressibility factor of the mixture at 298.15 K and 101.325 kPa, - and the current composition, dimensionless. + and the current composition, dimensionless. Examples -------- @@ -4526,7 +4526,7 @@ def Zg_STP(self): def rholm_STP(self): r'''Molar density of the mixture in the liquid phase at 298.15 K and 101.325 kPa, and the current composition, in units of mol/m^3. - + Examples -------- >>> Mixture(['water'], ws=[1]).rholm_STP @@ -4534,7 +4534,7 @@ def rholm_STP(self): ''' Vml = self.Vml_STP if Vml: - return 1./Vml + return 1./Vml return None @@ -4542,7 +4542,7 @@ def rholm_STP(self): def rhogm_STP(self): r'''Molar density of the mixture in the gas phase at 298.15 K and 101.325 kPa, and the current composition, in units of mol/m^3. - + Examples -------- >>> Mixture(['nitrogen'], ws=[1]).rhogm_STP @@ -4554,9 +4554,9 @@ def rhogm_STP(self): return None def draw_2d(self, Hs=False): # pragma: no cover - r'''Interface for drawing a 2D image of all the molecules in the - mixture. Requires an HTML5 browser, and the libraries RDKit and - IPython. An exception is raised if either of these libraries is + r'''Interface for drawing a 2D image of all the molecules in the + mixture. Requires an HTML5 browser, and the libraries RDKit and + IPython. An exception is raised if either of these libraries is absent. Parameters @@ -4631,7 +4631,7 @@ def __init__(self, IDs, zs=None, ws=None, Vfls=None, Vfgs=None, self.Q = self.m/self.rho else: self.Q = None - + self.n = property_molar_to_mass(self.m, self.MW) self.ns = [self.n*zi for zi in self.zs] if hasattr(self, 'H') and hasattr(self, 'S'): @@ -4714,7 +4714,7 @@ def __truediv__(self, const): def __sub__(self, other): # Subtracts the mass flow rates in other from self and returns a new # Stream instance - + # Check if all components are present in the original stream, # while ignoring 0-flow streams in other components_in_self = [i in self.CASs for i in other.CASs] @@ -4723,12 +4723,12 @@ def __sub__(self, other): if not in_self and other.ws[i] > 0: raise Exception('Not all components to be removed are \ present in the first stream; %s is not present.' %other.components[i]) - - + + # Calculate the mass flows of each species ms_self = [wi*self.m for wi in self.ws] ms_other = [wj*other.m for wj in other.ws] - + for i, CAS in enumerate(self.CASs): if CAS in other.CASs: mj = ms_other[other.CASs.index(CAS)] @@ -4736,18 +4736,18 @@ def __sub__(self, other): raise Exception('Attempting to remove more %s than is in the \ first stream.' %self.components[i]) ms_self[i] -= mj - + # Remove now-empty streams: remaining_CASs = self.CASs for i, m in enumerate(list(ms_self)): if m == 0: remaining_CASs.pop(i) ms_self.pop(i) - + # Create the resulting stream m_tot = sum(ms_self) return Stream(IDs=remaining_CASs, ws=ms_self, m=m_tot, T=self.T, P=self.P) - + From ba36e5cb36868269eb3cf13168ee734e5d7c8b8c Mon Sep 17 00:00:00 2001 From: Enrique Cintron Date: Wed, 24 May 2017 17:25:20 -0400 Subject: [PATCH 2/4] fixed not calculating when chemical not cached. test_chemical now passes. --- thermo/chemical.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thermo/chemical.py b/thermo/chemical.py index d7efa53e..b4ce0226 100644 --- a/thermo/chemical.py +++ b/thermo/chemical.py @@ -424,8 +424,8 @@ def __init__(self, ID, T=298.15, P=101325): self.set_eos(T=T, P=P) self.set_TP_sources() self.set_ref() + self.calculate(T, P) if len(_chemical_cache) < 1000: - self.calculate(T, P) _chemical_cache[self.CAS] = self From 9967931b1fa36601635214790333b456dc101998 Mon Sep 17 00:00:00 2001 From: Enrique Cintron Date: Wed, 24 May 2017 20:54:43 -0400 Subject: [PATCH 3/4] changes from space removal --- thermo/activity.py | 343 +++++++++++++++++++++++---------------------- 1 file changed, 173 insertions(+), 170 deletions(-) diff --git a/thermo/activity.py b/thermo/activity.py index 2a4753c0..3e891f28 100644 --- a/thermo/activity.py +++ b/thermo/activity.py @@ -22,10 +22,10 @@ from __future__ import division -__all__ = ['K_value', 'Rachford_Rice_flash_error', 'Rachford_Rice_solution', +__all__ = ['K_value', 'Rachford_Rice_flash_error', 'Rachford_Rice_solution', 'Li_Johns_Ahmadi_solution', 'flash_inner_loop', 'NRTL', 'Wilson', - 'UNIQUAC', 'flash', 'dew_at_T', - 'bubble_at_T', 'identify_phase', 'mixture_phase_methods', + 'UNIQUAC', 'flash', 'dew_at_T', + 'bubble_at_T', 'identify_phase', 'mixture_phase_methods', 'identify_phase_mixture', 'Pbubble_mixture', 'Pdew_mixture'] from scipy.optimize import fsolve, newton, brenth @@ -39,51 +39,51 @@ def K_value(P=None, Psat=None, phi_l=None, phi_g=None, gamma=None, Poynting=1): r'''Calculates the equilibrium K-value assuming Raoult's law, or an equation of state model, or an activity coefficient model, or a combined equation of state-activity model. - - The calculation procedure will use the most advanced approach with the + + The calculation procedure will use the most advanced approach with the provided inputs: - + * If `P`, `Psat`, `phi_l`, `phi_g`, and `gamma` are provided, use the combined approach. * If `P`, `Psat`, and `gamma` are provided, use the modified Raoult's law. * If `phi_l` and `phi_g` are provided, use the EOS only method. * If `P` and `Psat` are provided, use Raoult's law. - + Definitions: - + .. math:: K_i=\frac{y_i}{x_i} - + Raoult's law: - + .. math:: K_i = \frac{P_{i}^{sat}}{P} - + Activity coefficient, no EOS (modified Raoult's law): - + .. math:: K_i = \frac{\gamma_i P_{i}^{sat}}{P} - + Equation of state only: - + .. math:: K_i = \frac{\phi_i^l}{\phi_i^v} = \frac{f_i^l}{f_i^v} - - Combined approach (liquid reference fugacity coefficient is normally + + Combined approach (liquid reference fugacity coefficient is normally calculated the saturation pressure for it as a pure species; vapor fugacity coefficient calculated normally): - + .. math:: K_i = \frac{\gamma_i P_i^{sat} \phi_i^{l,ref}}{\phi_i^v P} - + Combined approach, with Poynting Correction Factor (liquid molar volume in the integral is for i as a pure species only): - + .. math:: K_i = \frac{\gamma_i P_i^{sat} \phi_i^{l, ref} \exp\left[\frac{ \int_{P_i^{sat}}^P V_i^l dP}{RT}\right]}{\phi_i^v P} - + Parameters ---------- P : float @@ -93,10 +93,10 @@ def K_value(P=None, Psat=None, phi_l=None, phi_g=None, gamma=None, Poynting=1): phi_l : float Fugacity coefficient of species i in the liquid phase, either at the system conditions (EOS-only case) or at the saturation pressure - of species i as a pure species (reference condition for the combined + of species i as a pure species (reference condition for the combined approach), optional [-] phi_g : float - Fugacity coefficient of species i in the vapor phase at the system + Fugacity coefficient of species i in the vapor phase at the system conditions, optional [-] gamma : float Activity coefficient of species i in the liquid phase, optional [-] @@ -113,43 +113,43 @@ def K_value(P=None, Psat=None, phi_l=None, phi_g=None, gamma=None, Poynting=1): ----- The Poynting correction factor is normally simplified as follows, due to a liquid's low pressure dependency: - + .. math:: - K_i = \frac{\gamma_i P_i^{sat} \phi_i^{l, ref} \exp\left[\frac{V_l + K_i = \frac{\gamma_i P_i^{sat} \phi_i^{l, ref} \exp\left[\frac{V_l (P-P_i^{sat})}{RT}\right]}{\phi_i^v P} - + Examples -------- Raoult's law: - + >>> K_value(101325, 3000.) 0.029607698001480384 - + Modified Raoult's law: - + >>> K_value(P=101325, Psat=3000, gamma=0.9) 0.026646928201332347 - + EOS-only approach: - + >>> K_value(phi_l=1.6356, phi_g=0.88427) 1.8496613025433408 - + Gamma-phi combined approach: - + >>> K_value(P=1E6, Psat=1938800, phi_l=1.4356, phi_g=0.88427, gamma=0.92) 2.8958055544121137 - + Gamma-phi combined approach with a Poynting factor: - - >>> K_value(P=1E6, Psat=1938800, phi_l=1.4356, phi_g=0.88427, gamma=0.92, + + >>> K_value(P=1E6, Psat=1938800, phi_l=1.4356, phi_g=0.88427, gamma=0.92, ... Poynting=0.999) 2.8929097488577016 - + References ---------- - .. [1] Gmehling, Jurgen, Barbel Kolbe, Michael Kleiber, and Jurgen Rarey. - Chemical Thermodynamics for Process Simulation. 1st edition. Weinheim: + .. [1] Gmehling, Jurgen, Barbel Kolbe, Michael Kleiber, and Jurgen Rarey. + Chemical Thermodynamics for Process Simulation. 1st edition. Weinheim: Wiley-VCH, 2012. .. [2] Skogestad, Sigurd. Chemical and Energy Process Engineering. 1st edition. Boca Raton, FL: CRC Press, 2008. @@ -165,7 +165,7 @@ def K_value(P=None, Psat=None, phi_l=None, phi_g=None, gamma=None, Poynting=1): except TypeError: raise Exception('Input must consist of one set from (P, Psat, phi_l, \ phi_g, gamma), (P, Psat, gamma), (phi_l, phi_g), (P, Psat)') - + @@ -174,9 +174,9 @@ def K_value(P=None, Psat=None, phi_l=None, phi_g=None, gamma=None, Poynting=1): def Rachford_Rice_flash_error(V_over_F, zs, Ks): r'''Calculates the objective function of the Rachford-Rice flash equation. This function should be called by a solver seeking a solution to a flash - calculation. The unknown variable is `V_over_F`, for which a solution + calculation. The unknown variable is `V_over_F`, for which a solution must be between 0 and 1. - + .. math:: \sum_i \frac{z_i(K_i-1)}{1 + \frac{V}{F}(K_i-1)} = 0 @@ -198,29 +198,29 @@ def Rachford_Rice_flash_error(V_over_F, zs, Ks): Notes ----- The derivation is as follows: - + .. math:: F z_i = L x_i + V y_i - + x_i = \frac{z_i}{1 + \frac{V}{F}(K_i-1)} - + \sum_i y_i = \sum_i K_i x_i = 1 - + \sum_i(y_i - x_i)=0 - + \sum_i \frac{z_i(K_i-1)}{1 + \frac{V}{F}(K_i-1)} = 0 Examples -------- - >>> Rachford_Rice_flash_error(0.5, zs=[0.5, 0.3, 0.2], + >>> Rachford_Rice_flash_error(0.5, zs=[0.5, 0.3, 0.2], ... Ks=[1.685, 0.742, 0.532]) 0.04406445591174976 References ---------- .. [1] Rachford, H. H. Jr, and J. D. Rice. "Procedure for Use of Electronic - Digital Computers in Calculating Flash Vaporization Hydrocarbon - Equilibrium." Journal of Petroleum Technology 4, no. 10 (October 1, + Digital Computers in Calculating Flash Vaporization Hydrocarbon + Equilibrium." Journal of Petroleum Technology 4, no. 10 (October 1, 1952): 19-3. doi:10.2118/952327-G. ''' return sum([zi*(Ki-1.)/(1.+V_over_F*(Ki-1.)) for Ki, zi in zip(Ks, zs)]) @@ -229,7 +229,7 @@ def Rachford_Rice_flash_error(V_over_F, zs, Ks): def Rachford_Rice_solution(zs, Ks): r'''Solves the objective function of the Rachford-Rice flash equation. Uses the method proposed in [2]_ to obtain an initial guess. - + .. math:: \sum_i \frac{z_i(K_i-1)}{1 + \frac{V}{F}(K_i-1)} = 0 @@ -252,24 +252,24 @@ def Rachford_Rice_solution(zs, Ks): Notes ----- The initial guess is the average of the following, as described in [2]_. - + .. math:: - \left(\frac{V}{F}\right)_{min} = \frac{(K_{max}-K_{min})z_{of\;K_{max}} + \left(\frac{V}{F}\right)_{min} = \frac{(K_{max}-K_{min})z_{of\;K_{max}} - (1-K_{min})}{(1-K_{min})(K_{max}-1)} \left(\frac{V}{F}\right)_{max} = \frac{1}{1-K_{min}} - + Another algorithm for determining the range of the correct solution is given in [3]_; [2]_ provides a narrower range however. For both cases, each guess should be limited to be between 0 and 1 as they are often negative or larger than 1. - + .. math:: \left(\frac{V}{F}\right)_{min} = \frac{1}{1-K_{max}} - + \left(\frac{V}{F}\right)_{max} = \frac{1}{1-K_{min}} - If the `newton` method does not converge, a bisection method (brenth) is + If the `newton` method does not converge, a bisection method (brenth) is used instead. However, it is somewhat slower, especially as newton will attempt 50 iterations before giving up. @@ -281,16 +281,16 @@ def Rachford_Rice_solution(zs, Ks): References ---------- .. [1] Rachford, H. H. Jr, and J. D. Rice. "Procedure for Use of Electronic - Digital Computers in Calculating Flash Vaporization Hydrocarbon - Equilibrium." Journal of Petroleum Technology 4, no. 10 (October 1, + Digital Computers in Calculating Flash Vaporization Hydrocarbon + Equilibrium." Journal of Petroleum Technology 4, no. 10 (October 1, 1952): 19-3. doi:10.2118/952327-G. .. [2] Li, Yinghui, Russell T. Johns, and Kaveh Ahmadi. "A Rapid and Robust - Alternative to Rachford-Rice in Flash Calculations." Fluid Phase - Equilibria 316 (February 25, 2012): 85-97. + Alternative to Rachford-Rice in Flash Calculations." Fluid Phase + Equilibria 316 (February 25, 2012): 85-97. doi:10.1016/j.fluid.2011.12.005. - .. [3] Whitson, Curtis H., and Michael L. Michelsen. "The Negative Flash." - Fluid Phase Equilibria, Proceedings of the Fifth International - Conference, 53 (December 1, 1989): 51-71. + .. [3] Whitson, Curtis H., and Michael L. Michelsen. "The Negative Flash." + Fluid Phase Equilibria, Proceedings of the Fifth International + Conference, 53 (December 1, 1989): 51-71. doi:10.1016/0378-3812(89)80072-X. ''' Kmin = min(Ks) @@ -299,7 +299,7 @@ def Rachford_Rice_solution(zs, Ks): V_over_F_min = ((Kmax-Kmin)*z_of_Kmax - (1.-Kmin))/((1.-Kmin)*(Kmax-1.)) V_over_F_max = 1./(1.-Kmin) - + V_over_F_min2 = max(0., V_over_F_min) V_over_F_max2 = min(1., V_over_F_max) @@ -323,9 +323,9 @@ def Rachford_Rice_solution(zs, Ks): def Li_Johns_Ahmadi_solution(zs, Ks): r'''Solves the objective function of the Li-Johns-Ahmadi flash equation. Uses the method proposed in [1]_ to obtain an initial guess. - + .. math:: - 0 = 1 + \left(\frac{K_{max}-K_{min}}{K_{min}-1}\right)x_1 + 0 = 1 + \left(\frac{K_{max}-K_{min}}{K_{min}-1}\right)x_1 + \sum_{i=2}^{n-1}\frac{K_i-K_{min}}{K_{min}-1}\left[\frac{z_i(K_{max} -1)x_{max}}{(K_i-1)z_{max} + (K_{max}-K_i)x_{max}}\right] @@ -351,15 +351,15 @@ def Li_Johns_Ahmadi_solution(zs, Ks): Each guess should be limited to be between 0 and 1 as they are often negative or larger than 1. `max` refers to the corresponding mole fractions for the species with the largest K value. - + .. math:: \left(\frac{1-K_{min}}{K_{max}-K_{min}}\right)z_{max}\le x_{max} \le \left(\frac{1-K_{min}}{K_{max}-K_{min}}\right) - - If the `newton` method does not converge, a bisection method (brenth) is + + If the `newton` method does not converge, a bisection method (brenth) is used instead. However, it is somewhat slower, especially as newton will attempt 50 iterations before giving up. - + This method does not work for problems of only two components. K values are sorted internally. Has not been found to be quicker than the Rachford-Rice equation. @@ -372,14 +372,14 @@ def Li_Johns_Ahmadi_solution(zs, Ks): References ---------- .. [1] Li, Yinghui, Russell T. Johns, and Kaveh Ahmadi. "A Rapid and Robust - Alternative to Rachford-Rice in Flash Calculations." Fluid Phase - Equilibria 316 (February 25, 2012): 85-97. + Alternative to Rachford-Rice in Flash Calculations." Fluid Phase + Equilibria 316 (February 25, 2012): 85-97. doi:10.1016/j.fluid.2011.12.005. ''' # Re-order both Ks and Zs by K value, higher coming first p = sorted(zip(Ks,zs), reverse=True) Ks_sorted, zs_sorted = [K for (K,z) in p], [z for (K,z) in p] - + # Largest K value and corresponding overall mole fraction k1 = Ks_sorted[0] @@ -389,17 +389,17 @@ def Li_Johns_Ahmadi_solution(zs, Ks): x_min = (1. - kn)/(k1 - kn)*z1 x_max = (1. - kn)/(k1 - kn) - + x_min2 = max(0., x_min) x_max2 = min(1., x_max) - + x_guess = (x_min2 + x_max2)*0.5 - + length = len(zs)-1 kn_m_1 = kn-1. k1_m_1 = (k1-1.) t1 = (k1-kn)/(kn-1.) - + objective = lambda x1: 1. + t1*x1 + sum([(ki-kn)/(kn_m_1) * zi*k1_m_1*x1 /( (ki-1.)*z1 + (k1-ki)*x1) for ki, zi in zip(Ks_sorted[1:length], zs_sorted[1:length])]) try: x1 = newton(objective, x_guess) @@ -424,7 +424,7 @@ def flash_inner_loop(zs, Ks, AvailableMethods=False, Method=None): calculation, solving for liquid and gas mole fractions and vapor fraction based on specified overall mole fractions and K values. As K values are weak functions of composition, this should be called repeatedly by an outer - loop. Will automatically select an algorithm to use if no Method is + loop. Will automatically select an algorithm to use if no Method is provided. Should always provide a solution. The automatic algorithm selection will try an analytical solution, and use @@ -446,14 +446,14 @@ def flash_inner_loop(zs, Ks, AvailableMethods=False, Method=None): ys : list[float] Mole fractions of each species in the vapor phase, [-] methods : list, only returned if AvailableMethods == True - List of methods which can be used to obtain a solution with the given + List of methods which can be used to obtain a solution with the given inputs Other Parameters ---------------- Method : string, optional - The method name to use. Accepted methods are 'Analytical', - 'Rachford-Rice', and 'Li-Johns-Ahmadi'. All valid values are also held + The method name to use. Accepted methods are 'Analytical', + 'Rachford-Rice', and 'Li-Johns-Ahmadi'. All valid values are also held in the list `flash_inner_loop_methods`. AvailableMethods : bool, optional If True, function will determine which methods can be used to obtain @@ -512,22 +512,22 @@ def list_methods(): raise Exception('Incorrect Method input') -def NRTL(xs, taus, alphas): - r'''Calculates the activity coefficients of each species in a mixture +def NRTL(xs, taus, alphas): + r'''Calculates the activity coefficients of each species in a mixture using the Non-Random Two-Liquid (NRTL) method, given their mole fractions, dimensionless interaction parameters, and nonrandomness constants. Those are normally correlated with temperature in some form, and need to be calculated separately. - + .. math:: \ln(\gamma_i)=\frac{\displaystyle\sum_{j=1}^{n}{x_{j}\tau_{ji}G_{ji}}} {\displaystyle\sum_{k=1}^{n}{x_{k}G_{ki}}}+\sum_{j=1}^{n} {\frac{x_{j}G_{ij}}{\displaystyle\sum_{k=1}^{n}{x_{k}G_{kj}}}} {\left ({\tau_{ij}-\frac{\displaystyle\sum_{m=1}^{n}{x_{m}\tau_{mj} G_{mj}}}{\displaystyle\sum_{k=1}^{n}{x_{k}G_{kj}}}}\right )} - + G_{ij}=\text{exp}\left ({-\alpha_{ij}\tau_{ij}}\right ) - + Parameters ---------- xs : list[float] @@ -545,35 +545,35 @@ def NRTL(xs, taus, alphas): Notes ----- - This model needs N^2 parameters. - + This model needs N^2 parameters. + One common temperature dependence of the nonrandomness constants is: - + .. math:: \alpha_{ij}=c_{ij}+d_{ij}T - + Most correlations for the interaction parameters include some of the terms shown in the following form: - + .. math:: \tau_{ij}=A_{ij}+\frac{B_{ij}}{T}+\frac{C_{ij}}{T^{2}}+D_{ij} \ln{\left ({T}\right )}+E_{ij}T^{F_{ij}} - + Examples -------- Ethanol-water example, at 343.15 K and 1 MPa: - - >>> NRTL(xs=[0.252, 0.748], taus=[[0, -0.178], [1.963, 0]], + + >>> NRTL(xs=[0.252, 0.748], taus=[[0, -0.178], [1.963, 0]], ... alphas=[[0, 0.2974],[.2974, 0]]) [1.9363183763514304, 1.1537609663170014] - + References ---------- - .. [1] Renon, Henri, and J. M. Prausnitz. "Local Compositions in - Thermodynamic Excess Functions for Liquid Mixtures." AIChE Journal 14, + .. [1] Renon, Henri, and J. M. Prausnitz. "Local Compositions in + Thermodynamic Excess Functions for Liquid Mixtures." AIChE Journal 14, no. 1 (1968): 135-144. doi:10.1002/aic.690140124. - .. [2] Gmehling, Jurgen, Barbel Kolbe, Michael Kleiber, and Jurgen Rarey. - Chemical Thermodynamics for Process Simulation. 1st edition. Weinheim: + .. [2] Gmehling, Jurgen, Barbel Kolbe, Michael Kleiber, and Jurgen Rarey. + Chemical Thermodynamics for Process Simulation. 1st edition. Weinheim: Wiley-VCH, 2012. ''' gammas = [] @@ -596,15 +596,15 @@ def NRTL(xs, taus, alphas): def Wilson(xs, params): - r'''Calculates the activity coefficients of each species in a mixture + r'''Calculates the activity coefficients of each species in a mixture using the Wilson method, given their mole fractions, and - dimensionless interaction parameters. Those are normally correlated with + dimensionless interaction parameters. Those are normally correlated with temperature, and need to be calculated separately. - + .. math:: \ln \gamma_i = 1 - \ln \left(\sum_j^N \Lambda_{ij} x_j\right) -\sum_j^N \frac{\Lambda_{ji}x_j}{\displaystyle\sum_k^N \Lambda_{jk}x_k} - + Parameters ---------- xs : list[float] @@ -620,40 +620,40 @@ def Wilson(xs, params): Notes ----- - This model needs N^2 parameters. - - The original model correlated the interaction parameters using the standard + This model needs N^2 parameters. + + The original model correlated the interaction parameters using the standard pure-component molar volumes of each species at 25°C, in the following form: - + .. math:: \Lambda_{ij} = \frac{V_j}{V_i} \exp\left(\frac{-\lambda_{i,j}}{RT}\right) - - However, that form has less flexibility and offered no advantage over + + However, that form has less flexibility and offered no advantage over using only regressed parameters. Most correlations for the interaction parameters include some of the terms shown in the following form: - + .. math:: - \ln \Lambda_{ij} =a_{ij}+\frac{b_{ij}}{T}+c_{ij}\ln T + d_{ij}T + \ln \Lambda_{ij} =a_{ij}+\frac{b_{ij}}{T}+c_{ij}\ln T + d_{ij}T + \frac{e_{ij}}{T^2} + h_{ij}{T^2} - + The Wilson model is not applicable to liquid-liquid systems. - + Examples -------- Ethanol-water example, at 343.15 K and 1 MPa: - + >>> Wilson([0.252, 0.748], [[1, 0.154], [0.888, 1]]) [1.8814926087178843, 1.1655774931125487] - + References ---------- - .. [1] Wilson, Grant M. "Vapor-Liquid Equilibrium. XI. A New Expression for - the Excess Free Energy of Mixing." Journal of the American Chemical + .. [1] Wilson, Grant M. "Vapor-Liquid Equilibrium. XI. A New Expression for + the Excess Free Energy of Mixing." Journal of the American Chemical Society 86, no. 2 (January 1, 1964): 127-130. doi:10.1021/ja01056a002. - .. [2] Gmehling, Jurgen, Barbel Kolbe, Michael Kleiber, and Jurgen Rarey. - Chemical Thermodynamics for Process Simulation. 1st edition. Weinheim: + .. [2] Gmehling, Jurgen, Barbel Kolbe, Michael Kleiber, and Jurgen Rarey. + Chemical Thermodynamics for Process Simulation. 1st edition. Weinheim: Wiley-VCH, 2012. ''' gammas = [] @@ -663,31 +663,31 @@ def Wilson(xs, params): tot2 = 0. for j in cmps: tot2 += params[j][i]*xs[j]/sum([params[j][k]*xs[k] for k in cmps]) - + gamma = exp(1. - tot1 - tot2) gammas.append(gamma) return gammas def UNIQUAC(xs, rs, qs, taus): - r'''Calculates the activity coefficients of each species in a mixture - using the Universal quasi-chemical (UNIQUAC) equation, given their mole - fractions, `rs`, `qs`, and dimensionless interaction parameters. The - interaction parameters are normally correlated with temperature, and need + r'''Calculates the activity coefficients of each species in a mixture + using the Universal quasi-chemical (UNIQUAC) equation, given their mole + fractions, `rs`, `qs`, and dimensionless interaction parameters. The + interaction parameters are normally correlated with temperature, and need to be calculated separately. - + .. math:: \ln \gamma_i = \ln \frac{\Phi_i}{x_i} + \frac{z}{2} q_i \ln - \frac{\theta_i}{\Phi_i}+ l_i - \frac{\Phi_i}{x_i}\sum_j^N x_j l_j - - q_i \ln\left( \sum_j^N \theta_j \tau_{ji}\right)+ q_i - q_i\sum_j^N + \frac{\theta_i}{\Phi_i}+ l_i - \frac{\Phi_i}{x_i}\sum_j^N x_j l_j + - q_i \ln\left( \sum_j^N \theta_j \tau_{ji}\right)+ q_i - q_i\sum_j^N \frac{\theta_j \tau_{ij}}{\sum_k^N \theta_k \tau_{kj}} - - \theta_i = \frac{x_i q_i}{\displaystyle\sum_{j=1}^{n} x_j q_j} - + + \theta_i = \frac{x_i q_i}{\displaystyle\sum_{j=1}^{n} x_j q_j} + \Phi_i = \frac{x_i r_i}{\displaystyle\sum_{j=1}^{n} x_j r_j} - + l_i = \frac{z}{2}(r_i - q_i) - (r_i - 1) - + Parameters ---------- xs : list[float] @@ -707,57 +707,57 @@ def UNIQUAC(xs, rs, qs, taus): Notes ----- - This model needs N^2 parameters. - + This model needs N^2 parameters. + The original expression for the interaction parameters is as follows: - + .. math:: \tau_{ji} = \exp\left(\frac{-\Delta u_{ij}}{RT}\right) - - However, it is seldom used. Most correlations for the interaction + + However, it is seldom used. Most correlations for the interaction parameters include some of the terms shown in the following form: - + .. math:: - \ln \tau{ij} =a_{ij}+\frac{b_{ij}}{T}+c_{ij}\ln T + d_{ij}T + \ln \tau{ij} =a_{ij}+\frac{b_{ij}}{T}+c_{ij}\ln T + d_{ij}T + \frac{e_{ij}}{T^2} - + This model is recast in a slightly more computationally efficient way in [2]_, as shown below: - + .. math:: \ln \gamma_i = \ln \gamma_i^{res} + \ln \gamma_i^{comb} - + \ln \gamma_i^{res} = q_i \left(1 - \ln\frac{\sum_j^N q_j x_j \tau_{ji}} {\sum_j^N q_j x_j}- \sum_j \frac{q_k x_j \tau_{ij}}{\sum_k q_k x_k \tau_{kj}}\right) - - \ln \gamma_i^{comb} = (1 - V_i + \ln V_i) - \frac{z}{2}q_i\left(1 - + + \ln \gamma_i^{comb} = (1 - V_i + \ln V_i) - \frac{z}{2}q_i\left(1 - \frac{V_i}{F_i} + \ln \frac{V_i}{F_i}\right) - + V_i = \frac{r_i}{\sum_j^N r_j x_j} - + F_i = \frac{q_i}{\sum_j q_j x_j} - + Examples -------- Ethanol-water example, at 343.15 K and 1 MPa: - - >>> UNIQUAC(xs=[0.252, 0.748], rs=[2.1055, 0.9200], qs=[1.972, 1.400], + + >>> UNIQUAC(xs=[0.252, 0.748], rs=[2.1055, 0.9200], qs=[1.972, 1.400], ... taus=[[1.0, 1.0919744384510301], [0.37452902779205477, 1.0]]) [2.35875137797083, 1.2442093415968987] - + References ---------- - .. [1] Abrams, Denis S., and John M. Prausnitz. "Statistical Thermodynamics - of Liquid Mixtures: A New Expression for the Excess Gibbs Energy of + .. [1] Abrams, Denis S., and John M. Prausnitz. "Statistical Thermodynamics + of Liquid Mixtures: A New Expression for the Excess Gibbs Energy of Partly or Completely Miscible Systems." AIChE Journal 21, no. 1 (January - 1, 1975): 116-28. doi:10.1002/aic.690210115. - .. [2] Gmehling, Jurgen, Barbel Kolbe, Michael Kleiber, and Jurgen Rarey. - Chemical Thermodynamics for Process Simulation. 1st edition. Weinheim: + 1, 1975): 116-28. doi:10.1002/aic.690210115. + .. [2] Gmehling, Jurgen, Barbel Kolbe, Michael Kleiber, and Jurgen Rarey. + Chemical Thermodynamics for Process Simulation. 1st edition. Weinheim: Wiley-VCH, 2012. .. [3] Maurer, G., and J. M. Prausnitz. "On the Derivation and Extension of - the Uniquac Equation." Fluid Phase Equilibria 2, no. 2 (January 1, - 1978): 91-99. doi:10.1016/0378-3812(78)85002-X. + the Uniquac Equation." Fluid Phase Equilibria 2, no. 2 (January 1, + 1978): 91-99. doi:10.1016/0378-3812(78)85002-X. ''' cmps = range(len(xs)) rsxs = sum([rs[i]*xs[i] for i in cmps]) @@ -793,7 +793,7 @@ def valid_range(zs, Ks): return valid if not valid_range(zs, Ks): raise Exception('Solution does not exist') - + V_over_F, xs, ys = flash_inner_loop(zs=zs, Ks=Ks) if V_over_F < 0: raise Exception('V_over_F is negative!') @@ -841,27 +841,27 @@ def bubble_at_T(zs, Psats, fugacities=None, gammas=None): def identify_phase(T, P, Tm=None, Tb=None, Tc=None, Psat=None): - r'''Determines the phase of a one-species chemical system according to + r'''Determines the phase of a one-species chemical system according to basic rules, using whatever information is available. Considers only the phases liquid, solid, and gas; does not consider two-phase - scenarios, as should occurs between phase boundaries. - - * If the melting temperature is known and the temperature is under or equal + scenarios, as should occurs between phase boundaries. + + * If the melting temperature is known and the temperature is under or equal to it, consider it a solid. - * If the critical temperature is known and the temperature is greater or + * If the critical temperature is known and the temperature is greater or equal to it, consider it a gas. - * If the vapor pressure at `T` is known and the pressure is under or equal - to it, consider it a gas. If the pressure is greater than the vapor + * If the vapor pressure at `T` is known and the pressure is under or equal + to it, consider it a gas. If the pressure is greater than the vapor pressure, consider it a liquid. * If the melting temperature, critical temperature, and vapor pressure are not known, attempt to use the boiling point to provide phase information. If the pressure is between 90 kPa and 110 kPa (approximately normal), - consider it a liquid if it is under the boiling temperature and a gas if + consider it a liquid if it is under the boiling temperature and a gas if above the boiling temperature. * If the pressure is above 110 kPa and the boiling temperature is known, consider it a liquid if the temperature is under the boiling temperature. * Return None otherwise. - + Parameters ---------- T : float @@ -884,7 +884,7 @@ def identify_phase(T, P, Tm=None, Tb=None, Tc=None, Psat=None): Notes ----- - No special attential is paid to any phase transition. For the case where + No special attential is paid to any phase transition. For the case where the melting point is not provided, the possibility of the fluid being solid is simply ignored. @@ -899,7 +899,7 @@ def identify_phase(T, P, Tm=None, Tb=None, Tc=None, Psat=None): # No special return value for the critical point return 'g' elif Psat: - # Do not allow co-existence of phases; transition to 'l' directly under + # Do not allow co-existence of phases; transition to 'l' directly under if P <= Psat: return 'g' elif P > Psat: @@ -914,7 +914,7 @@ def identify_phase(T, P, Tm=None, Tb=None, Tc=None, Psat=None): return 'g' elif P > 1.1E5 and T <= Tb: # For the higher-pressure case, it is definitely liquid if under Tb - # Above the normal boiling point, impossible to say - return None + # Above the normal boiling point, impossible to say - return None return 'l' else: return None @@ -1035,6 +1035,9 @@ def list_methods(): return Pbubble + + + def Pdew_mixture(T=None, zs=None, Psats=None, CASRNs=None, AvailableMethods=False, Method=None): # pragma: no cover ''' From 80c233511088987cb3a5d14da2ff2498efc7e66a Mon Sep 17 00:00:00 2001 From: Enrique Cintron Date: Thu, 25 May 2017 01:34:14 -0400 Subject: [PATCH 4/4] added function to calculate bubble point at a given pressure. preliminary test case added. --- tests/test_activity.py | 125 +++++++++++++++++++++++------------------ thermo/activity.py | 34 ++++++++++- 2 files changed, 104 insertions(+), 55 deletions(-) diff --git a/tests/test_activity.py b/tests/test_activity.py index 89cc245e..44323d5a 100644 --- a/tests/test_activity.py +++ b/tests/test_activity.py @@ -26,37 +26,54 @@ import pandas as pd from math import exp, log from thermo.activity import * - +from thermo.chemical import Mixture def test_K_value(): K = K_value(101325, 3000.) assert_allclose(K, 0.029607698001480384) - + K = K_value(P=101325, Psat=3000, gamma=0.9) assert_allclose(K, 0.026646928201332347) - + K = K_value(P=101325, Psat=3000, gamma=0.9, Poynting=1.1) assert_allclose(K, 0.029311621021465586) - + K = K_value(phi_l=1.6356, phi_g=0.88427) assert_allclose(K, 1.8496613025433408) - + K = K_value(P=1E6, Psat=1938800, phi_l=1.4356, phi_g=0.88427, gamma=0.92) assert_allclose(K, 2.8958055544121137) - + K = K_value(P=1E6, Psat=1938800, phi_l=1.4356, phi_g=0.88427, gamma=0.92, Poynting=0.999) assert_allclose(K, 2.8929097488577016) - + with pytest.raises(Exception): K_value(101325) with pytest.raises(Exception): K_value(101325, gamma=0.9) - + with pytest.raises(Exception): K_value(P=1E6, Psat=1938800, phi_l=0.88427, gamma=0.92) +def test_bubble_at_P_with_ideal_mixing(): + '''Check to see if the bubble pressure calculated from the temperature + matches the temperature calculated by the test function''' + + test_mix = Mixture(['ethylene oxide', + 'tetrahydrofuran', + 'beta-propiolactone'], + ws=[6021, 111569.76, 30711.21, ], + T=273.15 + 80, + P=101325 + 1.5e5) + + bubble_temp = bubble_at_P(test_mix.Pbubble, + test_mix.zs, + test_mix.VaporPressures) + + assert_allclose(test_mix.T, bubble_temp) + def test_Rachford_Rice_flash_error(): err = Rachford_Rice_flash_error(0.5, zs=[0.5, 0.3, 0.2], Ks=[1.685, 0.742, 0.532]) @@ -70,7 +87,7 @@ def test_Rachford_Rice_solution(): assert_allclose(xs, xs_expect) assert_allclose(ys, ys_expect) - + def test_flash_inner_loop(): V_over_F, xs, ys = flash_inner_loop(zs=[0.5, 0.3, 0.2], Ks=[1.685, 0.742, 0.532], Method='Analytical') xs_expect = [0.33940869696634357, 0.3650560590371706, 0.2955352439964858] @@ -84,21 +101,21 @@ def test_flash_inner_loop(): assert_allclose(V_over_F, 0.416058394160584) V_over_F, xs, ys = flash_inner_loop(zs=[0.6, 0.4], Ks=[1.685, 0.4]) assert_allclose(V_over_F, 0.416058394160584) - + with pytest.raises(Exception): flash_inner_loop(zs=[0.6, 0.4], Ks=[1.685, 0.4], Method='FAIL') with pytest.raises(Exception): flash_inner_loop(zs=[0.1, 0.2, 0.3, 0.4], Ks=[4.2, 1.75, 0.74, 0.34], Method='Analytical') - + methods = flash_inner_loop(zs=[0.1, 0.2, 0.3, 0.4], Ks=[4.2, 1.75, 0.74, 0.34], AvailableMethods=True) assert methods == ['Rachford-Rice', 'Li-Johns-Ahmadi'] - + def test_flash_solution_algorithms(): flash_inner_loop_RR = lambda zs, Ks: flash_inner_loop(zs=zs, Ks=Ks, Method='Rachford-Rice') flash_inner_loop_LJA = lambda zs, Ks: flash_inner_loop(zs=zs, Ks=Ks, Method='Li-Johns-Ahmadi') - - algorithms = [Rachford_Rice_solution, Li_Johns_Ahmadi_solution, + + algorithms = [Rachford_Rice_solution, Li_Johns_Ahmadi_solution, flash_inner_loop, flash_inner_loop_RR, flash_inner_loop_LJA] for algo in algorithms: # Said to be in: J.D. Seader, E.J. Henley, D.K. Roper, Separation Process Principles, third ed., John Wiley & Sons, New York, 2010. @@ -106,21 +123,21 @@ def test_flash_solution_algorithms(): Ks = [4.2, 1.75, 0.74, 0.34] V_over_F_expect = 0.12188885 xs_expect = [0.07194015, 0.18324807, 0.30981849, 0.43499379] - + V_over_F, xs, ys = algo(zs=zs, Ks=Ks) assert_allclose(V_over_F, V_over_F_expect, rtol=1E-4) assert_allclose(xs, xs_expect, rtol=1E-4) - + # Said to be in: B.A. Finlayson, Introduction to Chemical Engineering Computing, second ed., John Wiley & Sons, New York, 2012. zs = [0.1, 0.3, 0.4, 0.2] Ks = [6.8, 2.2, 0.8, 0.052] V_over_F_expect = 0.42583973 xs_expect = [0.02881952, 0.19854300, 0.43723872, 0.33539943] - + V_over_F, xs, ys = algo(zs=zs, Ks=Ks) assert_allclose(V_over_F, V_over_F_expect, rtol=1E-5) assert_allclose(xs, xs_expect, rtol=1E-5) - + # Said to be in: J. Vidal, Thermodynamics: Applications in Chemical Engineering and the Petroleum Industry, Technip, Paris, 2003. zs = [0.2, 0.3, 0.4, 0.05, 0.05] Ks = [2.5250, 0.7708, 1.0660, 0.2401, 0.3140] @@ -129,28 +146,28 @@ def test_flash_solution_algorithms(): V_over_F, xs, ys = algo(zs=zs, Ks=Ks) assert_allclose(V_over_F, V_over_F_expect, rtol=1E-2) assert_allclose(xs, xs_expect, rtol=1E-2) - - + + # Said to be in: R. Monroy-Loperena, F.D. Vargas-Villamil, On the determination of the polynomial defining of vapor-liquid split of multicomponent mixtures, Chem.Eng. Sci. 56 (2001) 5865–5868. zs = [0.05, 0.10, 0.15, 0.30, 0.30, 0.10] Ks = [6.0934, 2.3714, 1.3924, 1.1418, 0.6457, 0.5563] V_over_F_expect = 0.72073810 xs_expect = [0.01070433, 0.05029118, 0.11693011, 0.27218275, 0.40287788, 0.14701374] - + V_over_F, xs, ys = algo(zs=zs, Ks=Ks) assert_allclose(V_over_F, V_over_F_expect, rtol=1E-6) assert_allclose(xs, xs_expect, rtol=1E-6) - + # Said to be in: R. Monroy-Loperena, F.D. Vargas-Villamil, On the determination of the polynomial defining of vapor-liquid split of multicomponent mixtures, Chem.Eng. Sci. 56 (2001) 5865–5868. zs = [0.3727, 0.0772, 0.0275, 0.0071, 0.0017, 0.0028, 0.0011, 0.0015, 0.0333, 0.0320, 0.0608, 0.0571, 0.0538, 0.0509, 0.0483, 0.0460, 0.0439, 0.0420, 0.0403] Ks = [7.11, 4.30, 3.96, 1.51, 1.20, 1.27, 1.16, 1.09, 0.86, 0.80, 0.73, 0.65, 0.58, 0.51, 0.45, 0.39, 0.35, 0.30, 0.26] V_over_F_expect = 0.84605135 xs_expect = [0.06041132, 0.02035881, 0.00784747, 0.00495988, 0.00145397, 0.00227932, 0.00096884, 0.00139386, 0.03777425, 0.03851756, 0.07880076, 0.08112154, 0.08345504, 0.08694391, 0.09033579, 0.09505925, 0.09754111, 0.10300074, 0.10777648] - + V_over_F, xs, ys = algo(zs=zs, Ks=Ks) assert_allclose(V_over_F, V_over_F_expect, rtol=1E-6) assert_allclose(xs, xs_expect, rtol=1E-5) - + # Random example from MultiComponentFlash.xlsx, https://6507a56d-a-62cb3a1a-s-sites.googlegroups.com/site/simulationsmodelsandworksheets/MultiComponentFlash.xlsx?attachauth=ANoY7coiZq4OX8HjlI75HGTWiegJ9Tqz6cyqmmmH9ib-dhcNL89TIUTmQw3HxrnolKHgYuL66drYGasDgTkf4_RrWlciyRKwJCbSi5YgTG1GfZR_UhlBuaoKQvrW_L8HdboB3PYejRbzVQaCshwzYcOeGCZycdXQdF9scxoiZLpy7wbUA0xx8j9e4nW1D9PjyApC-MjsjqjqL10HFcw1KVr5sD0LZTkZCqFYA1HReqLzOGZE01_b9sfk351BB33mwSgWQlo3DLVe&attredirects=0&d=1 Ks = [0.90000, 2.70000, 0.38000, 0.09800, 0.03800, 0.02400, 0.07500, 0.00019, 0.00070] zs = [0.0112, 0.8957, 0.0526, 0.0197, 0.0068, 0.0047, 0.0038, 0.0031, 0.0024] @@ -163,13 +180,13 @@ def test_flash_solution_algorithms(): Ks = [1.081310969639700E+002, 6.600350291317650E+000, 3.946099352050670E+001, 4.469649874919970E+000, 9.321795620021620E-001, 3.213910680361160E-001, 2.189276413305250E-001, 7.932561445994600E-002, 5.868520215582420E-002, 2.182440138190620E-002, 1.769601670781200E-003, 2.855879877894100E-005, 2.718731754877420E-007, 2.154768511018220E-009, 2.907309385811110E-013] V_over_F, _, _ = algo(zs=zs, Ks=Ks) assert_allclose(V_over_F, 0.48908229446749, rtol=1E-5) - + # Random example from VLE_Pete310.xls http://www.pe.tamu.edu/barrufet/public_html/PETE310/goodies/VLE_Pete310.xls # Had to resolve because the goal which was specified by its author was far off from 0 Ks = [3.578587993622110000, 10.348850231319200000, 2.033984472604390000, 0.225176162885930000, 0.096215673714140800, 0.070685757228660000, 0.001509595637954720, ] zs = [0.0387596899224806, 0.1937984496124030, 0.0775193798449612, 0.1162790697674420, 0.1085271317829460, 0.1550387596899220, 0.3100775193798450] V_over_F, _, _ = algo(zs=zs, Ks=Ks) - + assert_allclose(V_over_F, 0.191698639911785) @@ -188,41 +205,41 @@ def test_fuzz(): def test_identify_phase(): # Above the melting point, higher pressure than the vapor pressure assert 'l' == identify_phase(T=280, P=101325, Tm=273.15, Psat=991) - + # Above the melting point, lower pressure than the vapor pressure assert 'g' == identify_phase(T=480, P=101325, Tm=273.15, Psat=1791175) - + # Above the melting point, above the critical pressure (no vapor pressure available) assert 'g' == identify_phase(T=650, P=10132500000, Tm=273.15, Psat=None, Tc=647.3) - + # No vapor pressure specified, under the melting point assert 's' == identify_phase(T=250, P=100, Tm=273.15) - + # No data, returns None assert None == identify_phase(T=500, P=101325) - + # No Tm, under Tb, at normal atmospheric pressure assert 'l' == identify_phase(T=200, P=101325, Tb=373.15) - + # Incorrect case by design: # at 371 K, Psat is 93753 Pa, meaning the actual phase is gas assert 'l' == identify_phase(T=371, P=91000, Tb=373.15) - + # Above Tb, while still atmospheric == gas assert 'g' == identify_phase(T=400, P=101325, Tb=373.15) - + # Above Tb, 1 MPa == None - don't try to guess assert None == identify_phase(T=400, P=1E6, Tb=373.15) - + # Another wrong point - at 1 GPa, should actually be a solid as well assert 'l' == identify_phase(T=371, P=1E9, Tb=373.15) - + # At the critical point, consider it a gas assert 'g' == identify_phase(T=647.3, P=22048320.0, Tm=273.15, Psat=22048320.0, Tc=647.3) - + # Just under the critical point assert 'l' == identify_phase(T=647.2, P=22048320.0, Tm=273.15, Psat=22032638.96749514, Tc=647.3) - + def test_NRTL(): # P05.01b VLE Behavior of Ethanol - Water Using NRTL @@ -230,7 +247,7 @@ def test_NRTL(): assert_allclose(gammas, [1.9363183763514304, 1.1537609663170014]) # Test the general form against the simpler binary form - def NRTL2(xs, taus, alpha): + def NRTL2(xs, taus, alpha): x1, x2 = xs tau12, tau21 = taus G12 = exp(-alpha*tau12) @@ -243,23 +260,23 @@ def NRTL2(xs, taus, alpha): assert_allclose(gammas, [1.9363183763514304, 1.1537609663170014]) - # Example by + # Example by # https://github.com/iurisegtovich/PyTherm-applied-thermodynamics/blob/master/contents/main-lectures/GE1-NRTL-graphically.ipynb tau = [[0.0, 2.291653777670652, 0.5166949715946564], [4.308652420938829, 0.0, 1.6753963198550983], [0.5527434579849811, 0.15106032392136134, 0.0]] alpha = [[0.0, 0.4, 0.3], [0.4, 0.0, 0.3], [0.3, 0.3, 0.0]] xs = [.1, .3, .6] gammas = (NRTL(xs, tau, alpha)) assert_allclose(gammas, [2.7175098659360413, 2.1373006474468697, 1.085133765593844]) - + def test_Wilson(): # P05.01a VLE Behavior of Ethanol - Water Using Wilson # http://chemthermo.ddbst.com/Problems_Solutions/Mathcad_Files/P05.01a%20VLE%20Behavior%20of%20Ethanol%20-%20Water%20Using%20Wilson.xps gammas = Wilson([0.252, 0.748], [[1, 0.154], [0.888, 1]]) assert_allclose(gammas, [1.8814926087178843, 1.1655774931125487]) - + # Test the general form against the simpler binary form - def Wilson2(molefracs, lambdas): + def Wilson2(molefracs, lambdas): x1 = molefracs[0] x2 = molefracs[1] l12 = lambdas[0] @@ -270,13 +287,13 @@ def Wilson2(molefracs, lambdas): gammas = Wilson2([0.252, 0.748], [0.154, 0.888]) assert_allclose(gammas, [1.8814926087178843, 1.1655774931125487]) - - # Test 3 parameter version: + + # Test 3 parameter version: # 05.09 Compare Experimental VLE to Wilson Equation Results # http://chemthermo.ddbst.com/Problems_Solutions/Mathcad_Files/05.09%20Compare%20Experimental%20VLE%20to%20Wilson%20Equation%20Results.xps # Extra decimals obtained via the actual MathCad worksheet xs = [0.229, 0.175, 0.596] - params = [[1, 1.1229699812593, 0.73911816162836], + params = [[1, 1.1229699812593, 0.73911816162836], [3.26947621620298, 1, 1.16749678447695], [0.37280197780932, 0.01917909648619, 1]] gammas = Wilson(xs, params) @@ -295,7 +312,7 @@ def test_UNIQUAC(): gammas = UNIQUAC(xs=[.7566, .2434], rs=[2.1055, 3.1878], qs=[1.972, 2.4], taus=[[1.0, 1.17984681869376], [0.22826016391070073, 1.0]]) assert_allclose(gammas, [1.0826343452263132, 3.0176007269546083]) - # Example 7.3 in [2], for electrolytes + # Example 7.3 in [2], for electrolytes gammas = UNIQUAC(xs=[0.05, 0.025, 0.925], rs=[1., 1., 0.92], qs=[1., 1., 1.4], taus=[[1.0, 0.4052558731309731, 2.7333668483468143], [21.816716876191823, 1.0, 0.06871094878791346], [0.4790878929721784, 3.3901086879605944, 1.0]]) assert_allclose(gammas, [0.3838177662072466, 0.49469915162858774, 1.0204435746722416]) @@ -303,15 +320,15 @@ def test_UNIQUAC(): def UNIQUAC_original_form(xs, rs, qs, taus): # This works too - just slower. cmps = range(len(xs)) - + rsxs = sum([rs[i]*xs[i] for i in cmps]) qsxs = sum([qs[i]*xs[i] for i in cmps]) - + Phis = [rs[i]*xs[i]/rsxs for i in cmps] thetas = [qs[i]*xs[i]/qsxs for i in cmps] - + ls = [5*(ri - qi) - (ri - 1.) for ri, qi in zip(rs, qs)] - + gammas = [] for i in cmps: lngamma = (log(Phis[i]/xs[i]) + 5*qs[i]*log(thetas[i]/Phis[i]) + ls[i] @@ -321,12 +338,12 @@ def UNIQUAC_original_form(xs, rs, qs, taus): - qs[i]*sum([thetas[j]*taus[i][j]/sum([thetas[k]*taus[k][j] for k in cmps]) for j in cmps])) gammas.append(exp(lngamma)) return gammas - + gammas = UNIQUAC_original_form(xs=[.7566, .2434], rs=[2.1055, 3.1878], qs=[1.972, 2.4], taus=[[1.0, 1.17984681869376], [0.22826016391070073, 1.0]]) assert_allclose(gammas, [1.0826343452263132, 3.0176007269546083]) - + gammas = UNIQUAC_original_form(xs=[0.252, 0.748], rs=[2.1055, 0.9200], qs=[1.972, 1.400], taus=[[1.0, 1.0919744384510301], [0.37452902779205477, 1.0]]) assert_allclose(gammas, [2.35875137797083, 1.2442093415968987]) - + gammas = UNIQUAC_original_form(xs=[0.05, 0.025, 0.925], rs=[1., 1., 0.92], qs=[1., 1., 1.4], taus=[[1.0, 0.4052558731309731, 2.7333668483468143], [21.816716876191823, 1.0, 0.06871094878791346], [0.4790878929721784, 3.3901086879605944, 1.0]]) assert_allclose(gammas, [0.3838177662072466, 0.49469915162858774, 1.0204435746722416]) diff --git a/thermo/activity.py b/thermo/activity.py index 3e891f28..8322683d 100644 --- a/thermo/activity.py +++ b/thermo/activity.py @@ -26,7 +26,8 @@ 'Li_Johns_Ahmadi_solution', 'flash_inner_loop', 'NRTL', 'Wilson', 'UNIQUAC', 'flash', 'dew_at_T', 'bubble_at_T', 'identify_phase', 'mixture_phase_methods', - 'identify_phase_mixture', 'Pbubble_mixture', 'Pdew_mixture'] + 'identify_phase_mixture', 'Pbubble_mixture', 'bubble_at_P', + 'Pdew_mixture'] from scipy.optimize import fsolve, newton, brenth from thermo.utils import exp, log @@ -1035,7 +1036,38 @@ def list_methods(): return Pbubble +def bubble_at_P(P, zs, vapor_pressure_eqns, fugacities=None, gammas=None): + '''Calculates bubble point for a given pressure + Parameters + ---------- + P : float + Pressure, [Pa] + zs : list[float] + Overall mole fractions of all species, [-] + vapor_pressure_eqns : list[functions] + Temperature dependent function for each specie, Returns Psat, [Pa] + fugacities : list[float], optional + fugacities of each species, defaults to list of ones[-] + gammas : list[float], optional + gammas of each species, defaults to list of ones[-] + + Returns + ------- + Tbubble : float, optional + Temperature of bubble point at pressure `P`, [K] + + ''' + + def bubble_P_error(T): + Psats = [VP(T) for VP in vapor_pressure_eqns] + Pcalc = bubble_at_T(zs, Psats, fugacities, gammas) + + return P - Pcalc + + T_bubble = newton(bubble_P_error, 300) + + return T_bubble def Pdew_mixture(T=None, zs=None, Psats=None, CASRNs=None,