Beispiel #1
0
def T_ph(p, h, fluid):
    r"""
    Calculate 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 fluid in tespy_fluid.fluids.keys():
        db = tespy_fluid.fluids[fluid].funcs['h_pT']
        return newton(reverse_2d, reverse_2d_deriv, [db, p, h], 0)
    else:
        memorise.state[fluid].update(CP.HmassP_INPUTS, h, p)
        return memorise.state[fluid].T()
Beispiel #2
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 #3
0
def h_ps(p, s, fluid):
    r"""
    Calculate 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 fluid in tespy_fluid.fluids.keys():
        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:
        memorise.state[fluid].update(CP.PSmass_INPUTS, p, s)
        return memorise.state[fluid].hmass()
Beispiel #4
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 #5
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 #6
0
    def calc_bus_expr(self, bus):
        r"""
        Return the busses' characteristic line input expression.

        Parameters
        ----------
        bus : tespy.connections.bus.Bus
            Bus to calculate the characteristic function expression for.

        Returns
        -------
        expr : float
            Ratio of power to power design depending on the bus base
            specification.
        """
        b = bus.comps.loc[self]
        if np.isnan(b['P_ref']) or b['P_ref'] == 0:
            return 1
        else:
            comp_val = self.bus_func(b)
            if b['base'] == 'component':
                return abs(comp_val / b['P_ref'])
            else:
                bus_value = newton(
                    bus_char_evaluation,
                    bus_char_derivative,
                    [comp_val, b['P_ref'], b['char']], 0,
                    val0=b['P_ref'], valmin=-1e15, valmax=1e15)
                return bus_value / b['P_ref']
Beispiel #7
0
def visc_ph(p, h, fluid):
    r"""
    Calculate 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 fluid in tespy_fluid.fluids.keys():
        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:
        memorise.state[fluid].update(CP.HmassP_INPUTS, h, p)
        return memorise.state[fluid].viscosity()
Beispiel #8
0
def d_ph(p, h, fluid):
    r"""
    Calculate the density 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
    -------
    d : float
        Density d / (kg/:math:`\mathrm{m}^3`).
    """
    if fluid in tespy_fluid.fluids.keys():
        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['d_pT'].ev(p, T)
    else:
        memorise.state[fluid].update(CP.HmassP_INPUTS, h, p)
        return memorise.state[fluid].rhomass()
Beispiel #9
0
def T_ps(p, s, fluid):
    r"""
    Calculate the temperature 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
    -------
    T : float
       Temperature T / K.
    """
    if fluid in tespy_fluid.fluids.keys():
        db = tespy_fluid.fluids[fluid].funcs['s_pT']
        return newton(reverse_2d, reverse_2d_deriv, [db, p, s], 0)
    else:
        memorise.state[fluid].update(CP.PSmass_INPUTS, p, s)
        return memorise.state[fluid].T()
Beispiel #10
0
    def calc_bus_value(self, bus):
        r"""
        Return the busses' value of the component's energy transfer.

        Parameters
        ----------
        bus : tespy.connections.bus
            Bus to calculate energy transfer on.

        Returns
        -------
        bus_value : float
            Value of the energy transfer on the specified bus.

            .. math::

                \dot{E}_\mathrm{bus} = \begin{cases}
                \frac{\dot{E}_\mathrm{component}}{f\left(
                \frac{\dot{E}_\mathrm{bus}}{\dot{E}_\mathrm{bus,ref}}\right)} &
                \text{bus base = 'bus'}\\
                \dot{E}_\mathrm{component} \cdot f\left(
                \frac{\dot{E}_\mathrm{component}}
                {\dot{E}_\mathrm{component,ref}}\right) &
                \text{bus base = 'component'}
                \end{cases}

        Note
        ----
        If the base value of the bus is the bus value itself, a newton
        iteration is used to find the bus value satisfying the corresponding
        equation (case 1).
        """
        b = bus.comps.loc[self]
        comp_val = self.bus_func(b)
        if np.isnan(b['P_ref']):
            expr = 1
        else:
            if b['base'] == 'component':
                expr = abs(comp_val / b['P_ref'])
            else:
                bus_value = newton(bus_char_evaluation,
                                   bus_char_derivative,
                                   [comp_val, b['P_ref'], b['char']],
                                   0,
                                   val0=b['P_ref'],
                                   valmin=-1e15,
                                   valmax=1e15)
                return bus_value

        if b['base'] == 'component':
            return comp_val * b['char'].evaluate(expr)
        else:
            return comp_val / b['char'].evaluate(expr)
Beispiel #11
0
    def calc_bus_efficiency(self, bus):
        r"""
        Return the busses' efficiency.

        Parameters
        ----------
        bus : tespy.connections.bus
            Bus to calculate the efficiency value on.

        Returns
        -------
        efficiency : float
            Efficiency value of the bus.

            .. math::

                \eta_\mathrm{bus} = \begin{cases}
                \eta\left(
                \frac{\dot{E}_\mathrm{bus}}{\dot{E}_\mathrm{bus,ref}}\right) &
                \text{bus base = 'bus'}\\
                \eta\left(
                \frac{\dot{E}_\mathrm{component}}
                {\dot{E}_\mathrm{component,ref}}\right) &
                \text{bus base = 'component'}
                \end{cases}

        Note
        ----
        If the base value of the bus is the bus value itself, a newton
        iteration is used to find the bus value satisfying the corresponding
        equation (case 1).
        """
        b = bus.comps.loc[self]
        comp_val = self.bus_func(b)
        if np.isnan(b['P_ref']):
            expr = 1
        else:
            if b['base'] == 'component':
                expr = abs(comp_val / b['P_ref'])
            else:
                bus_value = newton(bus_char_evaluation,
                                   bus_char_derivative,
                                   [comp_val, b['P_ref'], b['char']],
                                   0,
                                   val0=b['P_ref'],
                                   valmin=-1e15,
                                   valmax=1e15)
                expr = bus_value / b['P_ref']

        return b['char'].evaluate(expr)
Beispiel #12
0
def test_newton_bounds():
    """
    Test newton algorithm value limit handling.

    Try to calculate a zero crossing of a quadratic function in three
    tries.

    - zero crossing within limits, starting value near 4
    - zero crossing within limits, starting value near -5

    - zero crossing below minimum
    - zero crossing above maximum

    The function is x^2 + x - 20, there crossings are -5 and 4.
    """
    result = newton(func, deriv, [], 0, valmin=-10, valmax=10, val0=0)
    msg = ('The newton algorithm should find the zero crossing at 4.0. ' +
           str(round(result, 1)) + ' was found instead.')
    eq_(4.0, result, msg)

    result = newton(func, deriv, [], 0, valmin=-10, valmax=10, val0=-10)
    msg = ('The newton algorithm should find the zero crossing at -5.0. ' +
           str(round(result, 1)) + ' was found instead.')
    eq_(-5.0, result, msg)

    result = newton(func, deriv, [], 0, valmin=-4, valmax=-2, val0=-3)
    msg = ('The newton algorithm should not be able to find a zero crossing. '
           'The value ' + str(round(result, 1)) + ' was found, but the '
           'algorithm should have found the lower boundary of -4.0.')
    eq_(-4.0, result, msg)

    result = newton(func, deriv, [], 0, valmin=-20, valmax=-10, val0=-10)
    msg = ('The newton algorithm should not be able to find a zero crossing. '
           'The value ' + str(round(result, 1)) + ' was found, but the '
           'algorithm should have found the upper boundary of -10.0.')
    eq_(-10.0, result, msg)
Beispiel #13
0
def entropy_iteration_IF97(p, h, fluid, output):
    r"""
    Calculate state in IF97 back-end via entropy iteration.

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

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

    fluid : str
        Fluid name.

    Returns
    -------
    T : float
        Temperature T / K.
    """
    # region 1 exclusive issue!
    Memorise.state[fluid].update(CP.HmassP_INPUTS, h, p)
    if p <= 16.529164252605 * 1e6:
        h_at_ph = Memorise.state[fluid].hmass()
        deviation = abs(h_at_ph - h)
        if deviation / h > 0.001:
            # region 1, where isenthalpic lines are tangent to saturation dome
            if p > 1e6 and p < 1e7 and h > 2700000 and h < 2850000:
                smin = 5750
                smax = 6500
            # bottom left corner in Ts diagram
            elif h < 10000:
                smin = 0
                smax = 50
            else:
                # proximity to saturated liquid
                Memorise.state[fluid].update(CP.PQ_INPUTS, p, 0)
                h_sat_l = Memorise.state[fluid].hmass()
                if abs(h - h_sat_l) / h_sat_l < 1e-1:
                    if p < 1000:
                        smin = 0
                    elif p < 60000:
                        smin = Memorise.state[fluid].smass() * 0.9
                    else:
                        smin = Memorise.state[fluid].smass() * 0.95

                    Memorise.state[fluid].update(CP.PQ_INPUTS, p, 0.3)
                    smax = Memorise.state[fluid].smass()
                # all others
                else:
                    Memorise.state[fluid].update(CP.HmassP_INPUTS, h, p)
                    s0 = Memorise.state[fluid].smass()
                    smin = 0.8 * s0
                    smax = 1.2 * s0

            s0 = (smax + smin) / 2
            s = newton(func=h_ps_IF97, deriv=dh_pds_IF97, params=[fluid, p],
                       y=h, val0=s0, valmin=smin, valmax=smax, max_iter=5,
                       tol_rel=1e-3, tol_mode='rel')
            Memorise.state[fluid].update(CP.PSmass_INPUTS, p, s)

    if output == 'T':
        return Memorise.state[fluid].T()
    elif output == 's':
        return Memorise.state[fluid].smass()
    elif output == 'rho':
        return Memorise.state[fluid].rhomass()
    else:
        return Memorise.state[fluid].viscosity()
Beispiel #14
0
def T_mix_ps(flow, s, T0=300):
    r"""
    Calculates the temperature from pressure and entropy.

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

    s : float
        Entropy of flow in J / (kgK).

    Returns
    -------
    T : float
        Temperature T / K.

    Note
    ----
    First, check if fluid property has been memorised already.
    If this is the case, return stored value, otherwise calculate value and
    store it in the memorisation class.

    Uses CoolProp interface for pure fluids, newton algorithm for mixtures:

    .. math::

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

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

    """
    # check if fluid properties have been calculated before
    fl = tuple(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, axis=1))[0]
    if ix.size == 1:
        # known fluid properties
        T = memorise.T_ps[fl][ix, -1][0]
        memorise.T_ps_f[fl] += [T]
        return T
    else:
        # unknown fluid properties
        if num_fluids(flow[3]) > 1:
            # calculate the fluid properties for fluid mixtures
            if T0 < 70:
                T0 = 300
            val = newton(s_mix_pT,
                         ds_mix_pdT,
                         flow,
                         s,
                         val0=T0,
                         valmin=70,
                         valmax=3000,
                         imax=10)
            new = np.array([[flow[1], flow[2]] + list(flow[3].values()) +
                            [s, val]])
            # memorise the newly calculated value
            memorise.T_ps[fl] = np.append(memorise.T_ps[fl], new, axis=0)
            return val
        else:
            # calculate fluid property for pure fluids
            msg = ('The calculation of temperature from pressure and entropy '
                   'for pure fluids should not be required, as the '
                   'calculation is always possible from pressure and '
                   'enthalpy. If there is a case, where you need to calculate '
                   'temperature from these properties, please inform us: '
                   'https://github.com/oemof/tespy.')
            logging.error(msg)
            raise ValueError(msg)
Beispiel #15
0
def T_mix_ph(flow, T0=300):
    r"""
    Calculates the temperature from pressure and enthalpy.

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

    Returns
    -------
    T : float
        Temperature T / K.

    Note
    ----
    First, check if fluid property has been memorised already.
    If this is the case, return stored value, otherwise calculate value and
    store it in the memorisation class.

    Uses CoolProp interface for pure fluids, newton algorithm for mixtures:

    .. math::

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

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

    """
    # check if fluid properties have been calculated before
    fl = tuple(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, axis=1))[0]

    if ix.size == 1:
        # known fluid properties
        T = memorise.T_ph[fl][ix, -1][0]
        memorise.T_ph_f[fl] += [T]
        return T
    else:
        # unknown fluid properties
        if num_fluids(flow[3]) > 1:
            # calculate the fluid properties for fluid mixtures
            if T0 < 70:
                T0 = 300
            val = newton(h_mix_pT,
                         dh_mix_pdT,
                         flow,
                         flow[2],
                         val0=T0,
                         valmin=70,
                         valmax=3000,
                         imax=10)
            new = np.array([[flow[1], flow[2]] + list(flow[3].values()) +
                            [val]])
            # memorise the newly calculated value
            memorise.T_ph[fl] = np.append(memorise.T_ph[fl], new, axis=0)
            return val
        else:
            # calculate fluid property for pure fluids
            for fluid, x in flow[3].items():
                if x > err:
                    val = T_ph(flow[1], flow[2], fluid)
                    new = np.array([[flow[1], flow[2]] +
                                    list(flow[3].values()) + [val]])
                    # memorise the newly calculated value
                    memorise.T_ph[fl] = np.append(memorise.T_ph[fl],
                                                  new,
                                                  axis=0)
                    return val
Beispiel #16
0
def T_mix_ph(flow, T0=675):
    r"""
    Calculate the temperature from pressure and enthalpy.

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

    Returns
    -------
    T : float
        Temperature T / K.

    Note
    ----
    First, check if fluid property has been memorised already.
    If this is the case, return stored value, otherwise calculate value and
    store it in the memorisation class.

    Uses CoolProp interface for pure fluids, newton algorithm for mixtures:

    .. math::

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

        h_{i} = h \left(pp_{i}, T_{mix} \right)\\
        pp: \text{partial pressure}
    """
    # check if fluid properties have been calculated before
    fl = tuple(flow[3].keys())
    memorisation = fl in Memorise.T_ph
    if memorisation:
        a = Memorise.T_ph[fl][:, :-2]
        b = np.array([flow[1], flow[2]] + list(flow[3].values()))
        ix = np.where(np.all(abs(a - b) <= err, axis=1))[0]

        if ix.size == 1:
            # known fluid properties
            Memorise.T_ph[fl][ix, -1] += 1
            return Memorise.T_ph[fl][ix, -2][0]

    # unknown fluid properties
    fluid = single_fluid(flow[3])
    if fluid is None:
        # calculate the fluid properties for fluid mixtures
        valmin = max(
            [Memorise.value_range[f][2] for f in fl if flow[3][f] > err]
        ) + 0.1
        if T0 < valmin or np.isnan(T0):
            T0 = valmin * 1.1

        val = newton(h_mix_pT, dh_mix_pdT, flow, flow[2], val0=T0,
                     valmin=valmin, valmax=3000, imax=10)
    else:
        # calculate fluid property for pure fluids
        val = T_ph(flow[1], flow[2], fluid)

    if memorisation:
        # memorise the newly calculated value
        new = np.asarray(
            [[flow[1], flow[2]] + list(flow[3].values()) + [val, 0]])
        Memorise.T_ph[fl] = np.append(Memorise.T_ph[fl], new, axis=0)

    return val
Beispiel #17
0
def T_mix_ps(flow, s, T0=300):
    r"""
    Calculate the temperature from pressure and entropy.

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

    s : float
        Entropy of flow in J / (kgK).

    Returns
    -------
    T : float
        Temperature T / K.

    Note
    ----
    First, check if fluid property has been memorised already.
    If this is the case, return stored value, otherwise calculate value and
    store it in the memorisation class.

    Uses CoolProp interface for pure fluids, newton algorithm for mixtures:

    .. math::

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

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

    """
    # check if fluid properties have been calculated before
    fl = tuple(flow[3].keys())
    memorisation = fl in memorise.T_ps.keys()
    if memorisation is True:
        a = memorise.T_ps[fl][:, :-1]
        b = np.asarray([flow[1], flow[2]] + list(flow[3].values()) + [s])
        ix = np.where(np.all(abs(a - b) <= err, axis=1))[0]
        if ix.size == 1:
            # known fluid properties
            T = memorise.T_ps[fl][ix, -1][0]
            memorise.T_ps_f[fl] += [T]
            return T

    # unknown fluid properties
    fluid = single_fluid(flow[3])
    if fluid is None:
        # calculate the fluid properties for fluid mixtures
        if memorisation is True:
            valmin = max(
                [memorise.value_range[f][2]
                 for f in fl if flow[3][f] > err]) + 0.1
            if T0 < valmin or np.isnan(T0):
                T0 = valmin * 1.1
        else:
            valmin = 70

        val = newton(s_mix_pT,
                     ds_mix_pdT,
                     flow,
                     s,
                     val0=T0,
                     valmin=valmin,
                     valmax=3000,
                     imax=10)

    else:
        # calculate fluid property for pure fluids
        val = T_ps(flow[1], s, fluid)

    if memorisation is True:
        new = np.asarray([[flow[1], flow[2]] + list(flow[3].values()) +
                          [s, val]])
        # memorise the newly calculated value
        memorise.T_ps[fl] = np.append(memorise.T_ps[fl], new, axis=0)

    return val