Beispiel #1
0
 def list_methods():
     methods = []
     if none_and_length_check([xs, sigmas, rhoms]):
         methods.append(WINTERFELDSCRIVENDAVIS)
     if T and none_and_length_check([xs, sigmas_Tb, Tbs, Tcs]):
         methods.append(DIGUILIOTEJA)
     if none_and_length_check([xs, sigmas]):
         methods.append(SIMPLE)
     methods.append(NONE)
     return methods
Beispiel #2
0
 def list_methods():
     methods = []
     if none_and_length_check([xs, sigmas, rhoms]):
         methods.append(WINTERFELDSCRIVENDAVIS)
     if T and none_and_length_check([xs, sigmas_Tb, Tbs, Tcs]):
         methods.append(DIGUILIOTEJA)
     if none_and_length_check([xs, sigmas]):
         methods.append(SIMPLE)
     methods.append(NONE)
     return methods
Beispiel #3
0
 def list_methods():
     methods = []
     if none_and_length_check((Psats, zs)):
         methods.append('IDEAL_VLE')
     if none_and_length_check([Tcs]) and all([T >= i for i in Tcs]):
         methods.append('SUPERCRITICAL_T')
     if none_and_length_check([Pcs]) and all([P >= i for i in Pcs]):
         methods.append('SUPERCRITICAL_P')
     if none_and_length_check([zs, Tcs]) and any([T > Tc for Tc in Tcs]):
         methods.append('IDEAL_VLE_SUPERCRITICAL')
     methods.append('NONE')
     return methods
Beispiel #4
0
 def list_methods():
     methods = []
     if none_and_length_check((Psats, zs)):
         methods.append('IDEAL_VLE')
     if none_and_length_check([Tcs]) and all([T >= i for i in Tcs]):
         methods.append('SUPERCRITICAL_T')
     if none_and_length_check([Pcs]) and all([P >= i for i in Pcs]):
         methods.append('SUPERCRITICAL_P')
     if none_and_length_check((zs, Tcs)) and any([T > Tc for Tc in Tcs]):
         methods.append('IDEAL_VLE_SUPERCRITICAL')
     methods.append('NONE')
     return methods
Beispiel #5
0
 def list_methods():
     methods = []
     if none_and_length_check((Psats, zs)):
         methods.append(IDEALVLE)
     if none_and_length_check([Tcs]) and all([T >= i for i in Tcs]):
         methods.append(SUPERCRITICALT)
     if none_and_length_check([Pcs]) and all([P >= i for i in Pcs]):
         methods.append(SUPERCRITICALP)
     if none_and_length_check((zs, Tcs)) and any([T > Tc for Tc in Tcs]):
         methods.append(IDEALVLESUPERCRITICAL)
     methods.append(NONE)
     return methods
Beispiel #6
0
 def load_all_methods(self):
     methods = []
     methods.append(SIMPLE)  # Needs sigma
     methods.append(
         WINTERFELDSCRIVENDAVIS)  # Nothing to load, needs rhoms, sigma
     if none_and_length_check((self.Tbs, self.Tcs)):
         self.sigmas_Tb = [
             i(Tb) for i, Tb in zip(self.SurfaceTensions, self.Tbs)
         ]
         # Unlikely but necessary to check all values were calculable
         if none_and_length_check([self.sigmas_Tb]):
             methods.append(DIGUILIOTEJA)
     self.all_methods = set(methods)
Beispiel #7
0
def flash(P, zs, Psats, fugacities=None, gammas=None):
    if not fugacities:
        fugacities = [1 for i in range(len(zs))]
    if not gammas:
        gammas = [1 for i in range(len(zs))]
    if not none_and_length_check((zs, Psats, fugacities, gammas)):
        raise Exception('Input dimentions are inconsistent or some input parameters are missing.')
    ks = [K(P, Psats[i], fugacities[i], gammas[i]) for i in range(len(zs))]

    def valid_range(zs, ks):
        valid = True
        if sum([zs[i]*ks[i] for i in range(len(ks))]) < 1:
            valid = False
        if sum([zs[i]/ks[i] for i in range(len(ks))]) < 1:
            valid = False
        return valid
    if not valid_range(zs, ks):
        raise Exception('Solution does not exist')
#    zs = [0.5, 0.3, 0.2] practice solution
#    ks = [1.685, 0.742, 0.532]
    x0 = np.array([.5])
    V_over_F = fsolve(Rachford_Rice_flash_error, x0=x0, args=(zs, ks))[0]
    if V_over_F < 0:
#        print zs, ks
        raise Exception('V_over_F is negative!')
    xs = [zs[i]/(1+V_over_F*(ks[i]-1)) for i in range(len(zs))]
    ys = [ks[i]*xs[i] for i in range(len(zs))]
    return xs, ys, V_over_F
Beispiel #8
0
 def list_methods():
     methods = []
     if none_and_length_check([Tms]):
         methods.append('Maximum')
         methods.append('Simple')
     methods.append('None')
     return methods
Beispiel #9
0
def Winterfeld_Scriven_Davis(xs, sigmas, rhoms):
    r'''Calculates surface tension of a liquid mixture according to
    mixing rules in [1]_ and also in [2]_.

    .. math::
        \sigma_M = \sum_i \sum_j \frac{1}{V_L^{L2}}\left(x_i V_i \right)
        \left( x_jV_j\right)\sqrt{\sigma_i\cdot \sigma_j}

    Parameters
    ----------
    xs : array-like
        Mole fractions of all components, [-]
    sigmas : array-like
        Surface tensions of all components, [N/m]
    rhoms : array-like
        Molar densities of all components, [mol/m^3]

    Returns
    -------
    sigma : float
        Air-liquid surface tension of mixture, [N/m]

    Notes
    -----
    DIPPR Procedure 7C: Method for the Surface Tension of Nonaqueous Liquid
    Mixtures

    Becomes less accurate as liquid-liquid critical solution temperature is
    approached. DIPPR Evaluation:  3-4% AARD, from 107 nonaqueous binary
    systems, 1284 points. Internally, densities are converted to kmol/m^3. The
    Amgat function is used to obtain liquid mixture density in this equation.

    Raises a ZeroDivisionError if either molar volume are zero, and a
    ValueError if a surface tensions of a pure component is negative.

    Examples
    --------
    >>> Winterfeld_Scriven_Davis([0.1606, 0.8394], [0.01547, 0.02877],
    ... [8610., 15530.])
    0.024967388450439817

    References
    ----------
    .. [1] Winterfeld, P. H., L. E. Scriven, and H. T. Davis. "An Approximate
       Theory of Interfacial Tensions of Multicomponent Systems: Applications
       to Binary Liquid-Vapor Tensions." AIChE Journal 24, no. 6
       (November 1, 1978): 1010-14. doi:10.1002/aic.690240610.
    .. [2] Danner, Ronald P, and Design Institute for Physical Property Data.
       Manual for Predicting Chemical Process Design Data. New York, N.Y, 1982.
    '''
    if not none_and_length_check([xs, sigmas, rhoms]):
        raise Exception('Function inputs are incorrect format')
    rhoms = [i/1E3 for i in rhoms]
    Vms = [(i)**-1 for i in rhoms]
    rho = 1./mixing_simple(xs, Vms)
    sigma = 0
    for i in range(len(xs)):
        for j in range(len(xs)):
            sigma += rho**2*xs[i]/rhoms[i]*xs[j]/rhoms[j]*(sigmas[j]*sigmas[i])**0.5
    return sigma
Beispiel #10
0
 def list_methods():
     methods = []
     if CASRNs:
         CASRNs2 = list(CASRNs)
         UFLs2 = list(UFLs)
         for i in inerts:
             if i in CASRNs2:
                 ind = CASRNs.index(i)
                 CASRNs2.remove(i)
                 UFLs2.remove(UFLs[ind])
         if none_and_length_check([UFLs2]):
             methods.append('Summed Inverse, inerts removed')
     if none_and_length_check([UFLs, ys]):
         methods.append('Summed Inverse')
     methods.append('None')
     return methods
Beispiel #11
0
def Winterfeld_Scriven_Davis(xs, sigmas, rhoms):
    r'''Calculates surface tension of a liquid mixture according to
    mixing rules in [1]_ and also in [2]_.

    .. math::
        \sigma_M = \sum_i \sum_j \frac{1}{V_L^{L2}}\left(x_i V_i \right)
        \left( x_jV_j\right)\sqrt{\sigma_i\cdot \sigma_j}

    Parameters
    ----------
    xs : array-like
        Mole fractions of all components, [-]
    sigmas : array-like
        Surface tensions of all components, [N/m]
    rhoms : array-like
        Molar densities of all components, [mol/m^3]

    Returns
    -------
    sigma : float
        Air-liquid surface tension of mixture, [N/m]

    Notes
    -----
    DIPPR Procedure 7C: Method for the Surface Tension of Nonaqueous Liquid
    Mixtures

    Becomes less accurate as liquid-liquid critical solution temperature is
    approached. DIPPR Evaluation:  3-4% AARD, from 107 nonaqueous binary
    systems, 1284 points. Internally, densities are converted to kmol/m^3. The
    Amgat function is used to obtain liquid mixture density in this equation.

    Raises a ZeroDivisionError if either molar volume are zero, and a
    ValueError if a surface tensions of a pure component is negative.

    Examples
    --------
    >>> Winterfeld_Scriven_Davis([0.1606, 0.8394], [0.01547, 0.02877],
    ... [8610., 15530.])
    0.024967388450439817

    References
    ----------
    .. [1] Winterfeld, P. H., L. E. Scriven, and H. T. Davis. "An Approximate
       Theory of Interfacial Tensions of Multicomponent Systems: Applications
       to Binary Liquid-Vapor Tensions." AIChE Journal 24, no. 6
       (November 1, 1978): 1010-14. doi:10.1002/aic.690240610.
    .. [2] Danner, Ronald P, and Design Institute for Physical Property Data.
       Manual for Predicting Chemical Process Design Data. New York, N.Y, 1982.
    '''
    if not none_and_length_check([xs, sigmas, rhoms]):
        raise Exception('Function inputs are incorrect format')
    rhoms = [i/1E3 for i in rhoms]
    Vms = [(i)**-1 for i in rhoms]
    rho = 1./mixing_simple(xs, Vms)
    sigma = 0
    for i in range(len(xs)):
        for j in range(len(xs)):
            sigma += rho**2*xs[i]/rhoms[i]*xs[j]/rhoms[j]*(sigmas[j]*sigmas[i])**0.5
    return sigma
Beispiel #12
0
 def list_methods():
     methods = []
     if none_and_length_check([Tms]):
         methods.append('Maximum')
         methods.append('Simple')
     methods.append('None')
     return methods
Beispiel #13
0
 def list_methods():
     ''' List methods available to identify the phase of a mixture '''
     methods = []
     if Psats and none_and_length_check((Psats, zs)):
         methods.append('IDEAL_VLE')
     if (Tcs and none_and_length_check([Tcs])
             and all([T >= i for i in Tcs])):
         methods.append('SUPERCRITICAL_T')
     if (Pcs and none_and_length_check([Pcs])
             and all([P >= i for i in Pcs])):
         methods.append('SUPERCRITICAL_P')
     if (Tcs and none_and_length_check([zs, Tcs])
             and any([T > Tc for Tc in Tcs])):
         methods.append('IDEAL_VLE_SUPERCRITICAL')
     methods.append('NONE')
     return methods
Beispiel #14
0
def flash(P, zs, Psats, fugacities=None, gammas=None):
    if not fugacities:
        fugacities = [1 for i in range(len(zs))]
    if not gammas:
        gammas = [1 for i in range(len(zs))]
    if not none_and_length_check((zs, Psats, fugacities, gammas)):
        raise Exception(
            'Input dimentions are inconsistent or some input parameters are missing.'
        )
    ks = [K(P, Psats[i], fugacities[i], gammas[i]) for i in range(len(zs))]

    def valid_range(zs, ks):
        valid = True
        if sum([zs[i] * ks[i] for i in range(len(ks))]) < 1:
            valid = False
        if sum([zs[i] / ks[i] for i in range(len(ks))]) < 1:
            valid = False
        return valid

    if not valid_range(zs, ks):
        raise Exception('Solution does not exist')


#    zs = [0.5, 0.3, 0.2] practice solution
#    ks = [1.685, 0.742, 0.532]
    x0 = np.array([.5])
    V_over_F = fsolve(Rachford_Rice_flash_error, x0=x0, args=(zs, ks))[0]
    if V_over_F < 0:
        #        print zs, ks
        raise Exception('V_over_F is negative!')
    xs = [zs[i] / (1 + V_over_F * (ks[i] - 1)) for i in range(len(zs))]
    ys = [ks[i] * xs[i] for i in range(len(zs))]
    return xs, ys, V_over_F
Beispiel #15
0
 def list_methods():
     ''' List methods available for calculating bubble pressure '''
     methods = []
     if none_and_length_check((Psats, zs)):
         methods.append('IDEAL_VLE')
     methods.append('NONE')
     return methods
Beispiel #16
0
 def list_methods():
     ''' List methods availble for calculating mixture dew point '''
     methods = []
     if none_and_length_check((Psats, zs)):
         methods.append('IDEAL_VLE')
     methods.append('NONE')
     return methods
Beispiel #17
0
def flash(P, zs, Psats):
    '''
    Parameters
    ----------
    P : list[float]?
        Pressure, [-]
    zs : list[float]
        Overall mole fractions of all species, [-]
    Psats : list[float]?
        Saturation pressure, [-]

    Returns
    -------
    xs : list[float]
        Mole fractions of each species in the liquid phase, [-]
    ys : list[float]
        Mole fractions of each species in the vapor phase, [-]
    V_over_F : float
        Vapor fraction solution [-]

    '''
    #    if not fugacities:
    #        fugacities = [1 for i in range(len(zs))]
    #    if not gammas:
    #        gammas = [1 for i in range(len(zs))]
    if not none_and_length_check((zs, Psats)):
        raise Exception('Input dimentions are inconsistent or some input '
                        'parameters are missing.')
    Ks = [K_value(P=P, Psat=Psats[i]) for i in range(len(zs))]

    def valid_range(zs, Ks):
        ''' Determines if zs and Ks are valid for this calculation

        Parameters
        ----------
        zs : list[float]
            Overall mole fractions of all species, [-]
        Ks : list[float]
            Equilibrium K-values, [-]

        Returns
        -------
        valid : bool
            True if arguments are valid, False otherwise
        '''

        valid = True
        if sum([zs[i] * Ks[i] for i in range(len(Ks))]) < 1:
            valid = False
        if sum([zs[i] / Ks[i] for i in range(len(Ks))]) < 1:
            valid = False
        return valid

    if not valid_range(zs, Ks):
        raise Exception('Solution does not exist')

    V_over_F, xs, ys = flash_inner_loop(zs=zs, Ks=Ks)
    if V_over_F < 0:
        raise Exception('V_over_F is negative!')
    return xs, ys, V_over_F
Beispiel #18
0
    def list_methods():
        ''' List methods available for calculating a mixture's acentric
        factor, omega '''

        methods = []
        if none_and_length_check([zs, omegas]):
            methods.append('SIMPLE')
        methods.append('NONE')
        return methods
Beispiel #19
0
    def load_all_methods(self):
        r'''Method to initialize the object by precomputing any values which
        may be used repeatedly and by retrieving mixture-specific variables.
        All data are stored as attributes. This method also sets :obj:`Tmin`, 
        :obj:`Tmax`, and :obj:`all_methods` as a set of methods which should 
        work to calculate the property.

        Called on initialization only. See the source code for the variables at
        which the coefficients are stored. The coefficients can safely be
        altered once the class is initialized. This method can be called again
        to reset the parameters.
        '''
        methods = []
        methods.append(SIMPLE)  # Needs sigma
        methods.append(
            WINTERFELDSCRIVENDAVIS)  # Nothing to load, needs rhoms, sigma
        if none_and_length_check((self.Tbs, self.Tcs)):
            self.sigmas_Tb = [
                i(Tb) for i, Tb in zip(self.SurfaceTensions, self.Tbs)
            ]
            if none_and_length_check([self.sigmas_Tb]):
                methods.append(DIGUILIOTEJA)
        self.all_methods = set(methods)
Beispiel #20
0
def dew_at_T(zs, Psats, fugacities=None, gammas=None):
    '''
    >>> dew_at_T([0.5, 0.5], [1400, 7000])
    2333.3333333333335
    >>> dew_at_T([0.5, 0.5], [1400, 7000], gammas=[1.1, .75])
    2381.443298969072
    >>> dew_at_T([0.5, 0.5], [1400, 7000], gammas=[1.1, .75], fugacities=[.995, 0.98])
    2401.621874512658
    '''
    if not fugacities:
        fugacities = [1 for i in range(len(Psats))]
    if not gammas:
        gammas = [1 for i in range(len(Psats))]
    if not none_and_length_check((zs, Psats, fugacities, gammas)):
        raise Exception('Input dimentions are inconsistent or some input parameters are missing.')
    P = 1/sum(zs[i]*fugacities[i]/Psats[i]/gammas[i] for i in range(len(zs)))
    return P
Beispiel #21
0
def bubble_at_T(zs, Psats, fugacities=None, gammas=None):
    '''
    >>> bubble_at_T([0.5, 0.5], [1400, 7000])
    4200.0
    >>> bubble_at_T([0.5, 0.5], [1400, 7000], gammas=[1.1, .75])
    3395.0
    >>> bubble_at_T([0.5, 0.5], [1400, 7000], gammas=[1.1, .75], fugacities=[.995, 0.98])
    3452.440775305097
    '''
    if not fugacities:
        fugacities = [1 for i in range(len(Psats))]
    if not gammas:
        gammas = [1 for i in range(len(Psats))]
    if not none_and_length_check((zs, Psats, fugacities, gammas)):
        raise Exception('Input dimentions are inconsistent or some input parameters are missing.')
    P = sum(zs[i]*Psats[i]*gammas[i]/fugacities[i] for i in range(len(zs)))
    return P
Beispiel #22
0
def flash(P, zs, Psats, fugacities=None, gammas=None):
    if not fugacities:
        fugacities = [1 for i in range(len(zs))]
    if not gammas:
        gammas = [1 for i in range(len(zs))]
    if not none_and_length_check((zs, Psats, fugacities, gammas)):
        raise Exception('Input dimentions are inconsistent or some input parameters are missing.')
    Ks = [K(P, Psats[i], fugacities[i], gammas[i]) for i in range(len(zs))]
    def valid_range(zs, Ks):
        valid = True
        if sum([zs[i]*Ks[i] for i in range(len(Ks))]) < 1:
            valid = False
        if sum([zs[i]/Ks[i] for i in range(len(Ks))]) < 1:
            valid = False
        return valid
    if not valid_range(zs, Ks):
        raise Exception('Solution does not exist')
        
    V_over_F, xs, ys = flash_inner_loop(zs=zs, Ks=Ks)
    if V_over_F < 0:
        raise Exception('V_over_F is negative!')
    return xs, ys, V_over_F
Beispiel #23
0
def Diguilio_Teja(T, xs, sigmas_Tb, Tbs, Tcs):
    r'''Calculates surface tension of a liquid mixture according to
    mixing rules in [1]_.

    .. math::
        \sigma = 1.002855(T^*)^{1.118091} \frac{T}{T_b} \sigma_r

        T^*  = \frac{(T_c/T)-1}{(T_c/T_b)-1}

        \sigma_r = \sum x_i \sigma_i

        T_b = \sum x_i T_{b,i}

        T_c = \sum x_i T_{c,i}

    Parameters
    ----------
    T : float
        Temperature of fluid [K]
    xs : array-like
        Mole fractions of all components
    sigmas_Tb : array-like
        Surface tensions of all components at the boiling point, [N/m]
    Tbs : array-like
        Boiling temperatures of all components, [K]
    Tcs : array-like
        Critical temperatures of all components, [K]

    Returns
    -------
    sigma : float
        Air-liquid surface tension of mixture, [N/m]

    Notes
    -----
    Simple model, however it has 0 citations. Gives similar results to the
    `Winterfeld_Scriven_Davis` model.

    Raises a ValueError if temperature is greater than the mixture's critical
    temperature or if the given temperature is negative, or if the mixture's
    boiling temperature is higher than its critical temperature.

    Examples
    --------
    >>> Diguilio_Teja(T=298.15, xs=[0.1606, 0.8394],
    ... sigmas_Tb=[0.01424, 0.02530], Tbs=[309.21, 312.95], Tcs=[469.7, 508.0])
    0.025716823875045505

    References
    ----------
    .. [1] Diguilio, Ralph, and Amyn S. Teja. "Correlation and Prediction of
       the Surface Tensions of Mixtures." The Chemical Engineering Journal 38,
       no. 3 (July 1988): 205-8. doi:10.1016/0300-9467(88)80079-0.
    '''
    if not none_and_length_check([xs, sigmas_Tb, Tbs, Tcs]):
        raise Exception('Function inputs are incorrect format')

    Tc = mixing_simple(xs, Tcs)
    Tb = mixing_simple(xs, Tbs)
    sigmar = mixing_simple(xs, sigmas_Tb)
    Tst = (Tc/T - 1.)/(Tc/Tb - 1)
    sigma = 1.002855*Tst**1.118091*(T/Tb)*sigmar
    return sigma
Beispiel #24
0
 def list_methods():
     methods = []
     if none_and_length_check((Psats, zs)):
         methods.append('IDEAL_VLE')
     methods.append('NONE')
     return methods
Beispiel #25
0
 def list_methods():
     methods = []
     if none_and_length_check([zs, omegas]):
         methods.append('SIMPLE')
     methods.append('NONE')
     return methods
Beispiel #26
0
 def list_methods():
     methods = []
     if none_and_length_check((Psats, zs)):
         methods.append(IDEALVLE)
     methods.append(NONE)
     return methods
Beispiel #27
0
def Diguilio_Teja(T, xs, sigmas_Tb, Tbs, Tcs):
    r'''Calculates surface tension of a liquid mixture according to
    mixing rules in [1]_.

    .. math::
        \sigma = 1.002855(T^*)^{1.118091} \frac{T}{T_b} \sigma_r

        T^*  = \frac{(T_c/T)-1}{(T_c/T_b)-1}

        \sigma_r = \sum x_i \sigma_i

        T_b = \sum x_i T_{b,i}

        T_c = \sum x_i T_{c,i}

    Parameters
    ----------
    T : float
        Temperature of fluid [K]
    xs : array-like
        Mole fractions of all components
    sigmas_Tb : array-like
        Surface tensions of all components at the boiling point, [N/m]
    Tbs : array-like
        Boiling temperatures of all components, [K]
    Tcs : array-like
        Critical temperatures of all components, [K]

    Returns
    -------
    sigma : float
        Air-liquid surface tension of mixture, [N/m]

    Notes
    -----
    Simple model, however it has 0 citations. Gives similar results to the
    `Winterfeld_Scriven_Davis` model.

    Raises a ValueError if temperature is greater than the mixture's critical
    temperature or if the given temperature is negative, or if the mixture's
    boiling temperature is higher than its critical temperature.

    Examples
    --------
    >>> Diguilio_Teja(T=298.15, xs=[0.1606, 0.8394],
    ... sigmas_Tb=[0.01424, 0.02530], Tbs=[309.21, 312.95], Tcs=[469.7, 508.0])
    0.025716823875045505

    References
    ----------
    .. [1] Diguilio, Ralph, and Amyn S. Teja. "Correlation and Prediction of
       the Surface Tensions of Mixtures." The Chemical Engineering Journal 38,
       no. 3 (July 1988): 205-8. doi:10.1016/0300-9467(88)80079-0.
    '''
    if not none_and_length_check([xs, sigmas_Tb, Tbs, Tcs]):
        raise Exception('Function inputs are incorrect format')

    Tc = mixing_simple(xs, Tcs)
    Tb = mixing_simple(xs, Tbs)
    sigmar = mixing_simple(xs, sigmas_Tb)
    Tst = (Tc / T - 1.) / (Tc / Tb - 1)
    sigma = 1.002855 * Tst**1.118091 * (T / Tb) * sigmar
    return sigma
Beispiel #28
0
 def list_methods():
     methods = []
     if none_and_length_check([zs, omegas]):
         methods.append('SIMPLE')
     methods.append('NONE')
     return methods
Beispiel #29
0
 def list_methods():
     methods = []
     if none_and_length_check((Psats, zs)):
         methods.append('IDEAL_VLE')
     methods.append('NONE')
     return methods