Beispiel #1
0
    def __init__(self, fluids):

        num_fl = len(fluids)
        if num_fl > 0:
            fl = tuple(fluids)
            memorise.T_ph[fl] = np.empty((0, num_fl + 3), float)
            memorise.T_ph_f[fl] = []
            memorise.T_ps[fl] = np.empty((0, num_fl + 4), float)
            memorise.T_ps_f[fl] = []
            memorise.v_ph[fl] = np.empty((0, num_fl + 3), float)
            memorise.v_ph_f[fl] = []
            memorise.visc_ph[fl] = np.empty((0, num_fl + 3), float)
            memorise.visc_ph_f[fl] = []
            memorise.s_ph[fl] = np.empty((0, num_fl + 3), float)
            memorise.s_ph_f[fl] = []
            memorise.count = 0

        for f in fluids:
            try:
                pmin, pmax = CPPSI('PMIN', f), CPPSI('PMAX', f)
            except ValueError:
                pmin, pmax = 2000, 2000e5

        for f in fluids:
            try:
                Tmin, Tmax = CPPSI('TMIN', f), CPPSI('TMAX', f)
            except ValueError:
                Tmin, Tmax = 2000, 2000e5

            memorise.vrange[f] = [pmin, pmax, Tmin, Tmax]
Beispiel #2
0
def ds_mix_pdT(flow, T):
    r"""
    calculates partial derivate of entropy to temperature at constant pressure

    :param flow: vector containing [mass flow, pressure, enthalpy, fluid]
    :type flow: list
    :param T: temperature in K
    :type T: numeric
    :returns: ds / dT (float) - derivative in J / (kg * K :sup:`2`)

    .. math::

        \frac{\partial s_{mix}}{\partial T} =
        \frac{s_{mix}(p,T+d)-s_{mix}(p,T-d)}{2 \cdot d}
    """
    n = molar_massflow(flow[3])
    d = 2
    s_u = 0
    s_l = 0
    for fluid, x in flow[3].items():
        if x > err:
            pp = flow[1] * x / (molar_masses[fluid] * n)
            s_u += CPPSI('S', 'P', pp, 'T', T + d, fluid) * x
            s_l += CPPSI('S', 'P', pp, 'T', T - d, fluid) * x

    return (s_u - s_l) / (2 * d)
Beispiel #3
0
def h_mix_pQ(flow, Q):
    """
    calculates enthalpy from pressure and quality

    .. note::

       This function works for pure fluids only!

    :param flow: vector containing [mass flow, pressure, enthalpy, fluid]
    :type flow: list
    :param Q: fraction of vapour mass to total mass in 1
    :type Q: numeric
    :returns: h (float) - enthalpy in J / kg
    """
    n = molar_massflow(flow[3])

    h = 0
    for fluid, x in flow[3].items():
        if x > err:
            pp = flow[1] * x / (molar_masses[fluid] * n)
            pcrit = CPPSI('Pcrit', fluid)
            while pp > pcrit:
                flow[1] = flow[1] * 0.95

            h += CPPSI('H', 'P', pp, 'Q', Q, fluid) * x

    return h
Beispiel #4
0
def h_ps(p, s, fluid):
    r"""
    Calculates the enthalpy from pressure and entropy for a pure fluid.

    Parameters
    ----------
    p : float
        Pressure p / Pa.

    s : float
        Specific entropy h / (J/(kgK)).

    fluid : str
        Fluid name.

    Returns
    -------
    h : float
        Specific enthalpy h / (J/kg).
    """
    #    if 'IDGAS::' in fluid:
    #        msg = 'Ideal gas calculation not available by now.'
    #        logging.warning(msg)
    if 'TESPy::' in fluid:
        db = tespy_fluid.fluids[fluid].funcs['s_pT']
        T = newton(reverse_2d, reverse_2d_deriv, [db, p, s], 0)
        return tespy_fluid.fluids[fluid].funcs['h_pT'].ev(p, T)
    elif 'INCOMP::' in fluid:
        return CPPSI('H', 'P', p, 'S', s, fluid)
    else:
        memorise.heos[fluid].update(CP.PSmass_INPUTS, p, s)
        return memorise.heos[fluid].hmass()
Beispiel #5
0
def visc_pT(p, T, fluid):
    r"""
    Calculates the dynamic viscosity from pressure and temperature for a pure
    fluid.

    Parameters
    ----------
    p : float
        Pressure p / Pa.

    T : float
        Temperature T / K.

    fluid : str
        Fluid name.

    Returns
    -------
    visc : float
        Viscosity visc / Pa s.
    """
    #    if 'IDGAS::' in fluid:
    #        msg = 'Ideal gas calculation not available by now.'
    #        logging.warning(msg)
    if 'TESPy::' in fluid:
        return tespy_fluid.fluids[fluid].funcs['visc_pT'].ev(p, T)
    elif 'INCOMP::' in fluid:
        return CPPSI('V', 'P', p, 'T', T, fluid)
    else:
        memorise.heos[fluid].update(CP.PT_INPUTS, p, T)
        return memorise.heos[fluid].viscosity()
Beispiel #6
0
def visc_mix_pT(flow, T):
    r"""
    calculates dynamic viscosity from pressure and temperature

    :param flow: vector containing [mass flow, pressure, enthalpy, fluid]
    :type flow: list
    :param T: temperature in K
    :type T: numeric
    :returns: v (float) - specific volume in kg / m :sup:`3`

    .. math::
        \eta_{mix}(p,T)=\frac{\sum_{i} \left( \eta(p,T,fluid_{i}) \cdot y_{i}
        \cdot M_{i} \right)}
        {\sum_{i} \left(y_{i} \cdot M_{i} \right)}\;
        \forall i \in \text{fluid components}\\
        y: \text{volume fraction}\\
        M: \text{molar mass}
    """
    n = molar_massflow(flow[3])

    a = 0
    b = 0
    for fluid, x in flow[3].items():
        if x > err:
            bi = x * math.sqrt(molar_masses[fluid]) / (molar_masses[fluid] * n)
            b += bi
            a += bi * CPPSI('V', 'P', flow[1], 'T', T, fluid)

    return a / b
Beispiel #7
0
def h_mix_pQ(flow, Q):
    r"""
    Calculates the enthalpy from pressure and vapour mass fraction.

    Parameters
    ----------
    flow : list
        Fluid property vector containing mass flow, pressure, enthalpy and
        fluid composition.

    Q : float
        Vapour mass fraction Q / 1.

    Returns
    -------
    h : float
        Specific enthalpy h / (J/kg).

    Note
    ----
    This function works for pure fluids only!
    """
    fluid = single_fluid(flow[3])
    if not isinstance(fluid, str):
        msg = 'The function h_mix_pQ can only be used for pure fluids.'
        logging.error(msg)
        raise ValueError(msg)

    pcrit = CPPSI('Pcrit', fluid)
    if flow[1] > pcrit:
        memorise.heos[fluid].update(CP.PQ_INPUTS, pcrit * 0.95, Q)
    else:
        memorise.heos[fluid].update(CP.PQ_INPUTS, flow[1], Q)

    return memorise.heos[fluid].hmass()
Beispiel #8
0
def T_bp_p(flow):
    r"""
    Calculates temperature from boiling point pressure.

    Parameters
    ----------
    flow : list
        Fluid property vector containing mass flow, pressure, enthalpy and
        fluid composition.

    Returns
    -------
    T : float
        Temperature at boiling point.

    Note
    ----
    This function works for pure fluids only!
    """
    for fluid, x in flow[3].items():
        if x > err:
            pcrit = CPPSI('Pcrit', fluid)
            if flow[1] > pcrit:
                memorise.heos[fluid].update(CP.PQ_INPUTS, pcrit * 0.95, 1)
            else:
                memorise.heos[fluid].update(CP.PQ_INPUTS, flow[1], 1)
            return memorise.heos[fluid].T()
Beispiel #9
0
def d_pT(p, T, fluid):
    r"""
    Calculates the density from pressure and temperature for a pure fluid.

    Parameters
    ----------
    p : float
        Pressure p / Pa.

    T : float
        Temperature T / K.

    fluid : str
        Fluid name.

    Returns
    -------
    d : float
        Density d / (kg/:math:`\mathrm{m}^3`).
    """
    #    if 'IDGAS::' in fluid:
    #        msg = 'Ideal gas calculation not available by now.'
    #        logging.warning(msg)
    if 'TESPy::' in fluid:
        return tespy_fluid.fluids[fluid].funcs['d_pT'].ev(p, T)
    elif 'INCOMP::' in fluid:
        return CPPSI('D', 'P', p, 'T', T, fluid)
    else:
        memorise.heos[fluid].update(CP.PT_INPUTS, p, T)
        return memorise.heos[fluid].rhomass()
Beispiel #10
0
def s_mix_pT(flow, T):
    r"""
    calculates entropy from pressure and temperature
    uses CoolProp reverse functions for pure fluids, newton for mixtures

    :param flow: vector containing [mass flow, pressure, enthalpy, fluid]
    :type flow: list
    :param T: temperature in K
    :type T: numeric
    :returns: s (float) - entropy in J / (kg * K)

    .. math::
        s_{mix}(p,T)=\sum_{i} x_{i} \cdot s(pp_{i},T,fluid_{i})-
        \sum_{i} x_{i} \cdot R_{i} \cdot \ln \frac{pp_{i}}{p}\;
        \forall i \in \text{fluid components}\\
        pp: \text{partial pressure}\\
        R: \text{gas constant}
    """
    n = molar_massflow(flow[3])

    s = 0
    for fluid, x in flow[3].items():
        if x > err:
            pp = flow[1] * x / (molar_masses[fluid] * n)
            s += CPPSI('S', 'P', pp, 'T', T, fluid) * x
            s -= (x * gas_constants[fluid] / molar_masses[fluid] *
                  math.log(pp / flow[1]))

    return s
Beispiel #11
0
def T_ph(p, h, fluid):
    r"""
    Calculates the temperature from pressure and enthalpy for a pure fluid.

    Parameters
    ----------
    p : float
        Pressure p / Pa.

    h : float
        Specific enthalpy h / (J/kg).

    fluid : str
        Fluid name.

    Returns
    -------
    T : float
        Temperature T / K.
    """
    #    if 'IDGAS::' in fluid:
    #        msg = 'Ideal gas calculation not available by now.'
    #        logging.warning(msg)
    if 'TESPy::' in fluid:
        db = tespy_fluid.fluids[fluid].funcs['h_pT']
        return newton(reverse_2d, reverse_2d_deriv, [db, p, h], 0)
    elif 'INCOMP::' in fluid:
        return CPPSI('T', 'P', p, 'H', h, fluid)
    else:
        memorise.heos[fluid].update(CP.HmassP_INPUTS, h, p)
        return memorise.heos[fluid].T()
Beispiel #12
0
def h_pT(p, T, fluid):
    r"""
    Calculates the enthalpy from pressure and temperature for a pure fluid.

    Parameters
    ----------
    p : float
        Pressure p / Pa.

    T : float
        Temperature T / K.

    fluid : str
        Fluid name.

    Returns
    -------
    h : float
        Specific enthalpy h / (J/kg).
    """
    #    if 'IDGAS::' in fluid:
    #        msg = 'Ideal gas calculation not available by now.'
    #        logging.warning(msg)
    if 'TESPy::' in fluid:
        return tespy_fluid.fluids[fluid].funcs['h_pT'].ev(p, T)
    elif 'INCOMP::' in fluid:
        return CPPSI('H', 'P', p, 'T', T, fluid)
    else:
        memorise.heos[fluid].update(CP.PT_INPUTS, p, T)
        return memorise.heos[fluid].hmass()
Beispiel #13
0
def visc_ph(p, h, fluid):
    r"""
    Calculates the dynamic viscosity from pressure and enthalpy for a pure
    fluid.

    Parameters
    ----------
    p : float
        Pressure p / Pa.

    h : float
        Specific enthalpy h / (J/kg).

    fluid : str
        Fluid name.

    Returns
    -------
    visc : float
        Viscosity visc / Pa s.
    """
    #    if 'IDGAS::' in fluid:
    #        msg = 'Ideal gas calculation not available by now.'
    #        logging.warning(msg)
    if 'TESPy::' in fluid:
        db = tespy_fluid.fluids[fluid].funcs['h_pT']
        T = newton(reverse_2d, reverse_2d_deriv, [db, p, h], 0)
        return tespy_fluid.fluids[fluid].funcs['visc_pT'].ev(p, T)
    elif 'INCOMP::' in fluid:
        return CPPSI('V', 'P', p, 'H', h, fluid)
    else:
        memorise.heos[fluid].update(CP.HmassP_INPUTS, h, p)
        return memorise.heos[fluid].viscosity()
Beispiel #14
0
def h_mix_pT(flow, T):
    r"""
    calculates enthalpy from pressure and temperature

    :param flow: vector containing [mass flow, pressure, enthalpy, fluid]
    :type flow: list
    :param T: temperature in K
    :type T: numeric
    :returns: h (float) - enthalpy in J / kg

    .. math::
        h_{mix}(p,T)=\sum_{i} h(pp_{i},T,fluid_{i})\;
        \forall i \in \text{fluid components}\\
        pp: \text{partial pressure}

    """

    n = molar_massflow(flow[3])

    h = 0
    for fluid, x in flow[3].items():
        if x > err:
            ni = x / molar_masses[fluid]
            h += CPPSI('H', 'P', flow[1] * ni / n, 'T', T, fluid) * x

    return h
Beispiel #15
0
def T_mix_ph(flow):
    r"""
    calculates the temperature from pressure and enthalpy,
    uses CoolProp reverse functions for pure fluids, newton for mixtures

    - check if property has already been memorised
    - calculate property otherwise

    :param flow: vector containing [mass flow, pressure, enthalpy, fluid]
    :type flow: list
    :returns: T (float) - temperature in K

    **fluid mixtures**

    .. math::

        T_{mix}\left(p,h\right) = T_{i}\left(pp_{i},h_{i}\right)\;
        \forall i \in \text{fluid components}\\

        h_{i} = h \left(pp_{i}, T_{mix} \right)\\
        pp: \text{partial pressure}

    """
    fl = tuple(sorted(list(flow[3].keys())))
    a = memorise.T_ph[fl][:, 0:-1]
    b = np.array([flow[1], flow[2]] + list(flow[3].values()))
    ix = np.where(np.all(abs(a - b) <= err**2, axis=1))[0]
    if ix.size == 1:
        T = memorise.T_ph[fl][ix, -1][0]
        memorise.T_ph_f[fl] += [T]
        return T
    else:
        if num_fluids(flow[3]) > 1:
            val = newton(h_mix_pT,
                         dh_mix_pdT,
                         flow,
                         flow[2],
                         val0=300,
                         valmin=70,
                         valmax=3000,
                         imax=10)
            new = np.array([[flow[1], flow[2]] + list(flow[3].values()) +
                            [val]])
            memorise.T_ph[fl] = np.append(memorise.T_ph[fl], new, axis=0)
            return val
        else:
            for fluid, x in flow[3].items():
                if x > err:
                    val = CPPSI('T', 'H', flow[2], 'P', flow[1], fluid)
                    new = np.array([[flow[1], flow[2]] +
                                    list(flow[3].values()) + [val]])
                    memorise.T_ph[fl] = np.append(memorise.T_ph[fl],
                                                  new,
                                                  axis=0)
                    return val
Beispiel #16
0
def T_mix_ps(flow, s):
    r"""
    calculates the temperature from pressure and entropy,
    uses CoolProp reverse functions for pure fluids, newton for mixtures

    :param flow: vector containing [mass flow, pressure, enthalpy, fluid]
    :type flow: list
    :param s: entropy in J / (kg * K)
    :type s: numeric
    :returns: T (float) - temperature in K

    **fluid mixtures**

    .. math::

        T_{mix}\left(p,s\right) = T_{i}\left(pp_{i},s_{i}\right)\;
        \forall i \in \text{fluid components}\\

        s_{i} = s \left(pp_{i}, T_{mix} \right)\\
        pp: \text{partial pressure}
    """
    fl = tuple(sorted(list(flow[3].keys())))
    a = memorise.T_ps[fl][:, 0:-1]
    b = np.array([flow[1], flow[2]] + list(flow[3].values()) + [s])
    ix = np.where(np.all(abs(a - b) <= err**2, axis=1))[0]
    if ix.size == 1:
        T = memorise.T_ps[fl][ix, -1][0]
        memorise.T_ps_f[fl] += [T]
        return T
    else:
        if num_fluids(flow[3]) > 1:
            val = newton(s_mix_pT,
                         ds_mix_pdT,
                         flow,
                         s,
                         val0=300,
                         valmin=70,
                         valmax=3000,
                         imax=10)
            new = np.array([[flow[1], flow[2]] + list(flow[3].values()) +
                            [s, val]])
            memorise.T_ps[fl] = np.append(memorise.T_ps[fl], new, axis=0)
            return val
        else:
            for fluid, x in flow[3].items():
                if x > err:
                    val = CPPSI('T', 'S', s, 'P', flow[1], fluid)
                    new = np.array([[flow[1], flow[2]] +
                                    list(flow[3].values()) + [s, val]])
                    memorise.T_ps[fl] = np.append(memorise.T_ps[fl],
                                                  new,
                                                  axis=0)
                    return val
Beispiel #17
0
def h_pT(p, T, fluid):
    r"""
    returns the enthalpy of a pure fluid given pressure and temperature

    :param p: pressure
    :type p: float
    :param T: temperature
    :type T: float
    :param fluid: fluid alias
    :type fluid: str
    :returns: h (float) - enthalpy in J / kg
    """
    if 'IDGAS::' in fluid:
        print('Ideal gas calculation not available by now.')
    elif 'TESPy::' in fluid:
        return tespy_fluid.fluids[fluid].funcs['h_pT'].ev(p, T)
    else:
        return CPPSI('H', 'P', p, 'T', T, fluid)
Beispiel #18
0
def T_ps(p, s, fluid):
    r"""
    returns the temperature of a pure fluid given pressure and entropy

    :param p: pressure
    :type p: float
    :param s: entropy
    :type s: float
    :param fluid: fluid alias
    :type fluid: str
    :returns: T (float) - temperature in K
    """
    if 'IDGAS::' in fluid:
        print('Ideal gas calculation not available by now.')
    elif 'TESPy::' in fluid:
        db = tespy_fluid.fluids[fluid].funcs['s_pT']
        return newton(reverse_2d, reverse_2d_deriv, [db, p, s], 0)
    else:
        return CPPSI('T', 'P', p, 'S', s, fluid)
Beispiel #19
0
def visc_pT(p, T, fluid):
    r"""
    returns the dynamic viscosity of a pure fluid given pressure and
    temperature

    :param p: pressure
    :type p: float
    :param T: temperature
    :type T: float
    :param fluid: fluid alias
    :type fluid: str
    :returns: visc (float) - dynamic viscosity in Pa s
    """
    if 'IDGAS::' in fluid:
        print('Ideal gas calculation not available by now.')
    elif 'TESPy::' in fluid:
        return tespy_fluid.fluids[fluid].funcs['visc_pT'].ev(p, T)
    else:
        return CPPSI('V', 'P', p, 'T', T, fluid)
Beispiel #20
0
def molar_massflow(flow):
    r"""
    calculates molar massflow

    :param flow: vector containing [mass flow, pressure, enthalpy, fluid]
    :type flow: list
    :returns: mm (float) - molar massflow in mol / s

    .. math::
        mm = \sum_{i} \left( \frac{x_{i}}{M_{i}} \right)
    """
    mm = 0
    for fluid, x in flow.items():
        if x > err:
            try:
                mm += x / molar_masses[fluid]
            except:
                mm += x / CPPSI('molar_mass', fluid)

    return mm
Beispiel #21
0
def visc_ph(p, h, fluid):
    r"""
    returns the dynamic viscosity of a pure fluid given pressure and enthalpy

    :param p: pressure
    :type p: float
    :param h: enthalpy
    :type h: float
    :param fluid: fluid alias
    :type fluid: str
    :returns: visc (float) - dynamic viscosity in Pa s
    """
    if 'IDGAS::' in fluid:
        print('Ideal gas calculation not available by now.')
    elif 'TESPy::' in fluid:
        db = tespy_fluid.fluids[fluid].funcs['h_pT']
        T = newton(reverse_2d, reverse_2d_deriv, [db, p, h], 0)
        return tespy_fluid.fluids[fluid].funcs['visc_pT'].ev(p, T)
    else:
        return CPPSI('V', 'P', p, 'H', h, fluid)
Beispiel #22
0
def h_ps(p, s, fluid):
    r"""
    returns the enthalpy of a pure fluid given pressure and entropy

    :param p: pressure
    :type p: float
    :param s: entropy
    :type s: float
    :param fluid: fluid alias
    :type fluid: str
    :returns: h (float) - enthalpy in J / kg
    """
    if 'IDGAS::' in fluid:
        print('Ideal gas calculation not available by now.')
    elif 'TESPy::' in fluid:
        db = tespy_fluid.fluids[fluid].funcs['s_pT']
        T = newton(reverse_2d, reverse_2d_deriv, [db, p, s], 0)
        return tespy_fluid.fluids[fluid].funcs['h_pT'].ev(p, T)
    else:
        return CPPSI('H', 'P', p, 'S', s, fluid)
Beispiel #23
0
def visc_mix_ph(flow):
    r"""
    calculates dynamic viscosity from pressure and enthalpy,
    uses CoolProp reverse functions for pure fluids, newton for mixtures

    :param flow: vector containing [mass flow, pressure, enthalpy, fluid]
    :type flow: list
    :returns: v (float) - specific volume in Pa s

    **fluid mixtures**

    .. math::

        \eta_{mix}\left(p,h\right) = \eta\left(p,T_{mix}(p,h)\right)
    """
    fl = tuple(sorted(list(flow[3].keys())))
    a = memorise.visc_ph[fl][:, 0:-1]
    b = np.array([flow[1], flow[2]] + list(flow[3].values()))
    ix = np.where(np.all(abs(a - b) <= err**2, axis=1))[0]
    if ix.size == 1:
        visc = memorise.visc_ph[fl][ix, -1][0]
        memorise.visc_ph_f[fl] += [visc]
        return visc
    else:
        if num_fluids(flow[3]) > 1:
            val = visc_mix_pT(flow, T_mix_ph(flow))
            new = np.array([[flow[1], flow[2]] + list(flow[3].values()) +
                            [val]])
            memorise.visc_ph[fl] = np.append(memorise.visc_ph[fl], new, axis=0)
            return val
        else:
            for fluid, x in flow[3].items():
                if x > err:
                    val = CPPSI('V', 'P', flow[1], 'H', flow[2], fluid)
                    new = np.array([[flow[1], flow[2]] +
                                    list(flow[3].values()) + [val]])
                    memorise.visc_ph[fl] = np.append(memorise.visc_ph[fl],
                                                     new,
                                                     axis=0)
                    return val
Beispiel #24
0
def s_mix_ph(flow):
    r"""
    calculates entropy from pressure and enthalpy
    uses CoolProp reverse functions for pure fluids, newton for mixtures

    :param flow: vector containing [mass flow, pressure, enthalpy, fluid]
    :type flow: list
    :returns: s (float) - entropy in J / (kg * K)

    **fluid mixtures**

    .. math::

        s_{mix}\left(p,h\right) = s\left(p,T_{mix}(p,h)\right)
    """
    fl = tuple(sorted(list(flow[3].keys())))
    a = memorise.s_ph[fl][:, 0:-1]
    b = np.array([flow[1], flow[2]] + list(flow[3].values()))
    ix = np.where(np.all(abs(a - b) <= err**2, axis=1))[0]
    if ix.size == 1:
        s = memorise.s_ph[fl][ix, -1][0]
        memorise.s_ph_f[fl] += [s]
        return s
    else:
        if num_fluids(flow[3]) > 1:
            val = s_mix_pT(flow, T_mix_ph(flow))
            new = np.array([[flow[1], flow[2]] + list(flow[3].values()) +
                            [val]])
            memorise.s_ph[fl] = np.append(memorise.s_ph[fl], new, axis=0)
            return val
        else:
            for fluid, x in flow[3].items():
                if x > err:
                    val = CPPSI('S', 'P', flow[1], 'H', flow[2], fluid)
                    new = np.array([[flow[1], flow[2]] +
                                    list(flow[3].values()) + [val]])
                    memorise.s_ph[fl] = np.append(memorise.s_ph[fl],
                                                  new,
                                                  axis=0)
                    return val
Beispiel #25
0
def v_mix_pT(flow, T):
    r"""
    calculates specific volume from pressure and temperature

    :param flow: vector containing [mass flow, pressure, enthalpy, fluid]
    :type flow: list
    :param T: temperature in K
    :type T: numeric
    :returns: v (float) - specific volume in kg / m :sup:`3`

    .. math::
        v_{mix}(p,T)=\sum_{i} v(pp_{i},T,fluid_{i})\;
        \forall i \in \text{fluid components}\\
        pp: \text{partial pressure}
    """
    n = molar_massflow(flow[3])

    d = 0
    for fluid, x in flow[3].items():
        if x > err:
            pp = flow[1] * x / (molar_masses[fluid] * n)
            d += CPPSI('D', 'P', pp, 'T', T, fluid) * x

    return 1 / d
Beispiel #26
0
    def add_fluids(fluids, memorise_fluid_properties=True):
        r"""
        Add list of fluids to fluid memorisation class.

        - Generate arrays for fluid property lookup if memorisation is
          activated.
        - Calculate/set fluid property value ranges for convergence checks.

        Parameters
        ----------
        fluids : dict
            Dict of fluid and corresponding CoolProp back end for fluid
            property memorization.

        memorise_fluid_properties : boolean
            Activate or deactivate fluid property value memorisation. Default
            state is activated (:code:`True`).

        Note
        ----
        The Memorise class creates globally accessible variables for different
        fluid property calls as dictionaries:

        - T(p,h)
        - T(p,s)
        - v(p,h)
        - visc(p,h)
        - s(p,h)

        Each dictionary uses the list of fluids passed to the Memorise class as
        identifier for the fluid property memorisation. The fluid properties
        are stored as numpy array, where each column represents the mass
        fraction of the respective fluid and the additional columns are the
        values for the fluid properties. The fluid property function will then
        look for identical fluid property inputs (p, h, (s), fluid mass
        fraction). If the inputs are in the array, the first column of that row
        is returned, see example.

        Example
        -------
        T(p,h) for set of fluids ('water', 'air'):

        - row 1: [282.64527752319697, 10000, 40000, 1, 0]
        - row 2: [284.3140698256616, 10000, 47000, 1, 0]
        """
        # number of fluids
        num_fl = len(fluids)
        if memorise_fluid_properties and num_fl > 0:
            fl = tuple(fluids.keys())
            # fluid property tables
            Memorise.T_ph[fl] = np.empty((0, num_fl + 4), float)
            Memorise.T_ps[fl] = np.empty((0, num_fl + 5), float)
            Memorise.v_ph[fl] = np.empty((0, num_fl + 4), float)
            Memorise.visc_ph[fl] = np.empty((0, num_fl + 4), float)
            Memorise.s_ph[fl] = np.empty((0, num_fl + 4), float)

            msg = (
                'Added fluids ' + ', '.join(fl) +
                ' to memorise lookup tables.')
            logging.debug(msg)

        Memorise.water = None
        for f, back_end in fluids.items():

            # save name for water in memorise
            if f in get_aliases("H2O"):
                Memorise.water = f

            if f in Memorise.state:
                del Memorise.state[f]

            # create CoolProp.AbstractState object
            try:
                Memorise.state[f] = CP.AbstractState(back_end, f)
                Memorise.back_end[f] = back_end
            except ValueError:
                msg = (
                    'Could not find the fluid "' + f + '" in the fluid '
                    'property database.'
                )
                logging.warning(msg)
                continue

            msg = (
                'Created CoolProp.AbstractState object for fluid ' +
                f + ' with back end ' + back_end + '.')
            logging.debug(msg)
            # pressure range
            try:
                pmin = Memorise.state[f].trivial_keyed_output(CP.iP_min)
                pmax = Memorise.state[f].trivial_keyed_output(CP.iP_max)
            except ValueError:
                pmin = 1e4
                pmax = 1e8
                msg = (
                    'Could not find values for maximum and minimum '
                    'pressure.')
                logging.warning(msg)

            # temperature range
            Tmin = Memorise.state[f].trivial_keyed_output(CP.iT_min)
            Tmax = Memorise.state[f].trivial_keyed_output(CP.iT_max)

            # value range for fluid properties
            Memorise.value_range[f] = [pmin, pmax, Tmin, Tmax]

            try:
                molar_masses[f] = Memorise.state[f].molar_mass()
                gas_constants[f] = Memorise.state[f].gas_constant()
            except ValueError:
                try:
                    molar_masses[f] = CPPSI('M', f)
                    gas_constants[f] = CPPSI('GAS_CONSTANT', f)
                except ValueError:
                    molar_masses[f] = 1
                    gas_constants[f] = 1
                    msg = (
                        'Could not find values for molar mass and gas '
                        'constant.')
                    logging.warning(msg)

            msg = (
                'Specifying fluid property ranges for pressure and '
                'temperature for convergence check of fluid ' + f + '.')
            logging.debug(msg)
Beispiel #27
0
    def __init__(self, alias, fluid, p_range, T_range, **kwargs):

        if not hasattr(tespy_fluid, 'fluids'):
            tespy_fluid.fluids = {}

        if not isinstance(alias, str):
            msg = 'Alias must be of type String.'
            raise TypeError(msg)

        if 'IDGAS::' in alias:
            msg = 'You are not allowed to use "IDGAS::" within your alias.'
            raise ValueError(msg)

        # process parameters
        if 'TESPy::' in alias:
            self.alias = alias
        else:
            self.alias = 'TESPy::' + alias
        self.fluid = fluid

        # load LUT from this path
        self.path = kwargs.get('path', dc_cp())

        # adjust value ranges according to specified unit system
        self.p_range = np.array(p_range)
        self.T_range = np.array(T_range)

        # set up grid
        self.p = np.linspace(self.p_range[0], self.p_range[1])
        self.T = np.linspace(self.T_range[0], self.T_range[1])

        # plotting
        self.plot = kwargs.get('plot', False)

        # calculate molar mass and gas constant
        for f in self.fluid:
            molar_masses[f] = CPPSI('M', f)
            gas_constants[f] = CPPSI('GAS_CONSTANT', f)

        molar_masses[self.alias] = 1 / molar_massflow(self.fluid)
        gas_constants[self.alias] = (gas_constants['uni'] /
                                     molar_masses[self.alias])

        # create look up tables
        tespy_fluid.fluids[self.alias] = {}

        params = {}

        params['h_pT'] = h_mix_pT
        params['s_pT'] = s_mix_pT
        params['d_pT'] = d_mix_pT
        params['visc_pT'] = visc_mix_pT

        self.funcs = {}

        if not self.path.is_set:

            for key in params.keys():

                self.funcs[key] = self.generate_lookup(key, params[key])

        else:

            for key in params.keys():
                self.funcs[key] = self.load_lookup(key)

        tespy_fluid.fluids[self.alias] = self

        print('Successfully created LUTs for custom fluid ' + self.alias)
Beispiel #28
0
    def add_fluids(fluids):
        r"""
        Add list of fluids to fluid memorisation class.

        - Generate arrays for fluid property lookup.
        - Calculate/set fluid property value ranges for convergence checks.

        Parameters
        ----------
        fluids : dict
            Dict of fluid and corresponding CoolProp back end for fluid
            property memorization.

        Note
        ----
        The memorise class creates globally accessible variables for different
        fluid property calls as dictionaries:

        - T(p,h)
        - T(p,s)
        - v(p,h)
        - visc(p,h)
        - s(p,h)

        Each dictionary uses the list of fluids passed to the memorise class as
        identifier for the fluid property memorisation. The fluid properties
        are stored as numpy array, where each column represents the mass
        fraction of the respective fluid and the additional columns are the
        values for the fluid properties. The fluid property function will then
        look for identical fluid property inputs (p, h, (s), fluid mass
        fraction). If the inputs are in the array, the first column of that row
        is returned, see example.

        Example
        -------
        T(p,h) for set of fluids ('water', 'air'):

        - row 1: [282.64527752319697, 10000, 40000, 1, 0]
        - row 2: [284.3140698256616, 10000, 47000, 1, 0]
        """
        # number of fluids
        num_fl = len(fluids)
        if num_fl > 0:
            fl = tuple(fluids.keys())
            # fluid property tables
            memorise.T_ph[fl] = np.empty((0, num_fl + 3), float)
            memorise.T_ps[fl] = np.empty((0, num_fl + 4), float)
            memorise.v_ph[fl] = np.empty((0, num_fl + 3), float)
            memorise.visc_ph[fl] = np.empty((0, num_fl + 3), float)
            memorise.s_ph[fl] = np.empty((0, num_fl + 3), float)
            # lists for memory cache, values not in these lists will be deleted
            # from the table after every tespy.networks.network.solve call.
            memorise.T_ph_f[fl] = []
            memorise.T_ps_f[fl] = []
            memorise.v_ph_f[fl] = []
            memorise.visc_ph_f[fl] = []
            memorise.s_ph_f[fl] = []
            memorise.count = 0

            msg = 'Added fluids ' + str(fl) + ' to memorise lookup tables.'
            logging.debug(msg)

        for f, back_end in fluids.items():
            if back_end == 'IF97':
                msg = (
                    'Due to a bug in the IF97 CoolProp back end, it is not '
                    'possible to use this back end at the moment. For more '
                    'information see '
                    'https://github.com/CoolProp/CoolProp/issues/1918.')
                logging.error(msg)
                raise ValueError(msg)
            elif f not in memorise.state.keys() and back_end != 'TESPy':
                # create CoolProp.AbstractState object
                try:
                    memorise.state[f] = CP.AbstractState(back_end, f)
                except ValueError:
                    msg = (
                        'Could not find the fluid "' + f + '" in the fluid '
                        'property database. If you are using a stoichimetric '
                        'combustion chamber, this warning can be ignored in '
                        'case the fluid is your fuel, your flue gas or your '
                        'air.')
                    logging.warning(msg)
                    continue

                msg = (
                    'Created CoolProp.AbstractState object for fluid ' +
                    f + ' with back end ' + back_end + '.')
                logging.debug(msg)
                # pressure range
                try:
                    pmin = memorise.state[f].trivial_keyed_output(CP.iP_min)
                    pmax = memorise.state[f].trivial_keyed_output(CP.iP_max)
                except ValueError:
                    pmin = 1e4
                    pmax = 1e8
                    msg = (
                        'Could not find values for maximum and minimum '
                        'pressure.')
                    logging.warning(msg)

                # temperature range
                Tmin = memorise.state[f].trivial_keyed_output(CP.iT_min)
                Tmax = memorise.state[f].trivial_keyed_output(CP.iT_max)

                # value range for fluid properties
                memorise.value_range[f] = [pmin, pmax, Tmin, Tmax]

                try:
                    molar_masses[f] = memorise.state[f].molar_mass()
                    gas_constants[f] = memorise.state[f].gas_constant()
                except ValueError:
                    try:
                        molar_masses[f] = CPPSI('M', f)
                        gas_constants[f] = CPPSI('GAS_CONSTANT', f)
                    except ValueError:
                        molar_masses[f] = 1
                        gas_constants[f] = 1
                        msg = (
                            'Could not find values for molar mass and gas '
                            'constant.')
                        logging.warning(msg)

                msg = (
                    'Specifying fluid property ranges for pressure and '
                    'temperature for convergence check of fluid ' + f + '.')
                logging.debug(msg)

            elif back_end == 'TESPy':
                pmin = tespy_fluid.fluids[f].p[0]
                pmax = tespy_fluid.fluids[f].p[-1]
                Tmin = tespy_fluid.fluids[f].T[0]
                Tmax = tespy_fluid.fluids[f].T[-1]
                msg = (
                    'Loading fluid property ranges for TESPy-fluid ' + f + '.')
                logging.debug(msg)
                # value range for fluid properties
                memorise.value_range[f] = [pmin, pmax, Tmin, Tmax]
                molar_masses[f] = 1 / molar_mass_flow(
                    tespy_fluid.fluids[f].fluid)
                gas_constants[f] = (
                    gas_constants['uni'] / molar_masses[f])
                msg = ('Specifying fluid property ranges for pressure and '
                       'temperature for convergence check.')
                logging.debug(msg)
Beispiel #29
0
    def add_fluids(fluids):
        r"""
        Add list of fluids to fluid memorisation class.

        - Generate arrays for fluid property lookup.
        - Calculate/set fluid property value ranges for convergence checks.

        Parameters
        ----------
        fluids : list
            List of fluid for fluid property memorization.

        Note
        ----
        The memorise class creates globally accessible variables for different
        fluid property calls as dictionaries:

            - T(p,h)
            - T(p,s)
            - v(p,h)
            - visc(p,h)
            - s(p,h)

        Each dictionary uses the list of fluids passed to the memorise class as
        identifier for the fluid property memorisation. The fluid properties
        are stored as numpy array, where each column represents the mass
        fraction of the respective fluid and the additional columns are the
        values for the fluid properties. The fluid property function will then
        look for identical fluid property inputs (p, h, (s), fluid mass
        fraction). If the inputs are in the array, the first column of that row
        is returned, see example.

        Example
        -------
        T(p,h) for set of fluids ('water', 'air'):

            - row 1: [282.64527752319697, 10000, 40000, 1, 0]
            - row 2: [284.3140698256616, 10000, 47000, 1, 0]
        """
        # number of fluids
        num_fl = len(fluids)
        if num_fl > 0:
            fl = tuple(fluids)
            # fluid property tables
            memorise.T_ph[fl] = np.empty((0, num_fl + 3), float)
            memorise.T_ps[fl] = np.empty((0, num_fl + 4), float)
            memorise.v_ph[fl] = np.empty((0, num_fl + 3), float)
            memorise.visc_ph[fl] = np.empty((0, num_fl + 3), float)
            memorise.s_ph[fl] = np.empty((0, num_fl + 3), float)
            # lists for memory cache, values not in these lists will be deleted
            # from the table after every tespy.networks.network.solve call.
            memorise.T_ph_f[fl] = []
            memorise.T_ps_f[fl] = []
            memorise.v_ph_f[fl] = []
            memorise.visc_ph_f[fl] = []
            memorise.s_ph_f[fl] = []
            memorise.count = 0

            msg = 'Added fluids ' + str(fl) + ' to memorise lookup tables.'
            logging.debug(msg)

        for f in fluids:
            if 'TESPy::' in f:
                if f in tespy_fluid.fluids.keys():
                    pmin = tespy_fluid.fluids[f].p_range[0]
                    pmax = tespy_fluid.fluids[f].p_range[1]
                    Tmin = tespy_fluid.fluids[f].T_range[0]
                    Tmax = tespy_fluid.fluids[f].T_range[1]
                    msg = ('Loading fluid property ranges for TESPy-fluid ' +
                           f + '.')
                    logging.debug(msg)
                    # value range for fluid properties
                    memorise.vrange[f] = [pmin, pmax, Tmin, Tmax]
                    msg = ('Specifying fluid property ranges for pressure and '
                           'temperature for convergence check.')
                    logging.debug(msg)
                else:
                    memorise.vrange[f] = [2000, 2000000, 300, 2000]

            elif 'INCOMP::' in f:
                # temperature range available only for incompressibles
                Tmin, Tmax = CPPSI('TMIN', f), CPPSI('TMAX', f)
                memorise.vrange[f] = [2000, 2000000, Tmin, Tmax]

            else:
                if f not in memorise.heos.keys():
                    # abstractstate object
                    memorise.heos[f] = CP.AbstractState('HEOS', f)
                    msg = ('Created CoolProp.AbstractState object for fluid ' +
                           f + ' in memorise class.')
                    logging.debug(msg)
                    # pressure range
                    pmin, pmax = CPPSI('PMIN', f), CPPSI('PMAX', f)
                    # temperature range
                    Tmin, Tmax = CPPSI('TMIN', f), CPPSI('TMAX', f)
                    # value range for fluid properties
                    memorise.vrange[f] = [pmin, pmax, Tmin, Tmax]
                    msg = ('Specifying fluid property ranges for pressure and '
                           'temperature for convergence check of fluid ' + f +
                           '.')
                    logging.debug(msg)
Beispiel #30
0
    def __init__(self, alias, fluid, p_range, T_range, path=None, plot=False):

        if not isinstance(alias, str):
            msg = 'Alias must be of type String.'
            logging.error(msg)
            raise TypeError(msg)

        if 'IDGAS::' in alias:
            msg = 'You are not allowed to use "IDGAS::" within your alias.'
            logging.error(msg)
            raise ValueError(msg)

        # process parameters
        if 'TESPy::' in alias:
            self.alias = alias
        else:
            self.alias = 'TESPy::' + alias
        self.fluid = fluid

        # adjust value ranges according to specified unit system
        self.p_range = np.array(p_range)
        self.T_range = np.array(T_range)

        # set up grid
        self.p = np.linspace(self.p_range[0], self.p_range[1])
        self.T = np.linspace(self.T_range[0], self.T_range[1])

        # plotting
        self.plot = plot

        # path for loading
        self.path = path

        # calculate molar mass and gas constant
        for f in self.fluid:
            molar_masses[f] = CPPSI('M', f)
            gas_constants[f] = CPPSI('GAS_CONSTANT', f)

        molar_masses[self.alias] = 1 / molar_mass_flow(self.fluid)
        gas_constants[self.alias] = (gas_constants['uni'] /
                                     molar_masses[self.alias])

        # create look up tables
        tespy_fluid.fluids[self.alias] = {}
        memorise.add_fluids(self.fluid.keys())

        params = {}

        params['h_pT'] = h_mix_pT
        params['s_pT'] = s_mix_pT
        params['d_pT'] = d_mix_pT
        params['visc_pT'] = visc_mix_pT

        self.funcs = {}

        if self.path is None:
            # generate fluid properties
            msg = 'Generating lookup-tables from CoolProp fluid properties.'
            logging.debug(msg)
            for key in params.keys():
                self.funcs[key] = self.generate_lookup(key, params[key])
                msg = 'Loading function values for function ' + key + '.'
                logging.debug(msg)

        else:
            # load fluid properties from specified path
            msg = ('Generating lookup-tables from base path ' + self.path +
                   '/' + self.alias + '/.')
            logging.debug(msg)
            for key in params.keys():
                self.funcs[key] = self.load_lookup(key)
                msg = 'Loading function values for function ' + key + '.'
                logging.debug(msg)

        tespy_fluid.fluids[self.alias] = self

        msg = ('Successfully created look-up-tables for custom fluid ' +
               self.alias + '.')
        logging.debug(msg)