Ejemplo n.º 1
0
def run_one_level(net, level):
    """

    """
    g = top.graphs_by_level_as_dict(net)[level]

    gas = Chemical("natural gas", T=net.T_GRND, P=net.LEVELS[level])
    loads = _scaled_loads_as_dict(net)
    p_ops = _operating_pressures_as_dict(net)

    p_nodes_i, m_dot_pipes_i, m_dot_nodes_i, gas = run_linear(net, level)
    x0 = np.concatenate((p_nodes_i, m_dot_pipes_i, m_dot_nodes_i))
    x0 = np.clip(x0, a_min=1e-1, a_max=None)
    x0 *= np.random.normal(loc=1, scale=0.1, size=len(x0))

    i_mat = create_incidence(g)

    leng = np.array([data["L_m"] for _, _, data in g.edges(data=True)])
    diam = np.array([data["D_m"] for _, _, data in g.edges(data=True)])

    materials = np.array([data["mat"] for _, _, data in g.edges(data=True)])
    eps = np.array([fluids.material_roughness(m) for m in materials])

    res = fsolve(_eq_model,
                 x0,
                 args=(i_mat, g, leng, diam, eps, gas, loads, p_ops, gas.P))

    p_nodes = res[:len(g.nodes)] * gas.P
    m_dot_pipes = res[len(g.nodes):len(g.nodes) + len(g.edges)] * M_DOT_REF
    m_dot_nodes = res[len(g.nodes) + len(g.edges):] * M_DOT_REF

    return p_nodes, m_dot_pipes, m_dot_nodes, gas
Ejemplo n.º 2
0
    def multiply_pressure_matrix_to_check(self):

        self.res_check = 0

        # check for pressure conservation for each level
        sorted_levels = sorted(self.net.levels.items(),
                               key=operator.itemgetter(1))
        for level, value in sorted_levels:
            if level in self.net.bus["level"].unique():

                # get network
                self.level = level
                netnx = self.net.netnx_all[level]
                level_value = self.net.levels[level]
                fluid_type = Chemical("natural gas",
                                      T=self.net.temperature,
                                      P=level_value + self.net.p_atm)

                # get network component for this level (not all component just part of it)
                self._compute_i_mat()
                self.bus_level = self.net.bus.loc[self.net.bus['level'] ==
                                                  level, :]
                self.load_level = self.net.load.loc[
                    self.net.load["bus"].isin(self.bus_level.index), :]
                self._scaled_loads()
                self._create_node_mass()

                # get data for this level
                materials = self.net.get_data_by_edge(level, "mat")
                roughness = np.array(
                    [fluids.material_roughness(m) for m in materials])
                leng = self.net.get_data_by_edge(level, "L_m")
                diam = self.net.get_data_by_edge(level, "D_m")
                name_pipe = self.net.get_data_by_edge(level, "name")
                m_dot_pipes = self.net.res_pipe.loc[name_pipe,
                                                    "m_dot_kg/s"].values
                p_nodes = self.net.res_bus.loc[np.array(netnx.nodes),
                                               "p_Pa"].values

                # make the matrix multiplication (should be null)
                self._i_mat_for_pressure()
                p_loss = _dp_from_m_dot_vec(m_dot_pipes, leng, diam, roughness,
                                            fluid_type) * (-1)
                p_loss = np.append(p_loss,
                                   [level_value] * len(self.ind_feeder))
                self.res_check += sum(self.mat_pres.dot(p_nodes) - p_loss)
Ejemplo n.º 3
0
def _run_sim(net, level="BP", t_grnd=10 + 273.15):
    g = top.graphs_by_level_as_dict(net)[level]

    gas = Chemical('natural gas', T=t_grnd, P=net.LEVELS[level])
    material = fluids.nearest_material_roughness('steel', clean=True)
    eps = fluids.material_roughness(material)

    x0 = _init_variables(g, net.LEVELS[level])
    i_mat = _i_mat(g)

    leng = np.array([data["L_m"] for _, _, data in g.edges(data=True)])
    diam = np.array([data["D_m"] for _, _, data in g.edges(data=True)])

    load = _scaled_loads_as_dict(net)
    p_nom = _p_nom_feed_as_dict(net)

    logging.debug("SIM {}".format(level))
    logging.debug("LOADS {}".format(load))
    logging.debug("P_NOM {}".format(p_nom))

    res = fsolve(_eq_model,
                 x0,
                 args=(i_mat, g, leng, diam, eps, gas, load, p_nom))

    p_nodes = np.round(res[:len(g.nodes)], 1)
    m_dot_pipes = np.round(res[len(g.nodes):len(g.nodes) + len(g.edges)], 6)
    m_dot_nodes = np.round(res[len(g.nodes) + len(g.edges):], 6)

    p_nodes = {n: p_nodes[i] for i, n in enumerate(g.nodes)}
    m_dot_pipes = {
        data["name"]: m_dot_pipes[i]
        for i, (_, _, data) in enumerate(g.edges(data=True))
    }
    m_dot_nodes = {n: m_dot_nodes[i] for i, n in enumerate(g.nodes)}

    return p_nodes, m_dot_pipes, m_dot_nodes, gas
Ejemplo n.º 4
0
def test_dp_from_m_dot():
    gas = Chemical('natural gas', T=10 + 273.15, P=4.5E5)
    material = fluids.nearest_material_roughness('steel', clean=True)
    eps = fluids.material_roughness(material)
    assert round(
        sim._dp_from_m_dot_vec(0.005, 100, 0.05, eps, gas).tolist(), 1) == 61.8
Ejemplo n.º 5
0
    def run_sim_by_level(self, level):
        """
        computes the gas simulation for one pressure level.

        :param level: the considered pressure level
        :return: a pandasgas network
        """

        # gas parameter
        self.level = level
        level_value = self.net.levels[level]
        fluid_type = Chemical("natural gas",
                              T=self.net.temperature,
                              P=level_value * self.net.corr_pnom +
                              self.net.p_atm)

        # select network component for this pressure level
        self._select_component_for_this_level()

        # get the data by edge for this level
        materials = self.net.get_data_by_edge(level, "mat")
        roughness = np.array([fluids.material_roughness(m) for m in materials])
        leng = self.net.get_data_by_edge(level, "L_m")
        diam = self.net.get_data_by_edge(level, "D_m")

        # add load (with the load linked to a station of a lower pressure level) and give these masses to the nodes
        self._scaled_loads()
        m_dot_nodes = self._create_node_mass()

        # compute incidence matrix (so a matrix which says which node are connected to which edge)
        self._compute_i_mat()
        row0 = self.i_mat.shape[0]
        col0 = self.i_mat.shape[1]
        if self.net.solver_option['disp']:
            print('incidence matrix: done.')

        # modify i_mat so that the unknown linked with the solver are on the left side of the "equation"
        self._i_mat_with_feeder()

        # get null space for the mass (so that the space with all possible solutions form the matrix)
        self._qr_null()
        nullity_mass = self.z_i_mat.shape[1]  # how many freedom degrees

        # get one solution to the equation representing mass conservation
        res = lsqr(self.mat_mass,
                   m_dot_nodes,
                   atol=self.net.solver_option['tol_mat_mass'],
                   btol=self.net.solver_option['tol_mat_mass'])
        sol0 = res[0]
        if self.net.solver_option['disp']:
            print('find null space for the mass equation: done.')

        # obtain the pseudo inverse matrix for the pressure equation (so the matrix which find the closest solution)
        self._i_mat_for_pressure()
        pinv_pres = pinv(self.mat_pres)
        p_noms = [level_value] * len(self.ind_feeder)
        if self.net.solver_option['disp']:
            print(
                'find pseudo-inverse matrix for the pressure equation: done.')

        # if we have more than one possibility as solution, minimize
        if nullity_mass > 0:
            m0 = np.random.rand(nullity_mass)
            args_mass = (self.z_i_mat, sol0, self.net.v_max, diam, row0, col0,
                         leng, roughness, fluid_type, pinv_pres, p_noms,
                         self.mat_pres, self.mat_mass, m_dot_nodes,
                         self.net.solver_option)
            options = {
                'maxiter': self.net.solver_option['maxiter'],
                'disp': self.net.solver_option['disp']
            }
            _compute_mass_and_pres.niter = 0  # attach a variable to a function

            # As we have more than on solution for the masss equation, we test many of them to find the one choice
            #  which fits the pressure equation.
            res = minimize(_compute_mass_and_pres,
                           m0,
                           method='SLSQP',
                           args=args_mass,
                           options=options)
            # all solution are the  "basic" solution + residual, cf. linear algebra.
            sol = sol0 + self.z_i_mat.dot(res.x)
        else:
            sol = sol0

        # separate the result
        m_dot_pipes = sol[:col0]
        m_dot_nodes[self.ind_feeder] = sol[col0:]

        # compute load and velocity
        v, load_pipes = self._v_from_m_dot(diam, m_dot_pipes, fluid_type)

        # compute pressure
        p_loss = _dp_from_m_dot_vec(m_dot_pipes, leng, diam, roughness,
                                    fluid_type) * (-1)
        p_loss = np.append(p_loss, p_noms)
        p_nodes = pinv_pres.dot(p_loss)
        if nullity_mass > 0 and self.net.solver_option['disp']:
            _print_minimize_state(p_nodes, res.fun,
                                  _compute_mass_and_pres.niter)

        # transfer output to self.net
        self._transfer_output_to_net(p_nodes, m_dot_nodes, v, load_pipes,
                                     m_dot_pipes)