Ejemplo n.º 1
0
    def convergence_check(self):
        r"""
        Perform a convergence check.

        Note
        ----
        Manipulate enthalpies/pressure at inlet and outlet if not specified by
        user to match physically feasible constraints.
        """
        i, o = self.inl, self.outl

        if not o[0].p.val_set and o[0].p.val_SI < i[0].p.val_SI:
            o[0].p.val_SI = o[0].p.val_SI * 2
        if not i[0].p.val_set and o[0].p.val_SI < i[0].p.val_SI:
            i[0].p.val_SI = o[0].p.val_SI * 0.5

        if not o[0].h.val_set and o[0].h.val_SI < i[0].h.val_SI:
            o[0].h.val_SI = o[0].h.val_SI * 1.1
        if not i[0].h.val_set and o[0].h.val_SI < i[0].h.val_SI:
            i[0].h.val_SI = o[0].h.val_SI * 0.9

        if self.flow_char.is_set:
            expr = i[0].m.val_SI * v_mix_ph(i[0].get_flow(), T0=i[0].T.val_SI)

            if expr > self.flow_char.char_func.x[-1] and not i[0].m.val_set:
                i[0].m.val_SI = (self.flow_char.char_func.x[-1] /
                                 v_mix_ph(i[0].get_flow(), T0=i[0].T.val_SI))
            elif expr < self.flow_char.char_func.x[1] and not i[0].m.val_set:
                i[0].m.val_SI = (self.flow_char.char_func.x[0] /
                                 v_mix_ph(i[0].get_flow(), T0=i[0].T.val_SI))
            else:
                pass
Ejemplo n.º 2
0
    def get_char_expr(self, param, type='rel', inconn=0, outconn=0):
        r"""
        Generic method to access characteristic function parameters.

        Parameters
        ----------
        param : str
            Parameter for characteristic function evaluation.

        type : str
            Type of expression:

            - :code:`rel`: relative to design value
            - :code:`abs`: absolute value

        inconn : int
            Index of inlet connection.

        outconn : int
            Index of outlet connection.

        Returns
        -------
        expr : float
            Value of expression
        """
        if type == 'rel':
            if param == 'm':
                return (self.inl[inconn].m.val_SI / self.inl[inconn].m.design)
            elif param == 'm_out':
                return (self.outl[outconn].m.val_SI /
                        self.outl[outconn].m.design)
            elif param == 'v':
                v = self.inl[inconn].m.val_SI * v_mix_ph(
                    self.inl[inconn].get_flow(), T0=self.inl[inconn].T.val_SI)
                return v / self.inl[inconn].v.design
            elif param == 'pr':
                return (
                    (self.outl[outconn].p.val_SI * self.inl[inconn].p.design) /
                    (self.inl[inconn].p.val_SI * self.outl[outconn].p.design))
            else:
                msg = ('The parameter ' + str(param) + ' is not available '
                       'for characteristic function evaluation.')
                logging.error(msg)
                raise ValueError(msg)
        else:
            if param == 'm':
                return self.inl[inconn].m.val_SI
            elif param == 'm_out':
                return self.outl[outconn].m.val_SI
            elif param == 'v':
                return self.inl[inconn].m.val_SI * v_mix_ph(
                    self.inl[inconn].get_flow(), T0=self.inl[inconn].T.val_SI)
            elif param == 'pr':
                return (self.outl[outconn].p.val_SI /
                        self.inl[inconn].p.val_SI)
            else:
                return False
Ejemplo n.º 3
0
    def calc_parameters(self):
        r"""Postprocessing parameter calculation."""
        i = self.inl[0].to_flow()
        o = self.outl[0].to_flow()
        self.pr.val = o[1] / i[1]
        self.zeta.val = ((i[1] - o[1]) * np.pi ** 2 /
                         (8 * i[0] ** 2 * (v_mix_ph(i) + v_mix_ph(o)) / 2))
        self.Sirr.val = i[0] * (s_mix_ph(o) - s_mix_ph(i))

        self.check_parameter_bounds()
Ejemplo n.º 4
0
    def zeta_func(self, zeta='', inconn=0, outconn=0):
        r"""
        Calculate residual value of :math:`\zeta`-function.

        Parameters
        ----------
        zeta : str
            Component parameter to evaluate the zeta_func on, e. g.
            :code:`zeta1`.

        inconn : int
            Connection index of inlet.

        outconn : int
            Connection index of outlet.

        Returns
        -------
        val : float
            Residual value of function.

            .. math::

                val = \begin{cases}
                p_{in} - p_{out} & |\dot{m}| < \epsilon \\
                \frac{\zeta}{D^4} - \frac{(p_{in} - p_{out}) \cdot \pi^2}
                {8 \cdot \dot{m}_{in} \cdot |\dot{m}_{in}| \cdot \frac{v_{in} +
                v_{out}}{2}} &
                |\dot{m}| > \epsilon
                \end{cases}

        Note
        ----
        The zeta value is caluclated on the basis of a given pressure loss at
        a given flow rate in the design case. As the cross sectional area A
        will not change, it is possible to handle the equation in this way:

        .. math::

            \frac{\zeta}{D^4} = \frac{\Delta p \cdot \pi^2}
            {8 \cdot \dot{m}^2 \cdot v}
        """
        zeta = self.get_attr(zeta).val
        i = self.inl[inconn].to_flow()
        o = self.outl[outconn].to_flow()

        if abs(i[0]) < 1e-4:
            return i[1] - o[1]

        else:
            v_i = v_mix_ph(i, T0=self.inl[inconn].T.val_SI)
            v_o = v_mix_ph(o, T0=self.outl[outconn].T.val_SI)
            return (zeta - (i[1] - o[1]) * np.pi**2 / (8 * abs(i[0]) * i[0] *
                                                       (v_i + v_o) / 2))
Ejemplo n.º 5
0
    def cone_func(self):
        r"""
        Equation for stodolas cone law.

        Returns
        -------
        residual : float
            Residual value of equation.

            .. math::

                0 = \frac{\dot{m}_{in,ref} \cdot p_{in}}{p_{in,ref}} \cdot
                \sqrt{\frac{p_{in,ref} \cdot v_{in}}{p_{in} \cdot v_{in,ref}}}
                \cdot \sqrt{\frac{1 - \left(\frac{p_{out}}{p_{in}} \right)^{2}}
                {1 - \left(\frac{p_{out,ref}}{p_{in,ref}} \right)^{2}}} -
                \dot{m}_{in}
        """
        n = 1
        i = self.inl[0]
        o = self.outl[0]
        vol = v_mix_ph(i.get_flow(), T0=self.inl[0].T.val_SI)
        return (
            - i.m.val_SI + i.m.design * i.p.val_SI / i.p.design *
            np.sqrt(i.p.design * i.vol.design / (i.p.val_SI * vol)) *
            np.sqrt(abs((1 - (o.p.val_SI / i.p.val_SI) ** ((n + 1) / n)) /
                        (1 - (self.pr.design) ** ((n + 1) / n)))))
Ejemplo n.º 6
0
    def zeta_func(self):
        r"""
        Calculates residual value of :math:`\zeta`-function.

        Returns
        -------
        val : float
            Residual value of function.

            .. math::

                val = \begin{cases}
                p_{in} - p_{out} & |\dot{m}| < \epsilon \\
                \frac{\zeta}{D^4} - \frac{(p_{in} - p_{out}) \cdot \pi^2}{8 \cdot
                \dot{m}_{in} \cdot |\dot{m}_{in}| \cdot \frac{v_{in} +
                v_{out}}{2}} &
                |\dot{m}| > \epsilon
                \end{cases}

        Note
        ----
        The zeta value is caluclated on the basis of a given pressure loss at
        a given flow rate in the design case. As the cross sectional area A
        will not change, it is possible to handle the equation in this way:

        .. math::

            \frac{\zeta}{D^4} = \frac{\Delta p \cdot \pi^2}
            {8 \cdot \dot{m}^2 \cdot v}
        """
        i = self.inl[0].to_flow()
        o = self.outl[0].to_flow()
        if hasattr(self, 'zeta'):
            val = self.zeta.val
        else:
            val = self.zeta1.val

        if abs(i[0]) < 1e-4:
            return i[1] - o[1]

        else:
            v_i = v_mix_ph(i, T0=self.inl[0].T.val_SI)
            v_o = v_mix_ph(o, T0=self.outl[0].T.val_SI)
            return (val - (i[1] - o[1]) * np.pi**2 / (8 * abs(i[0]) * i[0] *
                                                      (v_i + v_o) / 2))
Ejemplo n.º 7
0
    def calc_parameters(self):
        r"""Postprocessing parameter calculation."""
        self.Q.val = - self.inl[0].m.val_SI * (self.outl[0].h.val_SI -
                                               self.inl[0].h.val_SI)
        self.pr_c.val = self.outl[0].p.val_SI / self.inl[0].p.val_SI
        self.e.val = self.P.val / self.outl[2].m.val_SI
        self.eta.val = self.e0 / self.e.val

        i = self.inl[0].to_flow()
        o = self.outl[0].to_flow()
        self.zeta.val = ((i[1] - o[1]) * np.pi ** 2 /
                         (8 * i[0] ** 2 * (v_mix_ph(i) + v_mix_ph(o)) / 2))

        if self.eta_char.is_set:
            # get bound errors for efficiency characteristics
            expr = self.outl[2].m.val_SI / self.outl[2].m.design
            self.eta_char.func.get_bound_errors(expr, self.label)

        self.check_parameter_bounds()
Ejemplo n.º 8
0
    def hazen_williams_func(self):
        r"""
        Equation for pressure drop calculation from Hazen-Williams equation.

        Returns
        -------
        residual : float
            Residual value of equation.

            .. math::

                0 = \left(p_{in} - p_{out} \right) \cdot \left(-1\right)^i -
                \frac{10.67 \cdot |\dot{m}_{in}| ^ {1.852}
                \cdot L}{ks^{1.852} \cdot D^{4.871}} \cdot g \cdot
                \left(\frac{v_{in} + v_{out}}{2}\right)^{0.852}

                i = \begin{cases}
                0 & \dot{m}_{in} \geq 0\\
                1 & \dot{m}_{in} < 0
                \end{cases}

        Note
        ----
        Gravity :math:`g` is set to :math:`9.81 \frac{m}{s^2}`
        """
        i, o = self.inl[0].get_flow(), self.outl[0].get_flow()

        if abs(i[0]) < 1e-4:
            return i[1] - o[1]

        v_i = v_mix_ph(i, T0=self.inl[0].T.val_SI)
        v_o = v_mix_ph(o, T0=self.outl[0].T.val_SI)

        return ((i[1] - o[1]) * np.sign(i[0]) -
                (10.67 * abs(i[0])**1.852 * self.L.val /
                 (self.ks.val**1.852 * self.D.val**4.871)) *
                (9.81 * ((v_i + v_o) / 2)**0.852))
Ejemplo n.º 9
0
    def darcy_func(self):
        r"""
        Equation for pressure drop calculation from darcy friction factor.

        Returns
        -------
        residual : float
            Residual value of equation.

            .. math::

                0 = p_{in} - p_{out} - \frac{8 \cdot |\dot{m}_{in}| \cdot
                \dot{m}_{in} \cdot \frac{v_{in}+v_{out}}{2} \cdot L \cdot
                \lambda\left(Re, ks, D\right)}{\pi^2 \cdot D^5}\\

                Re = \frac{4 \cdot |\dot{m}_{in}|}{\pi \cdot D \cdot
                \frac{\eta_{in}+\eta_{out}}{2}}\\
                \eta: \text{dynamic viscosity}\\
                v: \text{specific volume}\\
                \lambda: \text{darcy friction factor}
        """
        i, o = self.inl[0].get_flow(), self.outl[0].get_flow()

        if abs(i[0]) < 1e-4:
            return i[1] - o[1]

        visc_i = visc_mix_ph(i, T0=self.inl[0].T.val_SI)
        visc_o = visc_mix_ph(o, T0=self.outl[0].T.val_SI)
        v_i = v_mix_ph(i, T0=self.inl[0].T.val_SI)
        v_o = v_mix_ph(o, T0=self.outl[0].T.val_SI)

        Re = 4 * abs(i[0]) / (np.pi * self.D.val * (visc_i + visc_o) / 2)

        return (
            (i[1] - o[1]) - 8 * abs(i[0]) * i[0] *
            (v_i + v_o) / 2 * self.L.val * dff(Re, self.ks.val, self.D.val) /
            (np.pi**2 * self.D.val**5))
Ejemplo n.º 10
0
    def calc_parameters(self):
        r"""Postprocessing parameter calculation."""
        # connection information
        i1 = self.inl[0].to_flow()
        i2 = self.inl[1].to_flow()
        i3 = self.inl[2].to_flow()
        o1 = self.outl[0].to_flow()
        o2 = self.outl[1].to_flow()
        o3 = self.outl[2].to_flow()

        # specific volume
        v_i1 = v_mix_ph(i1, T0=self.inl[0].T.val_SI)
        v_i2 = v_mix_ph(i2, T0=self.inl[1].T.val_SI)
        v_i3 = v_mix_ph(i3, T0=self.inl[2].T.val_SI)
        v_o1 = v_mix_ph(o1, T0=self.outl[0].T.val_SI)
        v_o2 = v_mix_ph(o2, T0=self.outl[1].T.val_SI)
        v_o3 = v_mix_ph(o3, T0=self.outl[2].T.val_SI)

        # specific entropy
        s_i1 = s_mix_ph(i1, T0=self.inl[0].T.val_SI)
        s_i2 = s_mix_ph(i2, T0=self.inl[1].T.val_SI)
        s_i3 = s_mix_ph(i3, T0=self.inl[2].T.val_SI)
        s_o1 = s_mix_ph(o1, T0=self.outl[0].T.val_SI)
        s_o2 = s_mix_ph(o2, T0=self.outl[1].T.val_SI)
        s_o3 = s_mix_ph(o3, T0=self.outl[2].T.val_SI)

        # component parameters
        self.Q.val = -i3[0] * (o3[2] - i3[2])

        self.pr1.val = o1[1] / i1[1]
        self.pr2.val = o2[1] / i2[1]
        self.pr3.val = o3[1] / i3[1]
        self.zeta1.val = ((i1[1] - o1[1]) * np.pi**2 / (8 * i1[0]**2 *
                                                        (v_i1 + v_o1) / 2))
        self.zeta2.val = ((i2[1] - o2[1]) * np.pi**2 / (8 * i2[0]**2 *
                                                        (v_i2 + v_o2) / 2))
        self.zeta3.val = ((i3[1] - o3[1]) * np.pi**2 / (8 * i3[0]**2 *
                                                        (v_i3 + v_o3) / 2))

        self.SQ1.val = self.inl[0].m.val_SI * (s_o1 - s_i1)
        self.SQ2.val = self.inl[1].m.val_SI * (s_o2 - s_i2)
        self.SQ3.val = self.inl[2].m.val_SI * (s_o3 - s_i3)
        self.Sirr.val = self.SQ1.val + self.SQ2.val + self.SQ3.val

        self.check_parameter_bounds()