Beispiel #1
0
    def propPhase(self):
        phases = []
        for i in self.medium:
            phase1 = PhaseSI('T', self.t1, 'P', self.p * i[1], i[0])
            if phase1 == 'supercritical_gas':
                phase1 = 'gas'
            elif phase1 == 'supercritical_liquid':
                phase1 = 'liquid'

            phase2 = PhaseSI('T', self.t2, 'P', self.p * i[1], i[0])
            if phase2 == 'supercritical_gas':
                phase2 = 'gas'
            elif phase2 == 'supercritical_liquid':
                phase2 = 'liquid'

            if phase1 == phase2:
                phases.append(phase1)
            else:
                return 'twophase'

        for phase in phases:
            if phase != phases[0]:
                return 'twophase'

        return phases[0]
def bottom_up(fluid, z_bot, z_top, dz, mflow, P, T_celsius, d, k, g=9.81):
    #
    #   bottom-up simulation
    z = z_bot
    h = PropsSI('H', 'T', T_celsius + 273.15, 'P', P, fluid)
    rho = PropsSI('D', 'T', T_celsius + 273.15, 'P', P, fluid)

    A = np.pi * d**2 / 4.
    V = mflow / rho / A  #negative massflow is injection
    phase = PhaseSI('T', T_celsius + 273.15, 'P', P, fluid)

    results_vals = [[z, P, h, rho, V, T_celsius, phase]]
    for i in np.arange(z_bot, z_top, dz):
        #        print z, z_top
        if z + dz > z_top:
            z2, h2, P2 = wellbore_step(fluid, z, z_top - z, h, V, P, rho, d, k,
                                       g)
        else:
            z2, h2, P2 = wellbore_step(fluid, z, dz, h, V, P, rho, d, k, g)

        if P2 < 5E3: break

        h = h2
        P = P2
        z = z2
        #update rho
        try:
            rho = PropsSI('D', 'H', h, 'P', P, fluid)
            phase = PhaseSI('H', h, 'P', P, fluid)
        except ValueError:
            print 'Warning: Error in z={}'.format(z)
            continue
        #update V
        V = mflow / rho / A  #velocity updated with density
        #check Temp
        T_celsius = PropsSI('T', 'H', h, 'P', P, fluid) - 273.15
        results_vals += [[z, P, h, rho, V, T_celsius, phase]]

#        print 'Debug: ', z, P, h, rho, V
    results_df = pd.DataFrame(
        results_vals, columns=['z', 'P', 'h', 'rho', 'V', 'T', 'phase'])

    return results_df
def get_heat_extraction_rate(work_dir, fluid, inj_temp=30):
    pres_df, temp_df, mass_df = get_data(fluid, work_dir)

    times = mass_df.time.unique().tolist()
    columns = temp_df.columns.tolist()
    wnames = get_well_names(work_dir)
    wname_map = {k: wnames[i] for i, k in enumerate(columns)}

    h_df = pd.DataFrame(columns=columns, index=times)
    state_df = pd.DataFrame(columns=columns, index=times)

    for t in times:
        print "DEBUG: time is " + str(t)
        for col in columns:

            if fluid == 'Water':
                mf = mass_df[(mass_df['Node'] == col)
                             & (mass_df['time'] == t)]['mf_water'].values[0]
            elif fluid == 'CO2':
                mf = mass_df[(mass_df['Node'] == col)
                             & (mass_df['time'] == t)]['mf_co2'].values[0]

            if mf > 0.0:
                T = temp_df.loc[t, col] + 273.15
            elif mf < 0.0:
                T = inj_temp + 273.15
                inj_well = col

            P = pres_df.loc[t, col] * 1E6
            h_df.loc[t, col] = PropsSI('H', 'T', T, 'P', P, fluid) / 1E3
            state_df.loc[t, col] = PhaseSI('T', T, 'P', P, fluid)

    prod_wells = [col for col in columns if col != inj_well]
    q_df = pd.DataFrame(columns=prod_wells, index=times)

    for t in times:
        print "DEBUG: time is " + str(t)
        for col in prod_wells:
            if fluid == 'Water':
                mf = mass_df[(mass_df['Node'] == col)
                             & (mass_df['time'] == t)]['mf_water'].values[0]
            elif fluid == 'CO2':
                mf = mass_df[(mass_df['Node'] == col)
                             & (mass_df['time'] == t)]['mf_co2'].values[0]

            q_df.loc[t, col] = mf * (h_df.loc[t, col] - h_df.loc[t, inj_well])

    q_df['Total'] = q_df.sum(axis=1)
    q_df.rename(columns=wname_map, inplace=True)
    h_df.rename(columns=wname_map, inplace=True)
    state_df.rename(columns=wname_map, inplace=True)

    return q_df, h_df, state_df
Beispiel #4
0
 def get_phase(self,
               fluid: str,
               fp: str,
               fpv: float,
               sp: str,
               spv: float,
               n: int = 4):
     """ get fluid's phase """
     try:
         result = PhaseSI(fp, fpv, sp, spv, fluid)
     except:
         result = 'phase does not work'
     return result
Beispiel #5
0
def get_phase(T,p):
    """Returns the phase of water through CoolProp library

    Arguments:
        T {K} -- Temperature
        P {Pa} -- Pressure
    
    Returns:
        Returns phase according to CoolProp
        ('liquid'/'gas'/'supercritical_gas'/'supercritical'/'supercritical_liquid')
    """ 

    return PhaseSI('T',T,'P',p,"HEOS::Water")
Beispiel #6
0
def CoolProp_T_dependent_property(T, CASRN, prop, phase):
    r'''Calculates a property of a chemical in either the liquid or gas phase
    as a function of temperature only. This means that the property is
    either at 1 atm or along the saturation curve.

    Parameters
    ----------
        T : float
            Temperature of the fluid [K]
        CASRN : str
            CAS number of the fluid
        prop : str
            CoolProp string shortcut for desired property
        phase : str
            Either 'l' or 'g' for liquid or gas properties respectively

    Returns
    -------
        prop : float
            Desired chemical property, [units]

    Notes
    -----
    For liquids above their boiling point, the liquid property is found on the
    saturation line (at higher pressures). Under their boiling point, the
    property is calculated at 1 atm.

    No liquid calculations are permitted above the critical temperature.

    For gases under the chemical's boiling point, the gas property is found
    on the saturation line (at sub-atmospheric pressures). Above the boiling
    point, the property is calculated at 1 atm.

    An exception is raised if the desired CAS is not supported, or if CoolProp
    is not available.

    The list of strings acceptable as an input for property types is:
    http://www.coolprop.org/coolprop/HighLevelAPI.html#table-of-string-inputs-to-propssi-function

    Examples
    --------
    Water at STP according to IAPWS-95

    >>> CoolProp_T_dependent_property(298.15, '7732-18-5', 'D', 'l')
    997.047636760347

    References
    ----------
    .. [1] Bell, Ian H., Jorrit Wronski, Sylvain Quoilin, and Vincent Lemort.
       "Pure and Pseudo-Pure Fluid Thermophysical Property Evaluation and the
       Open-Source Thermophysical Property Library CoolProp." Industrial &
       Engineering Chemistry Research 53, no. 6 (February 12, 2014):
       2498-2508. doi:10.1021/ie4033999. http://www.coolprop.org/
    '''
    if not has_CoolProp:  # pragma: no cover
        raise Exception('CoolProp library is not installed')
    if CASRN not in coolprop_dict:
        raise Exception('CASRN not in list of supported fluids')
    Tc = coolprop_fluids[CASRN].Tc
    T = float(T)  # Do not allow custom objects here
    if phase == 'l':
        if T > Tc:
            raise Exception(
                'For liquid properties, must be under the critical temperature.'
            )
        if PhaseSI('T', T, 'P', 101325,
                   CASRN) in [u'liquid', u'supercritical_liquid']:
            return PropsSI(prop, 'T', T, 'P', 101325, CASRN)
        else:
            return PropsSI(prop, 'T', T, 'Q', 0, CASRN)
    elif phase == 'g':
        if PhaseSI('T', T, 'P', 101325, CASRN) == 'gas':
            return PropsSI(prop, 'T', T, 'P', 101325, CASRN)
        else:
            if T < Tc:
                return PropsSI(prop, 'T', T, 'Q', 1, CASRN)
            else:
                # catch supercritical_gas and friends
                return PropsSI(prop, 'T', T, 'P', 101325, CASRN)
    else:
        raise Exception('Error in CoolProp property function')
Beispiel #7
0
def PropertyLookup(
    desired,
    T=None,
    p=None,
    v=None,
    u=None,
    h=None,
    s=None,
    x=None,
    d=None,
    rho=None,
    u_molar=None,
    h_molar=None,
    s_molar=None,
    d_molar=None,
    fluid=None,
    unit_system=None,
    verbose=False,
    **kwargs,
):
    """
    Each of the follow properties/parameters is expected to be a quantity with units

    :param desired: Dependent from two of the following independent properties
    :param T: Temperature (Default value = None)
    :param p: pressure (Default value = None)
    :param v: mass specific volume (Default value = None)
    :param u: mass specific internal energy (Default value = None)
    :param h: mass specific enthalpy (Default value = None)
    :param s: mass specific entropy (Default value = None)
    :param x: mass quality (Default value = None)
    :param d: mass density (Default value = None)
    :param rho: mass density (Default value = None)
    :param u_molar: molar specific internal energy (Default value = None)
    :param h_molar: molar specific enthalpy (Default value = None)
    :param s_molar: molar specific entropy (Default value = None)
    :param d_molar: molar density (Default value = None)
    :param fluid: fluid name (Default value = None)
    :param unit_system: unit system for return value - one of 'SI_C', 'SI_K', 'English_F', 'English_R' (Default value = )
    :param verbose: show debug information (Default value = False)
    :param **kwargs:

    """

    # Translate common variable names into CoolProp syntax, i.e. quality
    CP_symb_trans = {"x": "Q", "rho": "D"}
    # flag to determine whether the result from CoolProps should be inverted, i.e. density to specific volume
    invert_result = False
    if desired in CP_symb_trans.keys():
        # CoolProp expects all parameters to be capitalized
        CP_desired = CP_symb_trans[desired].upper()
    elif desired.upper() in ["V"]:
        # Use CoolProp library to return specific volume by inverting the density
        invert_result = True
        CP_desired = "D"
    elif desired in ["vmolar"]:
        # Use CoolProp library to return specific volume by inverting the density
        invert_result = True
        CP_desired = "DMOLAR"
    else:
        CP_desired = (desired.upper()
                      )  # CoolProp expects all parameters to be capitalized

    if "phase" in desired.lower():
        PropsSI_args = (
            []
        )  # don't add a desired parameter for the call to CoolProp.PhaseSI
    else:
        # add the desired parameter as the first argument to pass to CoolProp.PropsSI
        PropsSI_args = [CP_desired]

    def process_indep_arg(arg, CPSymb, exponent=1, AltSymb=None):
        """
        Add a property symbol and its value to the CoolProp.PropSI argument string

        :param arg: value of independent parameter
        :param CPSymb: CoolProp symbol
        :param exponent: exponent used to invert the value (Default value = 1)
        :param AltSymb: symbol to use for inverted values (Default value = None)

        """
        if arg is not None:
            if AltSymb:
                PropsSI_args.append(AltSymb)
            else:
                # Add independent parameter symbol to argument list
                PropsSI_args.append(CPSymb)
            if CP_symbUpper_to_units[CPSymb] is not None:
                # Add independent parameter value to argument list with appropriate magnitude and units stripped (invert specific volume to get density if needed)
                if not isinstance(arg, Quantity):
                    arg_type = CP_symb_to_type[PropsSI_args[-1]]
                    arg_units = preferred_units_from_type(
                        arg_type, unit_system)
                    arg = Quantity(arg, arg_units)
                value = (arg.to(
                    CP_symbUpper_to_units[CPSymb]).magnitude)**exponent
            else:
                value = arg  # Add independent paramter value directly to argument list if it has no units that need to be adjusted
            PropsSI_args.append(value)

    # Process all the possible independent arguments
    process_indep_arg(T, "T")
    process_indep_arg(p, "P")
    process_indep_arg(v, "V", exponent=-1, AltSymb="D")
    process_indep_arg(u, "U")
    process_indep_arg(h, "H")
    process_indep_arg(s, "S")
    process_indep_arg(x, "Q")
    process_indep_arg(d, "D")
    process_indep_arg(rho, "D")
    process_indep_arg(u_molar, "UMOLAR")
    process_indep_arg(h_molar, "HMOLAR")
    process_indep_arg(s_molar, "SMOLAR")
    process_indep_arg(d_molar, "DMOLAR")

    # Add the fluid name as the last parameter to the argument list
    PropsSI_args.append(fluid)
    if verbose:
        print("Calling: CoolProps.CoolProps.PropsSI({})".format(",".join(
            [str(i) for i in PropsSI_args])))
    # Make call to PropsSI or PhaseSI
    if "phase" in desired.lower():
        result = PhaseSI(*PropsSI_args)
        return result
    else:
        result = PropsSI(*PropsSI_args)
    # Determine the units of the value as returned from CoolProp
    CP_return_units = CP_symbUpper_to_units[CP_desired]
    CP_return_type = CP_symb_to_type[desired]
    # Determine the preferred units for the value
    if unit_system is None:
        result_units = preferred_units_from_type(CP_return_type,
                                                 units.preferred_units)
    else:
        result_units = preferred_units_from_type(CP_return_type, unit_system)
    # Convert the returned value to the preferred units
    if result_units is not None:
        if invert_result:
            result = Quantity(result, CP_return_units)**-1
            result = result.to(result_units)
        else:
            result = Quantity(result, CP_return_units).to(result_units)
    return result
Beispiel #8
0
    def phase_byPressTemp(self, flt_P_Pascal, flt_Temp_K):
        if self.isError():
            return

        return PhaseSI("P", flt_P_Pascal, "T", flt_Temp_K, self.m_fluid)