signature:
def Crowl_Louvar_UFL ( atoms ) :
    r'''Calculates upper flammability limit , using the Crowl - Louvar [ 1 ] _
 correlation . Uses molecular formula only .
 The upper flammability limit of a gas is air is :
 . . math : :
 C _ mH _ xO _ y + zO _ 2 \ to mCO _ 2 + \ frac { x } { 2 } H _ 2O
 \ text { UFL } = \ frac { 3.5 } { 4.76m + 1.19x - 2.38y + 1}
 Parameters
 atoms : dict
 Dictionary of atoms and atom counts
 Returns
 UFL : float
 Upper flammability limit , mole fraction
 Notes
 Coefficient of 3.5 taken from [ 2 ] _
 Examples
 Hexane , example from [ 1 ] _ , lit . 7.5 %
 > > > Crowl _ Louvar _ UFL ( { ' H ' : 14 , ' C ' : 6 } )
 0.07572479446127219
 References
 . . [ 1 ] Crowl , Daniel A . , and Joseph F . Louvar . Chemical Process Safety :
 Fundamentals with Applications . 2E . Upper Saddle River , N . J :
 Prentice Hall , 2001.
 . . [ 2 ] Jones , G . W . " Inflammation Limits and Their Practical Application
 in Hazardous Industrial Operations . " Chemical Reviews 22 , no . 1
 ( February 1 , 1938 ) : 1-26 . doi : 10.1021 / cr60071a001'''

implementation:
nC , nH , nO = 0 , 0 , 0
if 'C' in atoms and atoms [ 'C' ] :
    nC = atoms [ 'C' ]
else :
    return None
if 'H' in atoms :
    nH = atoms [ 'H' ]
if 'O' in atoms :
    nO = atoms [ 'O' ]
return 3.5 / ( 4.76 * nC + 1.19 * nH - 2.38 * nO + 1. )


signature:
def Vfls ( self , T = None , P = None ) :
    r'''Volume fractions of all species in a hypothetical pure - liquid phase
 at the current or specified temperature and pressure . If temperature
 or pressure are specified , the non - specified property is assumed to be
 that of the mixture . 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 ( )
 [0.5299671144566751 , 0.47003288554332484]
 > > > S = Mixture ( [ ' hexane ' , ' decane ' ] , zs = [ 0.25 , 0.75 ] )
 > > > S . Vfls ( 298.16 , 101326)
 [0.18301434895886864 , 0.8169856510411313]'''

implementation:
if ( T is None or T == self . T ) and ( P is None or P == self . P ) :
    Vmls = self . Vmls
else :
    if T is None :
        T = self . T
    if P is None :
        P = self . P
    Vmls = [ i ( T , P ) for i in self . VolumeLiquids ]
if none_and_length_check ( [ Vmls ] ) :
    return zs_to_Vfs ( self . zs , Vmls )
return None


signature:
def Vfgs ( self , T = None , P = None ) :
    r'''Volume fractions of all species in a hypothetical pure - gas phase
 at the current or specified temperature and pressure . If temperature
 or pressure are specified , the non - specified property is assumed to be
 that of the mixture . 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 ( )
 [0.18062059238682632 , 0.8193794076131737]
 > > > S = Mixture ( [ ' sulfur hexafluoride ' , ' methane ' ] , zs = [ . 1 , . 9 ] )
 > > > S . Vfgs ( P = 1E2)
 [0.0999987466608421 , 0.9000012533391578]'''

implementation:
if ( T is None or T == self . T ) and ( P is None or P == self . P ) :
    Vmgs = self . Vmgs
else :
    if T is None :
        T = self . T
    if P is None :
        P = self . P
    Vmgs = [ i ( T , P ) for i in self . VolumeGases ]
if none_and_length_check ( [ Vmgs ] ) :
    return zs_to_Vfs ( self . zs , Vmgs )
return None


signature:
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
 { ' C ' : 0.2 , ' O ' : 0.8}'''

implementation:
things = dict ( )
for zi , atoms in zip ( self . zs , self . atomss ) :
    for atom , count in atoms . iteritems ( ) :
        if atom in things :
            things [ atom ] += zi * count
        else :
            things [ atom ] = zi * count
tot = sum ( things . values ( ) )
return { atom : value / tot for atom , value in things . iteritems ( ) }


signature:
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
 { ' C ' : 0.15801826905745822 , ' O ' : 0.8419817309425419}'''

implementation:
things = dict ( )
for zi , atoms in zip ( self . zs , self . atomss ) :
    for atom , count in atoms . iteritems ( ) :
        if atom in things :
            things [ atom ] += zi * count
        else :
            things [ atom ] = zi * count
return mass_fractions ( things )


signature:
def charge_balance ( self ) :
    r'''Charge imbalance of the mixture , in units of [ faraday ] .
 Mixtures meeting the electroneutrality condition will have an imbalance
 of 0.
 Examples
 > > > Mixture ( [ ' Na + ' , ' Cl - ' , ' water ' ] , zs = [ . 01 , . 01 , . 98 ] ) . charge _ balance
 0.0'''

implementation: return sum ( [ zi * ci for zi , ci in zip ( self . zs , self . charges ) ] )


signature:
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
 Mixture instance creates one to actually perform the calculations .
 Examples
 > > > Mixture ( [ ' silver ' , ' platinum ' ] , ws = [ 0.95 , 0.05 ] ) . Cpsm
 25.32745796347474'''

implementation: return self . HeatCapacitySolidMixture ( self . T , self . P , self . zs , self . ws )


signature:
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 ` ;
 each Mixture instance creates one to actually perform the calculations .
 Examples
 > > > Mixture ( [ ' toluene ' , ' decane ' ] , ws = [ . 9 , . 1 ] , T = 300 ) . Cplm
 168.29127923518843'''

implementation: return self . HeatCapacityLiquidMixture ( self . T , self . P , self . zs , self . ws )


signature:
def Cpgm ( self ) :
    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
 Mixture instance creates one to actually perform the calculations .
 Examples
 > > > Mixture ( [ ' oxygen ' , ' nitrogen ' ] , ws = [ . 4 , . 6 ] , T = 350 , P = 1E6 ) . Cpgm
 29.361044582498046'''

implementation: return self . HeatCapacityGasMixture ( self . T , self . P , self . zs , self . ws )


signature:
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
 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
 229.55166388430328'''

implementation:
Cpsm = self . HeatCapacitySolidMixture ( self . T , self . P , self . zs , self . ws )
if Cpsm :
    return property_molar_to_mass ( Cpsm , self . MW )
return None


signature:
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 .
 Note that that interface provides output in molar units .
 Examples
 > > > Mixture ( [ ' water ' , ' sodium chloride ' ] , ws = [ . 9 , . 1 ] , T = 301.5 ) . Cpl
 3735.4604049449786'''

implementation:
Cplm = self . HeatCapacityLiquidMixture ( self . T , self . P , self . zs , self . ws )
if Cplm :
    return property_molar_to_mass ( Cplm , self . MW )
return None


signature:
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
 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
 that interface provides output in molar units .
 Examples
 > > > Mixture ( [ ' oxygen ' , ' nitrogen ' ] , ws = [ . 4 , . 6 ] , T = 350 , P = 1E6 ) . Cpg
 995.8911053614883'''

implementation:
Cpgm = self . HeatCapacityGasMixture ( self . T , self . P , self . zs , self . ws )
if Cpgm :
    return property_molar_to_mass ( Cpgm , self . MW )
return None


signature:
def Cvgm ( self ) :
    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
 from an equation of state .
 Examples
 > > > Mixture ( [ ' water ' ] , ws = [ 1 ] , T = 520 ) . Cvgm
 27.13366316134193'''

implementation:
Cpgm = self . HeatCapacityGasMixture ( self . T , self . P , self . zs , self . ws )
if Cpgm :
    return Cpgm - R
return None


signature:
def Vml ( self ) :
    r'''Liquid - phase molar volume of the mixture at its current
 temperature , pressure , and composition in units of [ m ^ 3 / mol ] . 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'''

implementation: return self . VolumeLiquidMixture ( T = self . T , P = self . P , zs = self . zs , ws = self . ws )


signature:
def Vmg ( self ) :
    r'''Gas - phase molar volume of the mixture at its current
 temperature , pressure , and composition in units of [ m ^ 3 / mol ] . 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'''

implementation: return self . VolumeGasMixture ( T = self . T , P = self . P , zs = self . zs , ws = self . ws )


signature:
def SGg ( self ) :
    r'''Specific gravity of a hypothetical gas phase of the mixture , .
 [ dimensionless ] . The reference condition is air at 15.6 ° C ( 60 ° F ) and
 1 atm ( rho = 1.223 kg / m ^ 3 ) . The definition for gases uses the
 compressibility factor of the reference gas and the mixture both at the
 reference conditions , not the conditions of the mixture .
 Examples
 > > > Mixture ( ' argon ' ) . SGg
 1.3800407778218216'''

implementation:
Vmg = self . VolumeGasMixture ( T = 288.70555555555552 , P = 101325 , zs = self . zs , ws = self . ws )
if Vmg :
    rho = Vm_to_rho ( Vmg , self . MW )
    return SG ( rho , rho_ref = 1.2231876628642968 )
    # calculated with Mixture
return None


signature:
def mul ( self ) :
    r'''Viscosity of the mixture in the liquid phase at its current
 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
 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'''

implementation: return self . ViscosityLiquidMixture ( self . T , self . P , self . zs , self . ws )


signature:
def mug ( self ) :
    r'''Viscosity of the mixture in the gas phase at its current
 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
 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
 1.7298722343367148e - 05'''

implementation: return self . ViscosityGasMixture ( self . T , self . P , self . zs , self . ws )


signature:
def sigma ( self ) :
    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 ` ;
 each Mixture instance creates one to actually perform the calculations .
 Examples
 > > > Mixture ( [ ' water ' ] , ws = [ 1 ] , T = 300 , P = 1E5 ) . sigma
 0.07176932405246211'''

implementation: return self . SurfaceTensionMixture ( self . T , self . P , self . zs , self . ws )


signature:
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 ] .
 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 . thermal _ conductivity . ThermalConductivityLiquidMixture ` ;
 each Mixture instance creates one to actually perform the calculations .
 Examples
 > > > Mixture ( [ ' water ' ] , ws = [ 1 ] , T = 320 ) . kl
 0.6369957248212118'''

implementation: return self . ThermalConductivityLiquidMixture ( self . T , self . P , self . zs , self . ws )


signature:
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 ] .
 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 . thermal _ conductivity . ThermalConductivityGasMixture ` ;
 each Mixture instance creates one to actually perform the calculations .
 Examples
 > > > Mixture ( [ ' water ' ] , ws = [ 1 ] , T = 500 ) . kg
 0.036035173297862676'''

implementation: return self . ThermalConductivityGasMixture ( self . T , self . P , self . zs , self . ws )


signature:
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
 7983.414573003429'''

implementation: return phase_select_property ( phase = self . phase , s = None , l = self . rholm , g = self . rhogm )


signature:
def SG ( self ) :
    r'''Specific gravity of the mixture , [ dimensionless ] .
 For gas - phase conditions , this is calculated at 15.6 ° C ( 60 ° F ) and 1
 atm for the mixture and the reference fluid , air .
 For liquid and solid phase conditions , this is calculated based on a
 reference fluid of water at 4 ° C at 1 atm , but the with the liquid or
 solid mixture ' s density at the currently specified conditions .
 Examples
 > > > Mixture ( ' MTBE ' ) . SG
 0.7428160596603596'''

implementation: return phase_select_property ( phase = self . phase , s = self . SGs , l = self . SGl , g = self . SGg )


signature:
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 [ m ^ 3 / mol ] .
 Examples
 > > > Mixture ( [ ' cyclobutane ' ] , ws = [ 1 ] ) . Vml _ STP
 8.143327329133706e - 05'''

implementation: return self . VolumeLiquidMixture ( T = 298.15 , P = 101325 , zs = self . zs , ws = self . ws )


signature:
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 [ m ^ 3 / mol ] .
 Examples
 > > > Mixture ( [ ' nitrogen ' ] , ws = [ 1 ] ) . Vmg _ STP
 0.02445443688838904'''

implementation: return self . VolumeGasMixture ( T = 298.15 , P = 101325 , zs = self . zs , ws = self . ws )


signature:
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 ] .
 Examples
 > > > Mixture ( [ ' cyclobutane ' ] , ws = [ 1 ] ) . rhol _ STP
 688.9851989526821'''

implementation:
Vml = self . Vml_STP
if Vml :
    return Vm_to_rho ( Vml , self . MW )
return None


signature:
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 ] .
 Examples
 > > > Mixture ( [ ' nitrogen ' ] , ws = [ 1 ] ) . rhog _ STP
 1.145534453639403'''

implementation:
Vmg = self . Vmg_STP
if Vmg :
    return Vm_to_rho ( Vmg , self . MW )
return None


signature:
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 ] .
 Examples
 > > > Mixture ( [ ' cyclobutane ' ] , ws = [ 1 ] ) . Zl _ STP
 0.0033285083663950068'''

implementation:
Vml = self . Vml
if Vml :
    return Z ( self . T , self . P , Vml )
return None


signature:
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 ] .
 Examples
 > > > Mixture ( [ ' nitrogen ' ] , ws = [ 1 ] ) . Zg _ STP
 0.9995520809691023'''

implementation:
Vmg = self . Vmg
if Vmg :
    return Z ( self . T , self . P , Vmg )
return None


signature:
def API ( self ) :
    r'''API gravity of the hypothetical liquid phase of the mixture ,
 [ degrees ] . The reference condition is water at 15.6 ° C ( 60 ° F ) and 1 atm
 ( rho = 999.016 kg / m ^ 3 , standardized ) .
 Examples
 > > > Mixture ( [ ' hexane ' , ' decane ' ] , ws = [ 0.5 , 0.5 ] ) . API
 71.34707841728181'''

implementation:
Vml = self . VolumeLiquidMixture ( T = 288.70555555555552 , P = 101325 , zs = self . zs , ws = self . ws )
if Vml :
    rho = Vm_to_rho ( Vml , self . MW )
sg = SG ( rho , rho_ref = 999.016 )
return SG_to_API ( sg )


signature:
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
 absent .
 Parameters
 Hs : bool
 Whether or not to show hydrogen
 Examples
 Mixture ( [ ' natural gas ' ] ) . draw _ 2d ( )'''

implementation:
try :
    from rdkit . Chem import Draw
    from rdkit . Chem . Draw import IPythonConsole
    if Hs :
        mols = [ i . rdkitmol_Hs for i in self . Chemicals ]
    else :
        mols = [ i . rdkitmol for i in self . Chemicals ]
    return Draw . MolsToImage ( mols )
except :
    return 'Rdkit is required for this feature.'


signature:
def Tt ( CASRN , AvailableMethods = False , Method = None ) :
    r'''This function handles the retrieval of a chemical ' s triple temperature .
 Lookup is based on CASRNs . Will automatically select a data source to use
 if no Method is provided ; returns None if the data is not available .
 Returns data from [ 1 ] _ , or a chemical ' s melting point if available .
 Parameters
 CASRN : string
 CASRN [ - ]
 Returns
 Tt : float
 Triple point temperature , [ K ]
 methods : list , only returned if AvailableMethods = = True
 List of methods which can be used to obtain Tt with the
 given inputs
 Other Parameters
 Method : string , optional
 A string for the method name to use , as defined by constants in
 Tt _ methods
 AvailableMethods : bool , optional
 If True , function will determine which methods can be used to obtain
 the Tt for the desired chemical , and will return methods
 instead of the Tt
 Notes
 Median difference between melting points and triple points is 0.02 K .
 Accordingly , this should be more than good enough for engineering
 applications .
 Temperatures are on the ITS - 68 scale .
 Examples
 Ammonia
 > > > Tt ( ' 7664-41-7 ' )
 195.4799999
 References
 . . [ 1 ] Staveley , L . A . K . , L . Q . Lobo , and J . C . G . Calado . " Triple - Points
 of Low Melting Substances and Their Use in Cryogenic Work . " Cryogenics
 21 , no . 3 ( March 1981 ) : 131-144 . doi : 10.1016/0011-2275(81)90264-2.'''

implementation:
def list_methods ( ) :
    methods = [ ]
    if CASRN in Staveley_data . index :
        methods . append ( STAVELEY )
    if Tm ( CASRN ) :
        methods . append ( MELTING )
    methods . append ( NONE )
    return methods
if AvailableMethods :
    return list_methods ( )
if not Method :
    Method = list_methods ( ) [ 0 ]
if Method == STAVELEY :
    Tt = Staveley_data . at [ CASRN , "Tt68" ]
elif Method == MELTING :
    Tt = Tm ( CASRN )
elif Method == NONE :
    Tt = None
else :
    raise Exception ( 'Failure in in function' )
return Tt


signature:
def Pt ( CASRN , AvailableMethods = False , Method = None ) :
    r'''This function handles the retrieval of a chemical ' s triple pressure .
 Lookup is based on CASRNs . Will automatically select a data source to use
 if no Method is provided ; returns None if the data is not available .
 Returns data from [ 1 ] _ , or attempts to calculate the vapor pressure at the
 triple temperature , if data is available .
 Parameters
 CASRN : string
 CASRN [ - ]
 Returns
 Pt : float
 Triple point pressure , [ Pa ]
 methods : list , only returned if AvailableMethods = = True
 List of methods which can be used to obtain Pt with the
 given inputs
 Other Parameters
 Method : string , optional
 A string for the method name to use , as defined by constants in
 Pt _ methods
 AvailableMethods : bool , optional
 If True , function will determine which methods can be used to obtain
 the Pt for the desired chemical , and will return methods
 instead of the Pt
 Notes
 Examples
 Ammonia
 > > > Pt ( ' 7664-41-7 ' )
 6079.5
 References
 . . [ 1 ] Staveley , L . A . K . , L . Q . Lobo , and J . C . G . Calado . " Triple - Points
 of Low Melting Substances and Their Use in Cryogenic Work . " Cryogenics
 21 , no . 3 ( March 1981 ) : 131-144 . doi : 10.1016/0011-2275(81)90264-2.'''

implementation:
def list_methods ( ) :
    methods = [ ]
    if CASRN in Staveley_data . index and not np . isnan ( Staveley_data . at [ CASRN , 'Pt' ] ) :
        methods . append ( STAVELEY )
    if Tt ( CASRN ) and VaporPressure ( CASRN = CASRN ) . T_dependent_property ( T = Tt ( CASRN ) ) :
        methods . append ( DEFINITION )
    methods . append ( NONE )
    return methods
if AvailableMethods :
    return list_methods ( )
if not Method :
    Method = list_methods ( ) [ 0 ]
if Method == STAVELEY :
    Pt = Staveley_data . at [ CASRN , 'Pt' ]
elif Method == DEFINITION :
    Pt = VaporPressure ( CASRN = CASRN ) . T_dependent_property ( T = Tt ( CASRN ) )
elif Method == NONE :
    Pt = None
else :
    raise Exception ( 'Failure in in function' )
return Pt


signature:
def to_num ( values ) :
    r'''Legacy function to turn a list of strings into either floats
 ( if numeric ) , stripped strings ( if not ) or None if the string is empty .
 Accepts any numeric formatting the float function does .
 Parameters
 values : list
 list of strings
 Returns
 values : list
 list of floats , strings , and None values [ - ]
 Examples
 > > > to _ num ( [ ' 1 ' , ' 1.1 ' , ' 1E5 ' , ' 0xB4 ' , ' ' ] )
 [1.0 , 1.1 , 100000.0 , ' 0xB4 ' , None ]'''

implementation:
for i in range ( len ( values ) ) :
    try :
        values [ i ] = float ( values [ i ] )
    except :
        if values [ i ] == '' :
            values [ i ] = None
        else :
            values [ i ] = values [ i ] . strip ( )
            pass
return values


signature:
def Parachor ( MW , rhol , rhog , sigma ) :
    r'''Calculate Parachor for a pure species , using its density in the
 liquid and gas phases , surface tension , and molecular weight .
 . . math : :
 P = \ frac { \ sigma ^ { 0.25 } MW } { \ rho _ L - \ rho _ V }
 Parameters
 MW : float
 Molecular weight , [ g / mol ]
 rhol : float
 Liquid density [ kg / m ^ 3]
 rhog : float
 Gas density [ kg / m ^ 3]
 sigma : float
 Surface tension , [ N / m ]
 Returns
 P : float
 Parachor , [ N ^ 0.25 * m ^ 2.75 / mol ]
 Notes
 To convert the output of this function to units of [ mN ^ 0.25 * m ^ 2.75 / kmol ] ,
 multiply by 5623.4132519.
 Values in group contribution tables for Parachor are often listed as
 dimensionless , in which they are multiplied by 5623413 and the appropriate
 units to make them dimensionless .
 Examples
 Calculating Parachor from a known surface tension for methyl isobutyl
 ketone at 293.15 K
 > > > Parachor ( 100.15888 , 800.8088185536124 , 4.97865317223119 , 0.02672166960656005)
 5.088443542210164e - 05
 Converting to the ` dimensionless ` form :
 > > > 5623413*5.088443542210164e - 05
 286.14419565030687
 Compared to 274.9 according to a group contribution method described in
 [3 ] _ .
 References
 . . [ 1 ] Poling , Bruce E . The Properties of Gases and Liquids . 5th edition .
 New York : McGraw - Hill Professional , 2000.
 . . [ 2 ] Green , Don , and Robert Perry . Perry ' s Chemical Engineers ' Handbook ,
 8E . McGraw - Hill Professional , 2007.
 . . [ 3 ] Danner , Ronald P , and Design Institute for Physical Property Data .
 Manual for Predicting Chemical Process Design Data . New York , N . Y , 1982.'''

implementation:
rhol , rhog = rhol * 1000. , rhog * 1000.
# Convert kg / m ^ 3 to g / m ^ 3
return sigma ** 0.25 * MW / ( rhol - rhog )


signature:
def phase_identification_parameter ( V , dP_dT , dP_dV , d2P_dV2 , d2P_dVdT ) :
    r'''Calculate the Phase Identification Parameter developed in [ 1 ] _ for
 the accurate and efficient determination of whether a fluid is a liquid or
 a gas based on the results of an equation of state . For supercritical
 conditions , this provides a good method for choosing which property
 correlations to use .
 . . math : :
 \ Pi = V \ left [ \ frac { \ frac { \ partial ^ 2 P } { \ partial V \ partial T } }
 { \ frac { \ partial P } { \ partial T } } - \ frac { \ frac { \ partial ^ 2 P } { \ partial
 V ^ 2 } } { \ frac { \ partial P } { \ partial V } } \ right ]
 Parameters
 V : float
 Molar volume at ` T ` and ` P ` , [ m ^ 3 / mol ]
 dP _ dT : float
 Derivative of ` P ` with respect to ` T ` , [ Pa / K ]
 dP _ dV : float
 Derivative of ` P ` with respect to ` V ` , [ Pa * mol / m ^ 3]
 d2P _ dV2 : float
 Second derivative of ` P ` with respect to ` V ` , [ Pa * mol ^ 2 / m ^ 6]
 d2P _ dVdT : float
 Second derivative of ` P ` with respect to both ` V ` and ` T ` , [ Pa * mol / m ^ 3 / K ]
 Returns
 PIP : float
 Phase Identification Parameter , [ - ]
 Notes
 Heuristics were used by process simulators before the invent of this
 parameter .
 The criteria for liquid is Pi > 1 ; for vapor , Pi < = 1.
 There is also a solid phase mechanism available . For solids , the Solid
 Phase Identification Parameter is greater than 1 , like liquids ; however ,
 unlike liquids , d2P _ dVdT is always > 0 ; it is < 0 for liquids and gases .
 Examples
 Calculated for hexane from the PR EOS at 299 K and 1 MPa ( liquid ) :
 > > > phase _ identification _ parameter ( 0.000130229900874 , 582169.397484,
 . . . - 3.66431747236e + 12 , 4.48067893805e + 17 , - 20518995218.2)
 11.33428990564796
 References
 . . [ 1 ] Venkatarathnam , G . , and L . R . Oellrich . " Identification of the Phase
 of a Fluid Using Partial Derivatives of Pressure , Volume , and
 Temperature without Reference to Saturation Properties : Applications in
 Phase Equilibria Calculations . " Fluid Phase Equilibria 301 , no . 2
 ( February 25 , 2011 ) : 225-33 . doi : 10.1016 / j . fluid . 2010.12.001.
 . . [ 2 ] Jayanti , Pranava Chaitanya , and G . Venkatarathnam . " Identification
 of the Phase of a Substance from the Derivatives of Pressure , Volume and
 Temperature , without Prior Knowledge of Saturation Properties : Extension
 to Solid Phase . " Fluid Phase Equilibria 425 ( October 15 , 2016 ) : 269-277.
 doi : 10.1016 / j . fluid . 2016.06.001.'''

implementation: return V * ( d2P_dVdT / dP_dT - d2P_dV2 / dP_dV )


signature:
def phase_identification_parameter_phase ( d2P_dVdT , V = None , dP_dT = None , dP_dV = None , d2P_dV2 = None ) :
    r'''Uses the Phase Identification Parameter concept developed in [ 1 ] _ and
 [2 ] _ to determine if a chemical is a solid , liquid , or vapor given the
 appropriate thermodynamic conditions .
 The criteria for liquid is PIP > 1 ; for vapor , PIP < = 1.
 For solids , PIP ( solid ) is defined to be d2P _ dVdT . If it is larger than 0,
 the species is a solid . It is less than 0 for all liquids and gases .
 Parameters
 d2P _ dVdT : float
 Second derivative of ` P ` with respect to both ` V ` and ` T ` , [ Pa * mol / m ^ 3 / K ]
 V : float , optional
 Molar volume at ` T ` and ` P ` , [ m ^ 3 / mol ]
 dP _ dT : float , optional
 Derivative of ` P ` with respect to ` T ` , [ Pa / K ]
 dP _ dV : float , optional
 Derivative of ` P ` with respect to ` V ` , [ Pa * mol / m ^ 3]
 d2P _ dV2 : float , optionsl
 Second derivative of ` P ` with respect to ` V ` , [ Pa * mol ^ 2 / m ^ 6]
 Returns
 phase : str
 Either ' s ' , ' l ' or ' g '
 Notes
 The criteria for being a solid phase is checked first , which only
 requires d2P _ dVdT . All other inputs are optional for this reason .
 However , an exception will be raised if the other inputs become
 needed to determine if a species is a liquid or a gas .
 Examples
 Calculated for hexane from the PR EOS at 299 K and 1 MPa ( liquid ) :
 > > > phase _ identification _ parameter _ phase ( - 20518995218.2 , 0.000130229900874,
 . . . 582169.397484 , - 3.66431747236e + 12 , 4.48067893805e + 17)
 References
 . . [ 1 ] Venkatarathnam , G . , and L . R . Oellrich . " Identification of the Phase
 of a Fluid Using Partial Derivatives of Pressure , Volume , and
 Temperature without Reference to Saturation Properties : Applications in
 Phase Equilibria Calculations . " Fluid Phase Equilibria 301 , no . 2
 ( February 25 , 2011 ) : 225-33 . doi : 10.1016 / j . fluid . 2010.12.001.
 . . [ 2 ] Jayanti , Pranava Chaitanya , and G . Venkatarathnam . " Identification
 of the Phase of a Substance from the Derivatives of Pressure , Volume and
 Temperature , without Prior Knowledge of Saturation Properties : Extension
 to Solid Phase . " Fluid Phase Equilibria 425 ( October 15 , 2016 ) : 269-277.
 doi : 10.1016 / j . fluid . 2016.06.001.'''

implementation:
if d2P_dVdT > 0 :
    return 's'
else :
    PIP = phase_identification_parameter ( V = V , dP_dT = dP_dT , dP_dV = dP_dV , d2P_dV2 = d2P_dV2 , d2P_dVdT = d2P_dVdT )
    return 'l' if PIP > 1 else 'g'


signature:
def speed_of_sound ( V , dP_dV , Cp , Cv , MW = None ) :
    r'''Calculate a real fluid ' s speed of sound . The required derivatives should
 be calculated with an equation of state , and ` Cp ` and ` Cv ` are both the
 real fluid versions . Expression is given in [ 1 ] _ and [ 2 ] _ ; a unit conversion
 is further performed to obtain a result in m / s . If MW is not provided the
 result is returned in units of m * kg ^ 0.5 / s / mol ^ 0.5.
 . . math : :
 w = \ left [ - V ^ 2 \ left ( \ frac { \ partial P } { \ partial V } \ right ) _ T \ frac { C _ p }
 { C _ v } \ right ] ^ { 1/2}
 Parameters
 V : float
 Molar volume of fluid , [ m ^ 3 / mol ]
 dP _ dV : float
 Derivative of ` P ` with respect to ` V ` , [ Pa * mol / m ^ 3]
 Cp : float
 Real fluid heat capacity at constant pressure , [ J / mol / K ]
 Cv : float
 Real fluid heat capacity at constant volume , [ J / mol / K ]
 MW : float , optional
 Molecular weight , [ g / mol ]
 Returns
 w : float
 Speed of sound for a real gas , [ m / s or m * kg ^ 0.5 / s / mol ^ 0.5 or MW missing ]
 Notes
 An alternate expression based on molar density is as follows :
 . . math : :
 w = \ left [ \ left ( \ frac { \ partial P } { \ partial \ rho } \ right ) _ T \ frac { C _ p }
 { C _ v } \ right ] ^ { 1/2}
 The form with the unit conversion performed inside it is as follows :
 . . math : :
 w = \ left [ - V ^ 2 \ frac { 1000 } { MW } \ left ( \ frac { \ partial P } { \ partial V }
 \ right ) _ T \ frac { C _ p } { C _ v } \ right ] ^ { 1/2}
 Examples
 Example from [ 2 ] _ :
 > > > speed _ of _ sound ( V = 0.00229754 , dP _ dV = - 3.5459e + 08 , Cp = 153.235 , Cv = 132.435 , MW = 67.152)
 179.5868138460819
 References
 . . [ 1 ] Gmehling , Jurgen , Barbel Kolbe , Michael Kleiber , and Jurgen Rarey .
 Chemical Thermodynamics for Process Simulation . 1st edition . Weinheim :
 Wiley - VCH , 2012.
 . . [ 2 ] Pratt , R . M . " Thermodynamic Properties Involving Derivatives : Using
 the Peng - Robinson Equation of State . " Chemical Engineering Education 35,
 no . 2 ( March 1 , 2001 ) : 112-115.'''

implementation:
if not MW :
    return ( - V ** 2 * dP_dV * Cp / Cv ) ** 0.5
else :
    return ( - V ** 2 * 1000. / MW * dP_dV * Cp / Cv ) ** 0.5


signature:
def Joule_Thomson ( T , V , Cp , dV_dT = None , beta = None ) :
    r'''Calculate a real fluid ' s Joule Thomson coefficient . The required
 derivative should be calculated with an equation of state , and ` Cp ` is the
 real fluid versions . This can either be calculated with ` dV _ dT ` directly ,
 or with ` beta ` if it is already known .
 . . 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 )
 Parameters
 T : float
 Temperature of fluid , [ K ]
 V : float
 Molar volume of fluid , [ m ^ 3 / mol ]
 Cp : float
 Real fluid heat capacity at constant pressure , [ J / mol / K ]
 dV _ dT : float , optional
 Derivative of ` V ` with respect to ` T ` , [ m ^ 3 / mol / K ]
 beta : float , optional
 Isobaric coefficient of a thermal expansion , [ 1 / K ]
 Returns
 mu _ JT : float
 Joule - Thomson coefficient [ K / Pa ]
 Examples
 Example from [ 2 ] _ :
 > > > Joule _ Thomson ( T = 390 , V = 0.00229754 , Cp = 153.235 , dV _ dT = 1.226396e - 05)
 1.621956080529905e - 05
 References
 . . [ 1 ] Walas , Stanley M . Phase Equilibria in Chemical Engineering .
 Butterworth - Heinemann , 1985.
 . . [ 2 ] Pratt , R . M . " Thermodynamic Properties Involving Derivatives : Using
 the Peng - Robinson Equation of State . " Chemical Engineering Education 35,
 no . 2 ( March 1 , 2001 ) : 112-115.'''

implementation:
if dV_dT :
    return ( T * dV_dT - V ) / Cp
elif beta :
    return V / Cp * ( beta * T - 1. )
else :
    raise Exception ( 'Either dV_dT or beta is needed' )


signature:
def Z_from_virial_density_form ( T , P , * args ) :
    r'''Calculates the compressibility factor of a gas given its temperature ,
 pressure , and molar density - form virial coefficients . Any number of
 coefficients is supported .
 . . math : :
 Z = \ frac { PV } { RT } = 1 + \ frac { B } { V } + \ frac { C } { V ^ 2 } + \ frac { D } { V ^ 3}
 + \ frac { E } { V ^ 4 } \ dots
 Parameters
 T : float
 Temperature , [ K ]
 P : float
 Pressure , [ Pa ]
 B to Z : float , optional
 Virial coefficients , [ various ]
 Returns
 Z : float
 Compressibility factor at T , P , and with given virial coefficients , [ - ]
 Notes
 For use with B or with B and C or with B and C and D , optimized equations
 are used to obtain the compressibility factor directly .
 If more coefficients are provided , uses numpy ' s roots function to solve
 this equation . This takes substantially longer as the solution is
 numerical .
 If no virial coefficients are given , returns 1 , as per the ideal gas law .
 The units of each virial coefficient are as follows , where for B , n = 1 , and
 C , n = 2 , and so on .
 . . math : :
 \ left ( \ frac { \ text { m } ^ 3 } { \ text { mol } } \ right ) ^ n
 Examples
 > > > Z _ from _ virial _ density _ form ( 300 , 122057.233762653 , 1E - 4 , 1E - 5 , 1E - 6 , 1E - 7)
 1.2843496002100001
 References
 . . [ 1 ] Prausnitz , John M . , Rudiger N . Lichtenthaler , and Edmundo Gomes de
 Azevedo . Molecular Thermodynamics of Fluid - Phase Equilibria . 3rd
 edition . Upper Saddle River , N . J : Prentice Hall , 1998.
 . . [ 2 ] Walas , Stanley M . Phase Equilibria in Chemical Engineering .
 Butterworth - Heinemann , 1985.'''


signature:
def Z_from_virial_pressure_form ( P , * args ) :
    r'''Calculates the compressibility factor of a gas given its pressure , and
 pressure - form virial coefficients . Any number of coefficients is supported .
 . . math : :
 Z = \ frac { Pv } { RT } = 1 + B ' P + C ' P ^ 2 + D ' P ^ 3 + E ' P ^ 4 \ dots
 Parameters
 P : float
 Pressure , [ Pa ]
 B to Z : float , optional
 Pressure form Virial coefficients , [ various ]
 Returns
 Z : float
 Compressibility factor at P , and with given virial coefficients , [ - ]
 Notes
 Note that although this function does not require a temperature input , it
 is still dependent on it because the coefficients themselves normally are
 regressed in terms of temperature .
 The use of this form is less common than the density form . Its coefficients
 are normally indicated with the " ' " suffix .
 If no virial coefficients are given , returns 1 , as per the ideal gas law .
 The units of each virial coefficient are as follows , where for B , n = 1 , and
 C , n = 2 , and so on .
 . . math : :
 \ left ( \ frac { 1 } { \ text { Pa } } \ right ) ^ n
 Examples
 > > > Z _ from _ virial _ pressure _ form ( 102919.99946855308 , 4.032286555169439e - 09 , 1.6197059494442215e - 13 , 6.483855042486911e - 19)
 1.00283753944
 References
 . . [ 1 ] Prausnitz , John M . , Rudiger N . Lichtenthaler , and Edmundo Gomes de
 Azevedo . Molecular Thermodynamics of Fluid - Phase Equilibria . 3rd
 edition . Upper Saddle River , N . J : Prentice Hall , 1998.
 . . [ 2 ] Walas , Stanley M . Phase Equilibria in Chemical Engineering .
 Butterworth - Heinemann , 1985.'''

implementation: return 1 + P * sum ( [ coeff * P ** i for i , coeff in enumerate ( args ) ] )


signature:
def zs_to_ws ( zs , MWs ) :
    r'''Converts a list of mole fractions to mass fractions . Requires molecular
 weights for all species .
 . . math : :
 w _ i = \ frac { z _ i MW _ i } { MW _ { avg } }
 MW _ { avg } = \ sum _ i z _ i MW _ i
 Parameters
 zs : iterable
 Mole fractions [ - ]
 MWs : iterable
 Molecular weights [ g / mol ]
 Returns
 ws : iterable
 Mass fractions [ - ]
 Notes
 Does not check that the sums add to one . Does not check that inputs are of
 the same length .
 Examples
 > > > zs _ to _ ws ( [ 0.5 , 0.5 ] , [ 10 , 20 ] )
 [0.33333 , 0.66666]'''

implementation:
Mavg = sum ( zi * MWi for zi , MWi in zip ( zs , MWs ) )
ws = [ zi * MWi / Mavg for zi , MWi in zip ( zs , MWs ) ]
return ws


signature:
def ws_to_zs ( ws , MWs ) :
    r'''Converts a list of mass fractions to mole fractions . Requires molecular
 weights for all species .
 . . math : :
 z _ i = \ frac { \ frac { w _ i } { MW _ i } } { \ sum _ i \ frac { w _ i } { MW _ i } }
 Parameters
 ws : iterable
 Mass fractions [ - ]
 MWs : iterable
 Molecular weights [ g / mol ]
 Returns
 zs : iterable
 Mole fractions [ - ]
 Notes
 Does not check that the sums add to one . Does not check that inputs are of
 the same length .
 Examples
 > > > ws _ to _ zs ( [ 0.33333 , 0.66666 ] , [ 10 , 20 ] )
 [0.5 , 0.5]'''

implementation:
tot = sum ( w / MW for w , MW in zip ( ws , MWs ) )
zs = [ w / MW / tot for w , MW in zip ( ws , MWs ) ]
return zs


signature:
def zs_to_Vfs ( zs , Vms ) :
    r'''Converts a list of mole fractions to volume fractions . Requires molar
 volumes for all species .
 . . math : :
 \ text { Vf } _ i = \ frac { z _ i V _ { m , i } } { \ sum _ i z _ i V _ { m , i } }
 Parameters
 zs : iterable
 Mole fractions [ - ]
 VMs : iterable
 Molar volumes of species [ m ^ 3 / mol ]
 Returns
 Vfs : list
 Molar volume fractions [ - ]
 Notes
 Does not check that the sums add to one . Does not check that inputs are of
 the same length .
 Molar volumes are specified in terms of pure components only . Function
 works with any phase .
 Examples
 Acetone and benzene example
 > > > zs _ to _ Vfs ( [ 0.637 , 0.363 ] , [ 8.0234e - 05 , 9.543e - 05 ] )
 [0.5960229712956298 , 0.4039770287043703]'''

implementation:
vol_is = [ zi * Vmi for zi , Vmi in zip ( zs , Vms ) ]
tot = sum ( vol_is )
return [ vol_i / tot for vol_i in vol_is ]


signature:
def Vfs_to_zs ( Vfs , Vms ) :
    r'''Converts a list of mass fractions to mole fractions . Requires molecular
 weights for all species .
 . . math : :
 z _ i = \ frac { \ frac { \ text { Vf } _ i } { V _ { m , i } } } { \ sum _ i
 \ frac { \ text { Vf } _ i } { V _ { m , i } } }
 Parameters
 Vfs : iterable
 Molar volume fractions [ - ]
 VMs : iterable
 Molar volumes of species [ m ^ 3 / mol ]
 Returns
 zs : list
 Mole fractions [ - ]
 Notes
 Does not check that the sums add to one . Does not check that inputs are of
 the same length .
 Molar volumes are specified in terms of pure components only . Function
 works with any phase .
 Examples
 Acetone and benzene example
 > > > Vfs _ to _ zs ( [ 0.596 , 0.404 ] , [ 8.0234e - 05 , 9.543e - 05 ] )
 [0.6369779395901142 , 0.3630220604098858]'''

implementation:
mols_i = [ Vfi / Vmi for Vfi , Vmi in zip ( Vfs , Vms ) ]
mols = sum ( mols_i )
return [ mol_i / mols for mol_i in mols_i ]


signature:
def none_and_length_check ( all_inputs , length = None ) :
    r'''Checks inputs for suitability of use by a mixing rule which requires
 all inputs to be of the same length and non - None . A number of variations
 were attempted for this function ; this was found to be the quickest .
 Parameters
 all _ inputs : array - like of array - like
 list of all the lists of inputs , [ - ]
 length : int , optional
 Length of the desired inputs , [ - ]
 Returns
 False / True : bool
 Returns True only if all inputs are the same length ( or length ` length ` )
 and none of the inputs contain None [ - ]
 Notes
 Does not check for nan values .
 Examples
 > > > none _ and _ length _ check ( ( [ 1 , 1 ] , [ 1 , 1 ] , [ 1 , 30 ] , [ 10,0 ] ) , length = 2)
 True'''

implementation:
if not length :
    length = len ( all_inputs [ 0 ] )
for things in all_inputs :
    if None in things or len ( things ) != length :
        return False
return True


signature:
def allclose_variable ( a , b , limits , rtols = None , atols = None ) :
    '''Returns True if two arrays are element - wise equal within several
 different tolerances . Tolerance values are always positive , usually
 very small . Based on numpy ' s allclose function .
 Only atols or rtols needs to be specified ; both are used if given .
 Parameters
 a , b : array _ like
 Input arrays to compare .
 limits : array _ like
 Fractions of elements allowed to not match to within each tolerance .
 rtols : array _ like
 The relative tolerance parameters .
 atols : float
 The absolute tolerance parameters .
 Returns
 allclose : bool
 Returns True if the two arrays are equal within the given
 tolerances ; False otherwise .
 Examples
 10 random similar variables , all of them matching to within 1E - 5 , allowing
 up to half to match up to 1E - 6.
 > > > x = [ 2.7244322249597719e - 08 , 3.0105683900110473e - 10 , 2.7244124924802327e - 08 , 3.0105259397637556e - 10 , 2.7243929226310193e - 08 , 3.0104990272770901e - 10 , 2.7243666849384451e - 08 , 3.0104101821236015e - 10 , 2.7243433745917367e - 08 , 3.0103707421519949e - 10]
 > > > y = [ 2.7244328304561904e - 08 , 3.0105753470546008e - 10 , 2.724412872417824e - 08 , 3.0105303055834564e - 10 , 2.7243914341030203e - 08 , 3.0104819238021998e - 10 , 2.7243684057561379e - 08 , 3.0104299541023674e - 10 , 2.7243436694839306e - 08 , 3.010374130526363e - 10]
 > > > allclose _ variable ( x , y , limits = [ . 0 , . 5 ] , rtols = [ 1E - 5 , 1E - 6 ] )
 True'''

implementation:
l = float ( len ( a ) )
if rtols is None and atols is None :
    raise Exception ( 'Either absolute errors or relative errors must be supplied.' )
elif rtols is None :
    rtols = [ 0 for i in atols ]
elif atols is None :
    atols = [ 0 for i in rtols ]
for atol , rtol , lim in zip ( atols , rtols , limits ) :
    matches = np . count_nonzero ( np . isclose ( a , b , rtol = rtol , atol = atol ) )
    if 1 - matches / l > lim :
        return False
return True


signature:
def polylog2 ( x ) :
    r'''Simple function to calculate PolyLog ( 2 , x ) from ranges 0 < = x < = 1,
 with relative error guaranteed to be < 1E - 7 from 0 to 0.99999 . This
 is a Pade approximation , with three coefficient sets with splits at 0.7
 and 0.99 . An exception is raised if x is under 0 or above 1.
 Parameters
 x : float
 Value to evaluate PolyLog ( 2 , x ) T
 Returns
 y : float
 Evaluated result
 Notes
 Efficient ( 2-4 microseconds ) . No implementation of this function exists in
 SciPy . Derived with mpmath ' s pade approximation .
 Required for the entropy integral of
 : obj : ` thermo . heat _ capacity . Zabransky _ quasi _ polynomial ` .
 Examples
 > > > polylog2(0.5)
 0.5822405264516294'''


signature:
def mixing_simple ( fracs , props ) :
    r'''Simple function calculates a property based on weighted averages of
 properties . Weights could be mole fractions , volume fractions , mass
 fractions , or anything else .
 . . math : :
 y = \ sum _ i \ text { frac } _ i \ cdot \ text { prop } _ i
 Parameters
 fracs : array - like
 Fractions of a mixture
 props : array - like
 Properties
 Returns
 prop : value
 Calculated property
 Notes
 Returns None if any fractions or properties are missing or are not of the
 same length .
 Examples
 > > > mixing _ simple ( [ 0.1 , 0.9 ] , [ 0.01 , 0.02 ] )
 0.019000003'''

implementation:
if not none_and_length_check ( [ fracs , props ] ) :
    return None
result = sum ( frac * prop for frac , prop in zip ( fracs , props ) )
return result


signature:
def mixing_logarithmic ( fracs , props ) :
    r'''Simple function calculates a property based on weighted averages of
 logarithmic properties .
 . . math : :
 y = \ sum _ i \ text { frac } _ i \ cdot \ log ( \ text { prop } _ i )
 Parameters
 fracs : array - like
 Fractions of a mixture
 props : array - like
 Properties
 Returns
 prop : value
 Calculated property
 Notes
 Does not work on negative values .
 Returns None if any fractions or properties are missing or are not of the
 same length .
 Examples
 > > > mixing _ logarithmic ( [ 0.1 , 0.9 ] , [ 0.01 , 0.02 ] )
 0.01866065983073615'''

implementation:
if not none_and_length_check ( [ fracs , props ] ) :
    return None
return exp ( sum ( frac * log ( prop ) for frac , prop in zip ( fracs , props ) ) )


signature:
def phase_select_property ( phase = None , s = None , l = None , g = None , V_over_F = None ) :
    r'''Determines which phase ' s property should be set as a default , given
 the phase a chemical is , and the property values of various phases . For the
 case of liquid - gas phase , returns None . If the property is not available
 for the current phase , or if the current phase is not known , returns None .
 Parameters
 phase : str
 One of { ' s ' , ' l ' , ' g ' , ' two - phase ' }
 s : float
 Solid - phase property
 l : float
 Liquid - phase property
 g : float
 Gas - phase property
 V _ over _ F : float
 Vapor phase fraction
 Returns
 prop : float
 The selected / calculated property for the relevant phase
 Notes
 Could calculate mole - fraction weighted properties for the two phase regime .
 Could also implement equilibria with solid phases .
 Examples
 > > > phase _ select _ property ( phase = ' g ' , l = 1560.14 , g = 3312 . )
 3312.0'''

implementation:
if phase == 's' :
    return s
elif phase == 'l' :
    return l
elif phase == 'g' :
    return g
elif phase == 'two-phase' :
    return None
    # TODO : all two - phase properties ?
elif phase is None :
    return None
else :
    raise Exception ( 'Property not recognized' )


signature:
def set_user_methods ( self , user_methods , forced = False ) :
    r'''Method used to select certain property methods as having a higher
 priority than were set by default . If ` forced ` is true , then methods
 which were not specified are excluded from consideration .
 As a side effect , ` method ` is removed to ensure than the new methods
 will be used in calculations afterwards .
 An exception is raised if any of the methods specified aren ' t available
 for the chemical . An exception is raised if no methods are provided .
 Parameters
 user _ methods : str or list
 Methods by name to be considered or prefered
 forced : bool , optional
 If True , only the user specified methods will ever be considered ;
 if False other methods will be considered if no user methods
 suceed'''

implementation:
# Accept either a string or a list of methods , and whether
# or not to only consider the false methods
if isinstance ( user_methods , str ) :
    user_methods = [ user_methods ]
# The user ' s order matters and is retained for use by select _ valid _ methods
self . user_methods = user_methods
self . forced = forced
# Validate that the user ' s specified methods are actual methods
if set ( self . user_methods ) . difference ( self . all_methods ) :
    raise Exception ( "One of the given methods is not available for this chemical" )
if not self . user_methods and self . forced :
    raise Exception ( 'Only user specified methods are considered when forced is True, but no methods were provided' )
# Remove previously selected methods
self . method = None
self . sorted_valid_methods = [ ]
self . T_cached = None


signature:
def select_valid_methods ( self , T ) :
    r'''Method to obtain a sorted list of methods which are valid at ` T `
 according to ` test _ method _ validity ` . Considers either only user methods
 if forced is True , or all methods . User methods are first tested
 according to their listed order , and unless forced is True , then all
 methods are tested and sorted by their order in ` ranked _ methods ` .
 Parameters
 T : float
 Temperature at which to test methods , [ K ]
 Returns
 sorted _ valid _ methods : list
 Sorted lists of methods valid at T according to
 ` test _ method _ validity `'''

implementation:
# Consider either only the user ' s methods or all methods
# Tabular data will be in both when inserted
if self . forced :
    considered_methods = list ( self . user_methods )
else :
    considered_methods = list ( self . all_methods )
# User methods ( incl . tabular data ) ; add back later , after ranking the rest
if self . user_methods :
    [ considered_methods . remove ( i ) for i in self . user_methods ]
# Index the rest of the methods by ranked _ methods , and add them to a list , sorted _ methods
preferences = sorted ( [ self . ranked_methods . index ( i ) for i in considered_methods ] )
sorted_methods = [ self . ranked_methods [ i ] for i in preferences ]
# Add back the user ' s methods to the top , in order .
if self . user_methods :
    [ sorted_methods . insert ( 0 , i ) for i in reversed ( self . user_methods ) ]
sorted_valid_methods = [ ]
for method in sorted_methods :
    if self . test_method_validity ( T , method ) :
        sorted_valid_methods . append ( method )
return sorted_valid_methods


signature:
def T_dependent_property ( self , T ) :
    r'''Method to calculate the property with sanity checking and without
 specifying a specific method . ` select _ valid _ methods ` is used to obtain
 a sorted list of methods to try . Methods are then tried in order until
 one succeeds . The methods are allowed to fail , and their results are
 checked with ` test _ property _ validity ` . On success , the used method
 is stored in the variable ` method ` .
 If ` method ` is set , this method is first checked for validity with
 ` test _ method _ validity ` for the specified temperature , and if it is
 valid , it is then used to calculate the property . The result is checked
 for validity , and returned if it is valid . If either of the checks fail ,
 the function retrieves a full list of valid methods with
 ` select _ valid _ methods ` and attempts them as described above .
 If no methods are found which succeed , returns None .
 Parameters
 T : float
 Temperature at which to calculate the property , [ K ]
 Returns
 prop : float
 Calculated property , [ ` units ` ]'''

implementation:
# Optimistic track , with the already set method
if self . method : # retest within range
    if self . test_method_validity ( T , self . method ) :
        try :
            prop = self . calculate ( T , self . method )
            if self . test_property_validity ( prop ) :
                return prop
        except : # pragma : no cover
            pass
# get valid methods at T , and try them until one yields a valid
# property ; store the method and return the answer
self . sorted_valid_methods = self . select_valid_methods ( T )
for method in self . sorted_valid_methods :
    try :
        prop = self . calculate ( T , method )
        if self . test_property_validity ( prop ) :
            self . method = method
            return prop
    except : # pragma : no cover
        pass
# Function returns None if it does not work .
return None


signature:
def plot_T_dependent_property ( self , Tmin = None , Tmax = None , methods = [ ] , pts = 50 , only_valid = True , order = 0 ) : # pragma : no cover
    r'''Method to create a plot of the property vs temperature according to
 either a specified list of methods , or user methods ( if set ) , or all
 methods . User - selectable number of points , and temperature range . If
 only _ valid is set , ` test _ method _ validity ` will be used to check if each
 temperature in the specified range is valid , and
 ` test _ property _ validity ` will be used to test the answer , and the
 method is allowed to fail ; only the valid points will be plotted .
 Otherwise , the result will be calculated and displayed as - is . This will
 not suceed if the method fails .
 Parameters
 Tmin : float
 Minimum temperature , to begin calculating the property , [ K ]
 Tmax : float
 Maximum temperature , to stop calculating the property , [ K ]
 methods : list , optional
 List of methods to consider
 pts : int , optional
 A list of points to calculate the property at ; if Tmin to Tmax
 covers a wide range of method validities , only a few points may end
 up calculated for a given method so this may need to be large
 only _ valid : bool
 If True , only plot successful methods and calculated properties ,
 and handle errors ; if False , attempt calculation without any
 checking and use methods outside their bounds'''

implementation:
# This function cannot be tested
if not has_matplotlib :
    raise Exception ( 'Optional dependency matplotlib is required for plotting' )
if Tmin is None :
    if self . Tmin is not None :
        Tmin = self . Tmin
    else :
        raise Exception ( 'Minimum temperature could not be auto-detected; please provide it' )
if Tmax is None :
    if self . Tmax is not None :
        Tmax = self . Tmax
    else :
        raise Exception ( 'Maximum temperature could not be auto-detected; please provide it' )
if not methods :
    if self . user_methods :
        methods = self . user_methods
    else :
        methods = self . all_methods
Ts = np . linspace ( Tmin , Tmax , pts )
if order == 0 :
    for method in methods :
        if only_valid :
            properties , Ts2 = [ ] , [ ]
            for T in Ts :
                if self . test_method_validity ( T , method ) :
                    try :
                        p = self . calculate ( T = T , method = method )
                        if self . test_property_validity ( p ) :
                            properties . append ( p )
                            Ts2 . append ( T )
                    except :
                        pass
            plt . semilogy ( Ts2 , properties , label = method )
        else :
            properties = [ self . calculate ( T = T , method = method ) for T in Ts ]
            plt . semilogy ( Ts , properties , label = method )
    plt . ylabel ( self . name + ', ' + self . units )
    plt . title ( self . name + ' of ' + self . CASRN )
elif order > 0 :
    for method in methods :
        if only_valid :
            properties , Ts2 = [ ] , [ ]
            for T in Ts :
                if self . test_method_validity ( T , method ) :
                    try :
                        p = self . calculate_derivative ( T = T , method = method , order = order )
                        properties . append ( p )
                        Ts2 . append ( T )
                    except :
                        pass
            plt . semilogy ( Ts2 , properties , label = method )
        else :
            properties = [ self . calculate_derivative ( T = T , method = method , order = order ) for T in Ts ]
            plt . semilogy ( Ts , properties , label = method )
    plt . ylabel ( self . name + ', ' + self . units + '/K^%d derivative of order %d' % ( order , order ) )
    plt . title ( self . name + ' derivative of order %d' % order + ' of ' + self . CASRN )
plt . legend ( loc = 'best' )
plt . xlabel ( 'Temperature, K' )
plt . show ( )


signature:
def interpolate ( self , T , name ) :
    r'''Method to perform interpolation on a given tabular data set
 previously added via : obj : ` set _ tabular _ data ` . This method will create the
 interpolators the first time it is used on a property set , and store
 them for quick future use .
 Interpolation is cubic - spline based if 5 or more points are available ,
 and linearly interpolated if not . Extrapolation is always performed
 linearly . This function uses the transforms ` interpolation _ T ` ,
 ` interpolation _ property ` , and ` interpolation _ property _ inv ` if set . If
 any of these are changed after the interpolators were first created ,
 new interpolators are created with the new transforms .
 All interpolation is performed via the ` interp1d ` function .
 Parameters
 T : float
 Temperature at which to interpolate the property , [ K ]
 name : str
 The name assigned to the tabular data set
 Returns
 prop : float
 Calculated property , [ ` units ` ]'''

implementation:
key = ( name , self . interpolation_T , self . interpolation_property , self . interpolation_property_inv )
# If the interpolator and extrapolator has already been created , load it
# if isinstance ( self . tabular _ data _ interpolators , dict ) and key in self . tabular _ data _ interpolators :
# extrapolator , spline = self . tabular _ data _ interpolators [ key ]
if key in self . tabular_data_interpolators :
    extrapolator , spline = self . tabular_data_interpolators [ key ]
else :
    Ts , properties = self . tabular_data [ name ]
    if self . interpolation_T : # Transform ths Ts with interpolation _ T if set
        Ts2 = [ self . interpolation_T ( T2 ) for T2 in Ts ]
    else :
        Ts2 = Ts
    if self . interpolation_property : # Transform ths props with interpolation _ property if set
        properties2 = [ self . interpolation_property ( p ) for p in properties ]
    else :
        properties2 = properties
    # Only allow linear extrapolation , but with whatever transforms are specified
    extrapolator = interp1d ( Ts2 , properties2 , fill_value = 'extrapolate' )
    # If more than 5 property points , create a spline interpolation
    if len ( properties ) >= 5 :
        spline = interp1d ( Ts2 , properties2 , kind = 'cubic' )
    else :
        spline = None
    # if isinstance ( self . tabular _ data _ interpolators , dict ) :
    # self . tabular _ data _ interpolators [ key ] = ( extrapolator , spline )
    # else :
    # self . tabular _ data _ interpolators = { key : ( extrapolator , spline ) }
    self . tabular_data_interpolators [ key ] = ( extrapolator , spline )
# Load the stores values , tor checking which interpolation strategy to
# use .
Ts , properties = self . tabular_data [ name ]
if T < Ts [ 0 ] or T > Ts [ - 1 ] or not spline :
    tool = extrapolator
else :
    tool = spline
if self . interpolation_T :
    T = self . interpolation_T ( T )
prop = tool ( T )
# either spline , or linear interpolation
if self . interpolation_property :
    prop = self . interpolation_property_inv ( prop )
return float ( prop )


signature:
def set_tabular_data ( self , Ts , properties , name = None , check_properties = True ) :
    r'''Method to set tabular data to be used for interpolation .
 Ts must be in increasing order . If no name is given , data will be
 assigned the name ' Tabular data series # x ' , where x is the number of
 previously added tabular data series . The name is added to all
 methods and iserted at the start of user methods ,
 Parameters
 Ts : array - like
 Increasing array of temperatures at which properties are specified , [ K ]
 properties : array - like
 List of properties at Ts , [ ` units ` ]
 name : str , optional
 Name assigned to the data
 check _ properties : bool
 If True , the properties will be checked for validity with
 ` test _ property _ validity ` and raise an exception if any are not
 valid'''

implementation:
# Ts must be in increasing order .
if check_properties :
    for p in properties :
        if not self . test_property_validity ( p ) :
            raise Exception ( 'One of the properties specified are not feasible' )
if not all ( b > a for a , b in zip ( Ts , Ts [ 1 : ] ) ) :
    raise Exception ( 'Temperatures are not sorted in increasing order' )
if name is None :
    name = 'Tabular data series #' + str ( len ( self . tabular_data ) )
    # Will overwrite a poorly named series
self . tabular_data [ name ] = ( Ts , properties )
# TODO set Tmin and Tmax if not set
self . method = None
self . user_methods . insert ( 0 , name )
self . all_methods . add ( name )
self . set_user_methods ( user_methods = self . user_methods , forced = self . forced )


signature:
def solve_prop ( self , goal , reset_method = True ) :
    r'''Method to solve for the temperature at which a property is at a
 specified value . ` T _ dependent _ property ` is used to calculate the value
 of the property as a function of temperature ; if ` reset _ method ` is True ,
 the best method is used at each temperature as the solver seeks a
 solution . This slows the solution moderately .
 Checks the given property value with ` test _ property _ validity ` first
 and raises an exception if it is not valid . Requires that Tmin and
 Tmax have been set to know what range to search within .
 Search is performed with the brenth solver from SciPy .
 Parameters
 goal : float
 Propoerty value desired , [ ` units ` ]
 reset _ method : bool
 Whether or not to reset the method as the solver searches
 Returns
 T : float
 Temperature at which the property is the specified value [ K ]'''

implementation:
if self . Tmin is None or self . Tmax is None :
    raise Exception ( 'Both a minimum and a maximum value are not present indicating there is not enough data for temperature dependency.' )
if not self . test_property_validity ( goal ) :
    raise Exception ( 'Input property is not considered plausible; no method would calculate it.' )
def error ( T ) :
    if reset_method :
        self . method = None
    return self . T_dependent_property ( T ) - goal
try :
    return brenth ( error , self . Tmin , self . Tmax )
except ValueError :
    raise Exception ( 'To within the implemented temperature range, it is not possible to calculate the desired value.' )


signature:
def calculate_derivative ( self , T , method , order = 1 ) :
    r'''Method to calculate a derivative of a property with respect to
 temperature , of a given order using a specified method . Uses SciPy ' s
 derivative function , with a delta of 1E - 6 K and a number of points
 equal to 2 * order + 1.
 This method can be overwritten by subclasses who may perfer to add
 analytical methods for some or all methods as this is much faster .
 If the calculation does not succeed , returns the actual error
 encountered .
 Parameters
 T : float
 Temperature at which to calculate the derivative , [ K ]
 method : str
 Method for which to find the derivative
 order : int
 Order of the derivative , > = 1
 Returns
 derivative : float
 Calculated derivative property , [ ` units / K ^ order ` ]'''

implementation: return derivative ( self . calculate , T , dx = 1e-6 , args = [ method ] , n = order , order = 1 + order * 2 )


signature:
def T_dependent_property_derivative ( self , T , order = 1 ) :
    r'''Method to obtain a derivative of a property with respect to
 temperature , of a given order . Methods found valid by
 ` select _ valid _ methods ` are attempted until a method succeeds . If no
 methods are valid and succeed , None is returned .
 Calls ` calculate _ derivative ` internally to perform the actual
 calculation .
 . . math : :
 \ text { derivative } = \ frac { d ( \ text { property } ) } { d T }
 Parameters
 T : float
 Temperature at which to calculate the derivative , [ K ]
 order : int
 Order of the derivative , > = 1
 Returns
 derivative : float
 Calculated derivative property , [ ` units / K ^ order ` ]'''

implementation:
if self . method : # retest within range
    if self . test_method_validity ( T , self . method ) :
        try :
            return self . calculate_derivative ( T , self . method , order )
        except : # pragma : no cover
            pass
sorted_valid_methods = self . select_valid_methods ( T )
for method in sorted_valid_methods :
    try :
        return self . calculate_derivative ( T , method , order )
    except :
        pass
return None


signature:
def calculate_integral ( self , T1 , T2 , method ) :
    r'''Method to calculate the integral of a property with respect to
 temperature , using a specified method . Uses SciPy ' s ` quad ` function
 to perform the integral , with no options .
 This method can be overwritten by subclasses who may perfer to add
 analytical methods for some or all methods as this is much faster .
 If the calculation does not succeed , returns the actual error
 encountered .
 Parameters
 T1 : float
 Lower limit of integration , [ K ]
 T2 : float
 Upper limit of integration , [ K ]
 method : str
 Method for which to find the integral
 Returns
 integral : float
 Calculated integral of the property over the given range ,
 [ ` units * K ` ]'''

implementation: return float ( quad ( self . calculate , T1 , T2 , args = ( method ) ) [ 0 ] )


signature:
def T_dependent_property_integral ( self , T1 , T2 ) :
    r'''Method to calculate the integral of a property with respect to
 temperature , using a specified method . Methods found valid by
 ` select _ valid _ methods ` are attempted until a method succeeds . If no
 methods are valid and succeed , None is returned .
 Calls ` calculate _ integral ` internally to perform the actual
 calculation .
 . . math : :
 \ text { integral } = \ int _ { T _ 1 } ^ { T _ 2 } \ text { property } \ ; dT
 Parameters
 T1 : float
 Lower limit of integration , [ K ]
 T2 : float
 Upper limit of integration , [ K ]
 method : str
 Method for which to find the integral
 Returns
 integral : float
 Calculated integral of the property over the given range ,
 [ ` units * K ` ]'''

implementation:
Tavg = 0.5 * ( T1 + T2 )
if self . method : # retest within range
    if self . test_method_validity ( Tavg , self . method ) :
        try :
            return self . calculate_integral ( T1 , T2 , self . method )
        except : # pragma : no cover
            pass
sorted_valid_methods = self . select_valid_methods ( Tavg )
for method in sorted_valid_methods :
    try :
        return self . calculate_integral ( T1 , T2 , method )
    except :
        pass
return None


signature:
def calculate_integral_over_T ( self , T1 , T2 , method ) :
    r'''Method to calculate the integral of a property over temperature
 with respect to temperature , using a specified method . Uses SciPy ' s
 ` quad ` function to perform the integral , with no options .
 This method can be overwritten by subclasses who may perfer to add
 analytical methods for some or all methods as this is much faster .
 If the calculation does not succeed , returns the actual error
 encountered .
 Parameters
 T1 : float
 Lower limit of integration , [ K ]
 T2 : float
 Upper limit of integration , [ K ]
 method : str
 Method for which to find the integral
 Returns
 integral : float
 Calculated integral of the property over the given range ,
 [ ` units ` ]'''

implementation: return float ( quad ( lambda T : self . calculate ( T , method ) / T , T1 , T2 ) [ 0 ] )


signature:
def T_dependent_property_integral_over_T ( self , T1 , T2 ) :
    r'''Method to calculate the integral of a property over temperature
 with respect to temperature , using a specified method . Methods found
 valid by ` select _ valid _ methods ` are attempted until a method succeeds .
 If no methods are valid and succeed , None is returned .
 Calls ` calculate _ integral _ over _ T ` internally to perform the actual
 calculation .
 . . math : :
 \ text { integral } = \ int _ { T _ 1 } ^ { T _ 2 } \ frac { \ text { property } } { T } \ ; dT
 Parameters
 T1 : float
 Lower limit of integration , [ K ]
 T2 : float
 Upper limit of integration , [ K ]
 method : str
 Method for which to find the integral
 Returns
 integral : float
 Calculated integral of the property over the given range ,
 [ ` units ` ]'''

implementation:
Tavg = 0.5 * ( T1 + T2 )
if self . method : # retest within range
    if self . test_method_validity ( Tavg , self . method ) :
        try :
            return self . calculate_integral_over_T ( T1 , T2 , self . method )
        except : # pragma : no cover
            pass
sorted_valid_methods = self . select_valid_methods ( Tavg )
for method in sorted_valid_methods :
    try :
        return self . calculate_integral_over_T ( T1 , T2 , method )
    except :
        pass
return None


signature:
def load_all_methods ( self ) :
    r'''Method to load all data , and set all _ methods based on the available
 data and properties . Demo function for testing only ; must be
 implemented according to the methods available for each individual
 method .'''

implementation:
methods = [ ]
Tmins , Tmaxs = [ ] , [ ]
if self . CASRN in [ '7732-18-5' , '67-56-1' , '64-17-5' ] :
    methods . append ( TEST_METHOD_1 )
    self . TEST_METHOD_1_Tmin = 200.
    self . TEST_METHOD_1_Tmax = 350
    self . TEST_METHOD_1_coeffs = [ 1 , .002 ]
    Tmins . append ( self . TEST_METHOD_1_Tmin ) ;
    Tmaxs . append ( self . TEST_METHOD_1_Tmax )
if self . CASRN in [ '67-56-1' ] :
    methods . append ( TEST_METHOD_2 )
    self . TEST_METHOD_2_Tmin = 300.
    self . TEST_METHOD_2_Tmax = 400
    self . TEST_METHOD_2_coeffs = [ 1 , .003 ]
    Tmins . append ( self . TEST_METHOD_2_Tmin ) ;
    Tmaxs . append ( self . TEST_METHOD_2_Tmax )
self . all_methods = set ( methods )
if Tmins and Tmaxs :
    self . Tmin = min ( Tmins )
    self . Tmax = max ( Tmaxs )


signature:
def calculate ( self , T , method ) :
    r'''Method to calculate a property with a specified method , with no
 validity checking or error handling . Demo function for testing only ;
 must be implemented according to the methods available for each
 individual method . Include the interpolation call here .
 Parameters
 T : float
 Temperature at which to calculate the property , [ K ]
 method : str
 Method name to use
 Returns
 prop : float
 Calculated property , [ ` units ` ]'''

implementation:
if method == TEST_METHOD_1 :
    prop = self . TEST_METHOD_1_coeffs [ 0 ] + self . TEST_METHOD_1_coeffs [ 1 ] * T
elif method == TEST_METHOD_2 :
    prop = self . TEST_METHOD_2_coeffs [ 0 ] + self . TEST_METHOD_2_coeffs [ 1 ] * T
elif method in self . tabular_data :
    prop = self . interpolate ( T , method )
return prop


signature:
def set_user_methods_P ( self , user_methods_P , forced_P = False ) :
    r'''Method to set the pressure - dependent property methods desired for
 consideration by the user . Can be used to exclude certain methods which
 might have unacceptable accuracy .
 As a side effect , the previously selected method is removed when
 this method is called to ensure user methods are tried in the desired
 order .
 Parameters
 user _ methods _ P : str or list
 Methods by name to be considered or preferred for pressure effect .
 forced : bool , optional
 If True , only the user specified methods will ever be considered ;
 if False other methods will be considered if no user methods
 suceed .'''

implementation:
# Accept either a string or a list of methods , and whether
# or not to only consider the false methods
if isinstance ( user_methods_P , str ) :
    user_methods_P = [ user_methods_P ]
# The user ' s order matters and is retained for use by select _ valid _ methods
self . user_methods_P = user_methods_P
self . forced_P = forced_P
# Validate that the user ' s specified methods are actual methods
if set ( self . user_methods_P ) . difference ( self . all_methods_P ) :
    raise Exception ( "One of the given methods is not available for this chemical" )
if not self . user_methods_P and self . forced :
    raise Exception ( 'Only user specified methods are considered when forced is True, but no methods were provided' )
# Remove previously selected methods
self . method_P = None
self . sorted_valid_methods_P = [ ]
self . TP_cached = None


signature:
def select_valid_methods_P ( self , T , P ) :
    r'''Method to obtain a sorted list methods which are valid at ` T `
 according to ` test _ method _ validity ` . Considers either only user methods
 if forced is True , or all methods . User methods are first tested
 according to their listed order , and unless forced is True , then all
 methods are tested and sorted by their order in ` ranked _ methods ` .
 Parameters
 T : float
 Temperature at which to test methods , [ K ]
 P : float
 Pressure at which to test methods , [ Pa ]
 Returns
 sorted _ valid _ methods _ P : list
 Sorted lists of methods valid at T and P according to
 ` test _ method _ validity `'''

implementation:
# Same as select _ valid _ methods but with _ P added to variables
if self . forced_P :
    considered_methods = list ( self . user_methods_P )
else :
    considered_methods = list ( self . all_methods_P )
if self . user_methods_P :
    [ considered_methods . remove ( i ) for i in self . user_methods_P ]
preferences = sorted ( [ self . ranked_methods_P . index ( i ) for i in considered_methods ] )
sorted_methods = [ self . ranked_methods_P [ i ] for i in preferences ]
if self . user_methods_P :
    [ sorted_methods . insert ( 0 , i ) for i in reversed ( self . user_methods_P ) ]
sorted_valid_methods_P = [ ]
for method in sorted_methods :
    if self . test_method_validity_P ( T , P , method ) :
        sorted_valid_methods_P . append ( method )
return sorted_valid_methods_P


signature:
def TP_dependent_property ( self , T , P ) :
    r'''Method to calculate the property with sanity checking and without
 specifying a specific method . ` select _ valid _ methods _ P ` is used to obtain
 a sorted list of methods to try . Methods are then tried in order until
 one succeeds . The methods are allowed to fail , and their results are
 checked with ` test _ property _ validity ` . On success , the used method
 is stored in the variable ` method _ P ` .
 If ` method _ P ` is set , this method is first checked for validity with
 ` test _ method _ validity _ P ` for the specified temperature , and if it is
 valid , it is then used to calculate the property . The result is checked
 for validity , and returned if it is valid . If either of the checks fail ,
 the function retrieves a full list of valid methods with
 ` select _ valid _ methods _ P ` and attempts them as described above .
 If no methods are found which succeed , returns None .
 Parameters
 T : float
 Temperature at which to calculate the property , [ K ]
 P : float
 Pressure at which to calculate the property , [ Pa ]
 Returns
 prop : float
 Calculated property , [ ` units ` ]'''

implementation:
# Optimistic track , with the already set method
if self . method_P : # retest within range
    if self . test_method_validity_P ( T , P , self . method_P ) :
        try :
            prop = self . calculate_P ( T , P , self . method_P )
            if self . test_property_validity ( prop ) :
                return prop
        except : # pragma : no cover
            pass
# get valid methods at T , and try them until one yields a valid
# property ; store the method _ P and return the answer
self . sorted_valid_methods_P = self . select_valid_methods_P ( T , P )
for method_P in self . sorted_valid_methods_P :
    try :
        prop = self . calculate_P ( T , P , method_P )
        if self . test_property_validity ( prop ) :
            self . method_P = method_P
            return prop
    except : # pragma : no cover
        pass
# Function returns None if it does not work .
return None


signature:
def set_tabular_data_P ( self , Ts , Ps , properties , name = None , check_properties = True ) :
    r'''Method to set tabular data to be used for interpolation .
 Ts and Psmust be in increasing order . If no name is given , data will be
 assigned the name ' Tabular data series # x ' , where x is the number of
 previously added tabular data series . The name is added to all
 methods and is inserted at the start of user methods ,
 Parameters
 Ts : array - like
 Increasing array of temperatures at which properties are specified , [ K ]
 Ps : array - like
 Increasing array of pressures at which properties are specified , [ Pa ]
 properties : array - like
 List of properties at Ts , [ ` units ` ]
 name : str , optional
 Name assigned to the data
 check _ properties : bool
 If True , the properties will be checked for validity with
 ` test _ property _ validity ` and raise an exception if any are not
 valid'''

implementation:
# Ts must be in increasing order .
if check_properties :
    for p in np . array ( properties ) . ravel ( ) :
        if not self . test_property_validity ( p ) :
            raise Exception ( 'One of the properties specified are not feasible' )
if not all ( b > a for a , b in zip ( Ts , Ts [ 1 : ] ) ) :
    raise Exception ( 'Temperatures are not sorted in increasing order' )
if not all ( b > a for a , b in zip ( Ps , Ps [ 1 : ] ) ) :
    raise Exception ( 'Pressures are not sorted in increasing order' )
if name is None :
    name = 'Tabular data series #' + str ( len ( self . tabular_data ) )
    # Will overwrite a poorly named series
self . tabular_data [ name ] = ( Ts , Ps , properties )
self . method_P = None
self . user_methods_P . insert ( 0 , name )
self . all_methods_P . add ( name )
self . set_user_methods_P ( user_methods_P = self . user_methods_P , forced_P = self . forced_P )


signature:
def interpolate_P ( self , T , P , name ) :
    r'''Method to perform interpolation on a given tabular data set
 previously added via ` set _ tabular _ data _ P ` . This method will create the
 interpolators the first time it is used on a property set , and store
 them for quick future use .
 Interpolation is cubic - spline based if 5 or more points are available ,
 and linearly interpolated if not . Extrapolation is always performed
 linearly . This function uses the transforms ` interpolation _ T ` ,
 ` interpolation _ P ` ,
 ` interpolation _ property ` , and ` interpolation _ property _ inv ` if set . If
 any of these are changed after the interpolators were first created ,
 new interpolators are created with the new transforms .
 All interpolation is performed via the ` interp2d ` function .
 Parameters
 T : float
 Temperature at which to interpolate the property , [ K ]
 T : float
 Pressure at which to interpolate the property , [ Pa ]
 name : str
 The name assigned to the tabular data set
 Returns
 prop : float
 Calculated property , [ ` units ` ]'''

implementation:
key = ( name , self . interpolation_T , self . interpolation_P , self . interpolation_property , self . interpolation_property_inv )
# If the interpolator and extrapolator has already been created , load it
if key in self . tabular_data_interpolators :
    extrapolator , spline = self . tabular_data_interpolators [ key ]
else :
    Ts , Ps , properties = self . tabular_data [ name ]
    if self . interpolation_T : # Transform ths Ts with interpolation _ T if set
        Ts2 = [ self . interpolation_T ( T2 ) for T2 in Ts ]
    else :
        Ts2 = Ts
    if self . interpolation_P : # Transform ths Ts with interpolation _ T if set
        Ps2 = [ self . interpolation_P ( P2 ) for P2 in Ps ]
    else :
        Ps2 = Ps
    if self . interpolation_property : # Transform ths props with interpolation _ property if set
        properties2 = [ self . interpolation_property ( p ) for p in properties ]
    else :
        properties2 = properties
    # Only allow linear extrapolation , but with whatever transforms are specified
    extrapolator = interp2d ( Ts2 , Ps2 , properties2 )
    # interpolation if fill value is missing
    # If more than 5 property points , create a spline interpolation
    if len ( properties ) >= 5 :
        spline = interp2d ( Ts2 , Ps2 , properties2 , kind = 'cubic' )
    else :
        spline = None
    self . tabular_data_interpolators [ key ] = ( extrapolator , spline )
# Load the stores values , tor checking which interpolation strategy to
# use .
Ts , Ps , properties = self . tabular_data [ name ]
if T < Ts [ 0 ] or T > Ts [ - 1 ] or not spline or P < Ps [ 0 ] or P > Ps [ - 1 ] :
    tool = extrapolator
else :
    tool = spline
if self . interpolation_T :
    T = self . interpolation_T ( T )
if self . interpolation_P :
    P = self . interpolation_T ( P )
prop = tool ( T , P )
# either spline , or linear interpolation
if self . interpolation_property :
    prop = self . interpolation_property_inv ( prop )
return float ( prop )


signature:
def plot_isotherm ( self , T , Pmin = None , Pmax = None , methods_P = [ ] , pts = 50 , only_valid = True ) : # pragma : no cover
    r'''Method to create a plot of the property vs pressure at a specified
 temperature according to either a specified list of methods , or the
 user methods ( if set ) , or all methods . User - selectable number of
 points , and pressure range . If only _ valid is set ,
 ` test _ method _ validity _ P ` will be used to check if each condition in
 the specified range is valid , and ` test _ property _ validity ` will be used
 to test the answer , and the method is allowed to fail ; only the valid
 points will be plotted . Otherwise , the result will be calculated and
 displayed as - is . This will not suceed if the method fails .
 Parameters
 T : float
 Temperature at which to create the plot , [ K ]
 Pmin : float
 Minimum pressure , to begin calculating the property , [ Pa ]
 Pmax : float
 Maximum pressure , to stop calculating the property , [ Pa ]
 methods _ P : list , optional
 List of methods to consider
 pts : int , optional
 A list of points to calculate the property at ; if Pmin to Pmax
 covers a wide range of method validities , only a few points may end
 up calculated for a given method so this may need to be large
 only _ valid : bool
 If True , only plot successful methods and calculated properties ,
 and handle errors ; if False , attempt calculation without any
 checking and use methods outside their bounds'''

implementation:
# This function cannot be tested
if not has_matplotlib :
    raise Exception ( 'Optional dependency matplotlib is required for plotting' )
if Pmin is None :
    if self . Pmin is not None :
        Pmin = self . Pmin
    else :
        raise Exception ( 'Minimum pressure could not be auto-detected; please provide it' )
if Pmax is None :
    if self . Pmax is not None :
        Pmax = self . Pmax
    else :
        raise Exception ( 'Maximum pressure could not be auto-detected; please provide it' )
if not methods_P :
    if self . user_methods_P :
        methods_P = self . user_methods_P
    else :
        methods_P = self . all_methods_P
Ps = np . linspace ( Pmin , Pmax , pts )
for method_P in methods_P :
    if only_valid :
        properties , Ps2 = [ ] , [ ]
        for P in Ps :
            if self . test_method_validity_P ( T , P , method_P ) :
                try :
                    p = self . calculate_P ( T , P , method_P )
                    if self . test_property_validity ( p ) :
                        properties . append ( p )
                        Ps2 . append ( P )
                except :
                    pass
        plt . plot ( Ps2 , properties , label = method_P )
    else :
        properties = [ self . calculate_P ( T , P , method_P ) for P in Ps ]
        plt . plot ( Ps , properties , label = method_P )
plt . legend ( loc = 'best' )
plt . ylabel ( self . name + ', ' + self . units )
plt . xlabel ( 'Pressure, Pa' )
plt . title ( self . name + ' of ' + self . CASRN )
plt . show ( )


signature:
def plot_isobar ( self , P , Tmin = None , Tmax = None , methods_P = [ ] , pts = 50 , only_valid = True ) : # pragma : no cover
    r'''Method to create a plot of the property vs temperature at a
 specific pressure according to
 either a specified list of methods , or user methods ( if set ) , or all
 methods . User - selectable number of points , and temperature range . If
 only _ valid is set , ` test _ method _ validity _ P ` will be used to check if
 each condition in the specified range is valid , and
 ` test _ property _ validity ` will be used to test the answer , and the
 method is allowed to fail ; only the valid points will be plotted .
 Otherwise , the result will be calculated and displayed as - is . This will
 not suceed if the method fails .
 Parameters
 P : float
 Pressure for the isobar , [ Pa ]
 Tmin : float
 Minimum temperature , to begin calculating the property , [ K ]
 Tmax : float
 Maximum temperature , to stop calculating the property , [ K ]
 methods _ P : list , optional
 List of methods to consider
 pts : int , optional
 A list of points to calculate the property at ; if Tmin to Tmax
 covers a wide range of method validities , only a few points may end
 up calculated for a given method so this may need to be large
 only _ valid : bool
 If True , only plot successful methods and calculated properties ,
 and handle errors ; if False , attempt calculation without any
 checking and use methods outside their bounds'''

implementation:
if not has_matplotlib :
    raise Exception ( 'Optional dependency matplotlib is required for plotting' )
if Tmin is None :
    if self . Tmin is not None :
        Tmin = self . Tmin
    else :
        raise Exception ( 'Minimum pressure could not be auto-detected; please provide it' )
if Tmax is None :
    if self . Tmax is not None :
        Tmax = self . Tmax
    else :
        raise Exception ( 'Maximum pressure could not be auto-detected; please provide it' )
if not methods_P :
    if self . user_methods_P :
        methods_P = self . user_methods_P
    else :
        methods_P = self . all_methods_P
Ts = np . linspace ( Tmin , Tmax , pts )
for method_P in methods_P :
    if only_valid :
        properties , Ts2 = [ ] , [ ]
        for T in Ts :
            if self . test_method_validity_P ( T , P , method_P ) :
                try :
                    p = self . calculate_P ( T , P , method_P )
                    if self . test_property_validity ( p ) :
                        properties . append ( p )
                        Ts2 . append ( T )
                except :
                    pass
        plt . plot ( Ts2 , properties , label = method_P )
    else :
        properties = [ self . calculate_P ( T , P , method_P ) for T in Ts ]
        plt . plot ( Ts , properties , label = method_P )
plt . legend ( loc = 'best' )
plt . ylabel ( self . name + ', ' + self . units )
plt . xlabel ( 'Temperature, K' )
plt . title ( self . name + ' of ' + self . CASRN )
plt . show ( )


signature:
def plot_TP_dependent_property ( self , Tmin = None , Tmax = None , Pmin = None , Pmax = None , methods_P = [ ] , pts = 15 , only_valid = True ) : # pragma : no cover
    r'''Method to create a plot of the property vs temperature and pressure
 according to either a specified list of methods , or user methods ( if
 set ) , or all methods . User - selectable number of points for each
 variable . If only _ valid is set , ` test _ method _ validity _ P ` will be used to
 check if each condition in the specified range is valid , and
 ` test _ property _ validity ` will be used to test the answer , and the
 method is allowed to fail ; only the valid points will be plotted .
 Otherwise , the result will be calculated and displayed as - is . This will
 not suceed if the any method fails for any point .
 Parameters
 Tmin : float
 Minimum temperature , to begin calculating the property , [ K ]
 Tmax : float
 Maximum temperature , to stop calculating the property , [ K ]
 Pmin : float
 Minimum pressure , to begin calculating the property , [ Pa ]
 Pmax : float
 Maximum pressure , to stop calculating the property , [ Pa ]
 methods _ P : list , optional
 List of methods to consider
 pts : int , optional
 A list of points to calculate the property at for both temperature
 and pressure ; pts ^ 2 points will be calculated .
 only _ valid : bool
 If True , only plot successful methods and calculated properties ,
 and handle errors ; if False , attempt calculation without any
 checking and use methods outside their bounds'''

implementation:
if not has_matplotlib :
    raise Exception ( 'Optional dependency matplotlib is required for plotting' )
from mpl_toolkits . mplot3d import axes3d
from matplotlib . ticker import FormatStrFormatter
import numpy . ma as ma
if Pmin is None :
    if self . Pmin is not None :
        Pmin = self . Pmin
    else :
        raise Exception ( 'Minimum pressure could not be auto-detected; please provide it' )
if Pmax is None :
    if self . Pmax is not None :
        Pmax = self . Pmax
    else :
        raise Exception ( 'Maximum pressure could not be auto-detected; please provide it' )
if Tmin is None :
    if self . Tmin is not None :
        Tmin = self . Tmin
    else :
        raise Exception ( 'Minimum pressure could not be auto-detected; please provide it' )
if Tmax is None :
    if self . Tmax is not None :
        Tmax = self . Tmax
    else :
        raise Exception ( 'Maximum pressure could not be auto-detected; please provide it' )
if not methods_P :
    methods_P = self . user_methods_P if self . user_methods_P else self . all_methods_P
Ps = np . linspace ( Pmin , Pmax , pts )
Ts = np . linspace ( Tmin , Tmax , pts )
Ts_mesh , Ps_mesh = np . meshgrid ( Ts , Ps )
fig = plt . figure ( )
ax = fig . gca ( projection = '3d' )
handles = [ ]
for method_P in methods_P :
    if only_valid :
        properties = [ ]
        for T in Ts :
            T_props = [ ]
            for P in Ps :
                if self . test_method_validity_P ( T , P , method_P ) :
                    try :
                        p = self . calculate_P ( T , P , method_P )
                        if self . test_property_validity ( p ) :
                            T_props . append ( p )
                        else :
                            T_props . append ( None )
                    except :
                        T_props . append ( None )
                else :
                    T_props . append ( None )
            properties . append ( T_props )
        properties = ma . masked_invalid ( np . array ( properties , dtype = np . float ) . T )
        handles . append ( ax . plot_surface ( Ts_mesh , Ps_mesh , properties , cstride = 1 , rstride = 1 , alpha = 0.5 ) )
    else :
        properties = [ [ self . calculate_P ( T , P , method_P ) for P in Ps ] for T in Ts ]
        handles . append ( ax . plot_surface ( Ts_mesh , Ps_mesh , properties , cstride = 1 , rstride = 1 , alpha = 0.5 ) )
ax . yaxis . set_major_formatter ( FormatStrFormatter ( '%.4g' ) )
ax . zaxis . set_major_formatter ( FormatStrFormatter ( '%.4g' ) )
ax . xaxis . set_major_formatter ( FormatStrFormatter ( '%.4g' ) )
ax . set_xlabel ( 'Temperature, K' )
ax . set_ylabel ( 'Pressure, Pa' )
ax . set_zlabel ( self . name + ', ' + self . units )
plt . title ( self . name + ' of ' + self . CASRN )
plt . show ( block = False )
# The below is a workaround for a matplotlib bug
ax . legend ( handles , methods_P )
plt . show ( block = False )


signature:
def calculate_derivative_T ( self , T , P , method , order = 1 ) :
    r'''Method to calculate a derivative of a temperature and pressure
 dependent property with respect to temperature at constant pressure ,
 of a given order using a specified method . Uses SciPy ' s derivative
 function , with a delta of 1E - 6 K and a number of points equal to
 2 * order + 1.
 This method can be overwritten by subclasses who may perfer to add
 analytical methods for some or all methods as this is much faster .
 If the calculation does not succeed , returns the actual error
 encountered .
 Parameters
 T : float
 Temperature at which to calculate the derivative , [ K ]
 P : float
 Pressure at which to calculate the derivative , [ Pa ]
 method : str
 Method for which to find the derivative
 order : int
 Order of the derivative , > = 1
 Returns
 d _ prop _ d _ T _ at _ P : float
 Calculated derivative property at constant pressure ,
 [ ` units / K ^ order ` ]'''

implementation: return derivative ( self . calculate_P , T , dx = 1e-6 , args = [ P , method ] , n = order , order = 1 + order * 2 )


signature:
def calculate_derivative_P ( self , P , T , method , order = 1 ) :
    r'''Method to calculate a derivative of a temperature and pressure
 dependent property with respect to pressure at constant temperature ,
 of a given order using a specified method . Uses SciPy ' s derivative
 function , with a delta of 0.01 Pa and a number of points equal to
 2 * order + 1.
 This method can be overwritten by subclasses who may perfer to add
 analytical methods for some or all methods as this is much faster .
 If the calculation does not succeed , returns the actual error
 encountered .
 Parameters
 P : float
 Pressure at which to calculate the derivative , [ Pa ]
 T : float
 Temperature at which to calculate the derivative , [ K ]
 method : str
 Method for which to find the derivative
 order : int
 Order of the derivative , > = 1
 Returns
 d _ prop _ d _ P _ at _ T : float
 Calculated derivative property at constant temperature ,
 [ ` units / Pa ^ order ` ]'''

implementation:
f = lambda P : self . calculate_P ( T , P , method )
return derivative ( f , P , dx = 1e-2 , n = order , order = 1 + order * 2 )


signature:
def TP_dependent_property_derivative_T ( self , T , P , order = 1 ) :
    r'''Method to calculate a derivative of a temperature and pressure
 dependent property with respect to temperature at constant pressure ,
 of a given order . Methods found valid by ` select _ valid _ methods _ P ` are
 attempted until a method succeeds . If no methods are valid and succeed ,
 None is returned .
 Calls ` calculate _ derivative _ T ` internally to perform the actual
 calculation .
 . . math : :
 \ text { derivative } = \ frac { d ( \ text { property } ) } { d T } | _ { P }
 Parameters
 T : float
 Temperature at which to calculate the derivative , [ K ]
 P : float
 Pressure at which to calculate the derivative , [ Pa ]
 order : int
 Order of the derivative , > = 1
 Returns
 d _ prop _ d _ T _ at _ P : float
 Calculated derivative property , [ ` units / K ^ order ` ]'''

implementation:
sorted_valid_methods_P = self . select_valid_methods_P ( T , P )
for method in sorted_valid_methods_P :
    try :
        return self . calculate_derivative_T ( T , P , method , order )
    except :
        pass
return None


signature:
def TP_dependent_property_derivative_P ( self , T , P , order = 1 ) :
    r'''Method to calculate a derivative of a temperature and pressure
 dependent property with respect to pressure at constant temperature ,
 of a given order . Methods found valid by ` select _ valid _ methods _ P ` are
 attempted until a method succeeds . If no methods are valid and succeed ,
 None is returned .
 Calls ` calculate _ derivative _ P ` internally to perform the actual
 calculation .
 . . math : :
 \ text { derivative } = \ frac { d ( \ text { property } ) } { d P } | _ { T }
 Parameters
 T : float
 Temperature at which to calculate the derivative , [ K ]
 P : float
 Pressure at which to calculate the derivative , [ Pa ]
 order : int
 Order of the derivative , > = 1
 Returns
 d _ prop _ d _ P _ at _ T : float
 Calculated derivative property , [ ` units / Pa ^ order ` ]'''

implementation:
sorted_valid_methods_P = self . select_valid_methods_P ( T , P )
for method in sorted_valid_methods_P :
    try :
        return self . calculate_derivative_P ( P , T , method , order )
    except :
        pass
return None


signature:
def set_user_method ( self , user_methods , forced = False ) :
    r'''Method to set the T , P , and composition dependent property methods
 desired for consideration by the user . Can be used to exclude certain
 methods which might have unacceptable accuracy .
 As a side effect , the previously selected method is removed when
 this method is called to ensure user methods are tried in the desired
 order .
 Parameters
 user _ methods : str or list
 Methods by name to be considered for calculation of the mixture
 property , ordered by preference .
 forced : bool , optional
 If True , only the user specified methods will ever be considered ;
 if False , other methods will be considered if no user methods
 suceed .'''

implementation:
# Accept either a string or a list of methods , and whether
# or not to only consider the false methods
if isinstance ( user_methods , str ) :
    user_methods = [ user_methods ]
# The user ' s order matters and is retained for use by select _ valid _ methods
self . user_methods = user_methods
self . forced = forced
# Validate that the user ' s specified methods are actual methods
if set ( self . user_methods ) . difference ( self . all_methods ) :
    raise Exception ( "One of the given methods is not available for this mixture" )
if not self . user_methods and self . forced :
    raise Exception ( 'Only user specified methods are considered when forced is True, but no methods were provided' )
# Remove previously selected methods
self . method = None
self . sorted_valid_methods = [ ]
self . TP_zs_ws_cached = ( None , None , None , None )