Ejemplo n.º 1
0
def test_missing_gen():
    net = nw.case4gs()
    pp.rundcpp(net)
    res_gen = copy.deepcopy(net.res_gen.values)
    net.pop("res_gen")
    pp.rundcpp(net)
    assert np.allclose(net.res_gen.values, res_gen, equal_nan=True)
Ejemplo n.º 2
0
    def evaluate_run(self, run):
        """Procedure to evaluate a single run (hour).
        
        Parameters
        ----------
        run : int
            number of the evaluated run"""

        # copy network
        network = copy.deepcopy(self.network)

        # fetch run data
        sgen_run, load_run = self.regionalize_curves(network, run)

        # update network dataframe
        network.sgen.p_mw.update(sgen_run)
        network.load.p_mw.update(load_run)

        # set dcline direction
        network = self.direct_dclines(network, run)

        # evaluate loadflow
        pp.rundcpp(network)

        # evaluate the results of the run
        self.evaluate_run_result(network, run)
Ejemplo n.º 3
0
def test_PTDF():
    net = nw.case9()
    pp.rundcpp(net)
    _, ppci = _pd2ppc(net)

    ptdf = makePTDF(ppci["baseMVA"],
                    ppci["bus"],
                    ppci["branch"],
                    using_sparse_solver=False)
    _ = makePTDF(ppci["baseMVA"],
                 ppci["bus"],
                 ppci["branch"],
                 result_side=1,
                 using_sparse_solver=False)
    ptdf_sparse = makePTDF(ppci["baseMVA"],
                           ppci["bus"],
                           ppci["branch"],
                           using_sparse_solver=True)

    if not np.allclose(ptdf, ptdf_sparse):
        raise AssertionError(
            "Sparse PTDF has differenct result against dense PTDF")
    if not ptdf.shape == (ppci["bus"].shape[0], ppci["branch"].shape[0]):
        raise AssertionError("PTDF has wrong dimension")
    if not np.all(~np.isnan(ptdf)):
        raise AssertionError("PTDF has NaN value")
Ejemplo n.º 4
0
def test_isolated_gen_lookup():
    net=pp.create_empty_network()

    gen_bus=pp.create_bus(net,vn_kv=1., name='gen_bus')
    slack_bus=pp.create_bus(net,vn_kv=1., name='slack_bus')
    gen_iso_bus=pp.create_bus(net,vn_kv=1., name='iso_bus')

    pp.create_line(net, from_bus=slack_bus, to_bus=gen_bus, length_km=1, std_type="48-AL1/8-ST1A 10.0")

    pp.create_ext_grid(net, bus=slack_bus, vm_pu=1.)

    pp.create_gen(net, bus=gen_iso_bus, p_mw=1, vm_pu=1., name='iso_gen')
    pp.create_gen(net, bus=gen_bus, p_mw=1, vm_pu=1., name='oos_gen', in_service=False)
    pp.create_gen(net, bus=gen_bus, p_mw=2, vm_pu=1., name='gen')

    pp.rundcpp(net)
    assert np.allclose(net.res_gen.p_mw.values, [0, 0, 2])

    pp.runpp(net)
    assert np.allclose(net.res_gen.p_mw.values, [0, 0, 2])

    pp.create_xward(net, bus=gen_iso_bus, pz_mw=1., qz_mvar=1., ps_mw=1., qs_mvar=1.,
                    vm_pu=1., x_ohm=1., r_ohm=.1)
    pp.create_xward(net, bus=gen_bus, pz_mw=1., qz_mvar=1., ps_mw=1., qs_mvar=1.,
                    vm_pu=1., x_ohm=1., r_ohm=.1)
    pp.create_xward(net, bus=gen_iso_bus, pz_mw=1., qz_mvar=1., ps_mw=1., qs_mvar=1.,
                    vm_pu=1., x_ohm=1., r_ohm=.1, in_service=False)

    pp.rundcpp(net)
    assert np.allclose(net.res_gen.p_mw.values, [0, 0, 2])
    assert np.allclose(net.res_xward.p_mw.values, [0, 2, 0])

    pp.runpp(net)
    assert np.allclose(net.res_gen.p_mw.values, [0, 0, 2])
    assert np.allclose(net.res_xward.p_mw.values, [0, 2, 0])
Ejemplo n.º 5
0
def _get_bus_ppc_mapping(net, bus_to_be_fused):
    bus_with_elements = set(net.load.bus).union(set(net.sgen.bus)).union(
        set(net.shunt.bus)).union(set(net.gen.bus)).union(set(
            net.ext_grid.bus)).union(set(net.ward.bus)).union(
                set(net.xward.bus))
    # Run dc pp to get the ppc we need
    pp.rundcpp(net)

    bus_ppci = pd.DataFrame(data=net._pd2ppc_lookups['bus'],
                            columns=["bus_ppci"])
    bus_ppci['bus_with_elements'] = bus_ppci.index.isin(bus_with_elements)
    existed_bus = bus_ppci[bus_ppci.index.isin(net.bus.index)]
    bus_ppci['vn_kv'] = net.bus.loc[existed_bus.index, 'vn_kv']
    ppci_bus_with_elements = bus_ppci.groupby(
        'bus_ppci')['bus_with_elements'].sum()
    bus_ppci.loc[:, 'elements_in_cluster'] = ppci_bus_with_elements[
        bus_ppci['bus_ppci'].values].values
    bus_ppci['bus_to_be_fused'] = False
    if bus_to_be_fused is not None:
        bus_ppci.loc[bus_to_be_fused, 'bus_to_be_fused'] = True
        bus_cluster_to_be_fused_mask = bus_ppci.groupby(
            'bus_ppci')['bus_to_be_fused'].any()
        bus_ppci.loc[
            bus_cluster_to_be_fused_mask[bus_ppci['bus_ppci'].values].values,
            'bus_to_be_fused'] = True
    return bus_ppci
Ejemplo n.º 6
0
def test_ext_grid_gen_order_in_ppc():
    net = pp.create_empty_network()

    for b in range(6):
        pp.create_bus(net, vn_kv=1., name=b)

    for l_bus in range(0, 5, 2):
        pp.create_line(net,
                       from_bus=l_bus,
                       to_bus=l_bus + 1,
                       length_km=1,
                       std_type="48-AL1/8-ST1A 10.0")

    for slack_bus in [0, 2, 5]:
        pp.create_ext_grid(net, bus=slack_bus, vm_pu=1.)

    for gen_bus in [0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5]:
        pp.create_gen(net, bus=gen_bus, p_kw=-1, vm_pu=1.)

    pp.rundcpp(net)
    assert all(net.res_gen.p_kw == net.gen.p_kw)
    assert all(net.res_ext_grid.p_kw > 0)

    pp.runpp(net)
    assert all(net.res_gen.p_kw == net.gen.p_kw)
    assert all(net.res_ext_grid.p_kw > 0)
Ejemplo n.º 7
0
    def run_dc_power_flow(self):

        """
        Run a DC Power Flow for the network
        """

        pp.rundcpp(self.network)
        return
Ejemplo n.º 8
0
def test_LODF():
    net = nw.case9()
    pp.rundcpp(net)
    _, ppci = _pd2ppc(net)

    ptdf = makePTDF(ppci["baseMVA"], ppci["bus"], ppci["branch"])
    lodf = makeLODF(ppci["branch"], ptdf)
    if not lodf.shape == (ppci["branch"].shape[0], ppci["branch"].shape[0]):
        raise AssertionError("LODF has wrong dimension")
Ejemplo n.º 9
0
def test_rundcpp_init():
    net = pp.create_empty_network()
    b1, b2, l1 = add_grid_connection(net)
    b3 = pp.create_bus(net, vn_kv=0.4)
    tidx = pp.create_transformer(net,
                                 hv_bus=b2,
                                 lv_bus=b3,
                                 std_type="0.25 MVA 20/0.4 kV")
    pp.rundcpp(net)
Ejemplo n.º 10
0
 def init(self):
     if self.pf == 'pf':
         pp.runpp(self.network)
     elif self.pf == 'dcpf':
         pp.rundcpp(self.network)
     elif self.pf == 'opf':
         pp.runopp(self.network)
     else:
         pp.rundcopp(self.network)
Ejemplo n.º 11
0
def test_test_sn_mva():
    test_net_gen1 = result_test_network_generator_dcpp(sn_mva=1)
    test_net_gen2 = result_test_network_generator_dcpp(sn_mva=2)
    for net1, net2 in zip(test_net_gen1, test_net_gen2):
        pp.rundcpp(net1)
        pp.rundcpp(net2)
        try:
            assert_net_equal(net1, net2)
        except:
            raise UserWarning("Result difference due to sn_mva after adding %s" % net1.last_added_case)
Ejemplo n.º 12
0
def test_single_bus_network():
    net = pp.create_empty_network()
    b = pp.create_bus(net, vn_kv=20.)
    pp.create_ext_grid(net, b)

    pp.runpp(net)
    assert net.converged

    pp.rundcpp(net)
    assert net.converged
Ejemplo n.º 13
0
def test_two_open_switches():
    net = pp.create_empty_network()
    b1, b2, l1 = add_grid_connection(net)
    b3 = pp.create_bus(net, vn_kv=20.)
    l2 = create_test_line(net, b2, b3)
    create_test_line(net, b3, b1)
    pp.create_switch(net, b2, l2, et="l", closed=False)
    pp.create_switch(net, b3, l2, et="l", closed=False)
    pp.rundcpp(net)
    assert np.isnan(net.res_line.i_ka.at[l2]) or net.res_line.i_ka.at[l2] == 0
Ejemplo n.º 14
0
 def runpf(self, is_dc=False):
     """
     Now we just perform a powerflow with pandapower which can be done with either `rundcpp` for dc powerflow
     or with `runpp`for AC powerflow
     """
     try:
         with warnings.catch_warnings():
             # remove the warning if _grid non connex. And it that case load flow as not converged
             warnings.filterwarnings("ignore", category=scipy.sparse.linalg.MatrixRankWarning)
             warnings.filterwarnings("ignore", category=RuntimeWarning)
             if is_dc:
                 pp.rundcpp(self._grid, check_connectivity=False)
             else:
                 pp.runpp(self._grid, check_connectivity=False)
             return self._grid.converged
     except pp.powerflow.LoadflowNotConverged as exc_:
         # of the powerflow has not converged, results are Nan
         return False
Ejemplo n.º 15
0
def test_rundcpp_init_auxiliary_buses():
    net = pp.create_empty_network()
    b1, b2, l1 = add_grid_connection(net, vn_kv=110.)
    b3 = pp.create_bus(net, vn_kv=20.)
    b4 = pp.create_bus(net, vn_kv=10.)
    tidx = pp.create_transformer3w(net, b2, b3, b4, std_type='63/25/38 MVA 110/20/10 kV')
    pp.create_load(net, b3, p_mw=5)
    pp.create_load(net, b4, p_mw=5)
    pp.create_xward(net, b4, 1, 1, 1, 1, 0.1, 0.1, 1.0)
    net.trafo3w.shift_lv_degree.at[tidx] = 120
    net.trafo3w.shift_mv_degree.at[tidx] = 80
    pp.rundcpp(net)
    va = net.res_bus.va_degree.at[b2]
    pp.rundcpp(net)
    assert np.allclose(va - net.trafo3w.shift_mv_degree.at[tidx], net.res_bus.va_degree.at[b3],
                       atol=2)
    assert np.allclose(va - net.trafo3w.shift_lv_degree.at[tidx], net.res_bus.va_degree.at[b4],
                       atol=2)
Ejemplo n.º 16
0
 def step(self, *args, **kwargs):
     if self.pf == 'pf':
         a = pp.runpp(self.network)
     elif self.pf == 'dcpf':
         a = pp.rundcpp(self.network)
     elif self.pf == 'opf':
         a = pp.runopp(self.network)
     else:
         a = pp.rundcopp(self.network)
     return a
Ejemplo n.º 17
0
def assert_pf(net, dc=False):
    custom_file = os.path.join(os.path.abspath(os.path.dirname(pp.__file__)),
                               "opf", "run_powermodels_powerflow.jl")
    if dc:
        # see https://github.com/lanl-ansi/PowerModels.jl/issues/612 for details
        pp.runpm(net, julia_file=custom_file, pm_model="DCMPPowerModel")
    else:
        pp.runpm(net, julia_file=custom_file, pm_model="ACPPowerModel")

    va_pm = copy.copy(net.res_bus.va_degree)
    vm_pm = copy.copy(net.res_bus.vm_pu)

    if dc:
        pp.rundcpp(net, calculate_voltage_angles=True)
    else:
        pp.runpp(net, calculate_voltage_angles=True)
    va_pp = copy.copy(net.res_bus.va_degree)
    vm_pp = copy.copy(net.res_bus.vm_pu)

    assert np.allclose(va_pm, va_pp)
    if not dc:
        assert np.allclose(vm_pm, vm_pp)
Ejemplo n.º 18
0
    def runpf(self, is_dc=False):
        """
        Now we just perform a powerflow with pandapower which can be done with either `rundcpp` for dc powerflow
        or with `runpp` for AC powerflow.

        This is really a 2 lines code. It is a bit more verbose here because we took care of silencing some
        warnings and try / catch some possible exceptions.

        """
        try:
            with warnings.catch_warnings():
                # remove the warning if _grid non connex. And it that case load flow as not converged
                warnings.filterwarnings(
                    "ignore", category=scipy.sparse.linalg.MatrixRankWarning)
                warnings.filterwarnings("ignore", category=RuntimeWarning)
                if is_dc:
                    pp.rundcpp(self._grid, check_connectivity=False)
                else:
                    pp.runpp(self._grid, check_connectivity=False)
                return self._grid.converged, None
        except pp.powerflow.LoadflowNotConverged as exc_:
            # of the powerflow has not converged, results are Nan
            return False, exc_
Ejemplo n.º 19
0
def assert_pf(net, dc=False):
    if dc:
        model="DCMPPowerModel"
    else:
        model="ACPPowerModel"

    pp.runpm_pf(net, pm_model=model)

    va_pm = copy.deepcopy(net.res_bus.va_degree)
    vm_pm = copy.deepcopy(net.res_bus.vm_pu)

    if dc:
        pp.rundcpp(net, calculate_voltage_angles=True)
    else:
        pp.runpp(net, calculate_voltage_angles=True)

    va_pp = copy.deepcopy(net.res_bus.va_degree)
    vm_pp = copy.deepcopy(net.res_bus.vm_pu)

    assert np.allclose(va_pm, va_pp)

    if not dc:
        assert np.allclose(vm_pm, vm_pp)
Ejemplo n.º 20
0
def calc_sc_on_line(net, line_ix, distance_to_bus0, **kwargs):
    """
    Calculate the shortcircuit in the middle of the line, returns a modified network
    with the shortcircuit calculation results and the bus added

    INPUT:
        **net** - panpdapower net

        **line_ix** (int) - The line of the shortcircuit

        **distance_to_bus0** (float) - The position of the shortcircuit should be between 0-1

    OPTIONAL:
        **kwargs**** - the parameters required for the pandapower calc_sc function
    """
    # Update network
    aux_net, aux_bus = _create_aux_net(net, line_ix, distance_to_bus0)

    pp.rundcpp(aux_net)
    calc_sc(aux_net, bus=aux_bus, **kwargs)

    # Return the new net and the aux bus
    return aux_net, aux_bus
Ejemplo n.º 21
0
def test_isolated_gen_lookup():
    net = pp.create_empty_network()

    gen_bus = pp.create_bus(net, vn_kv=1., name='gen_bus')
    slack_bus = pp.create_bus(net, vn_kv=1., name='slack_bus')
    gen_iso_bus = pp.create_bus(net, vn_kv=1., name='iso_bus')

    pp.create_line(net,
                   from_bus=slack_bus,
                   to_bus=gen_bus,
                   length_km=1,
                   std_type="48-AL1/8-ST1A 10.0")

    pp.create_ext_grid(net, bus=slack_bus, vm_pu=1.)

    pp.create_gen(net, bus=gen_iso_bus, p_kw=-1, vm_pu=1., name='iso_gen')
    pp.create_gen(net, bus=gen_bus, p_kw=-2, vm_pu=1., name='gen')

    pp.rundcpp(net)
    assert net.res_gen.p_kw.values[1] == net.gen.p_kw.values[1]

    pp.runpp(net)
    assert net.res_gen.p_kw.values[1] == net.gen.p_kw.values[1]
Ejemplo n.º 22
0
def rundcpp_with_consistency_checks(net, **kwargs):
    pp.rundcpp(net, **kwargs)
    consistency_checks(net, test_q=False)
    return True
Ejemplo n.º 23
0
 def run_ref_pf(self, net):
     pp.rundcpp(net, init="flat")
Ejemplo n.º 24
0
    def runpf(self, is_dc=False):
        """
        Run a power flow on the underlying _grid. This implements an optimization of the powerflow
        computation: if the number of
        buses has not changed between two calls, the previous results are re used. This speeds up the computation
        in case of "do nothing" action applied.
        """
        # print("I called runpf")
        conv = True
        nb_bus = self.get_nb_active_bus()
        try:
            with warnings.catch_warnings():
                # remove the warning if _grid non connex. And it that case load flow as not converged
                warnings.filterwarnings(
                    "ignore", category=scipy.sparse.linalg.MatrixRankWarning)
                if nb_bus == self._nb_bus_before:
                    self._pf_init = "results"
                    init_vm_pu = "results"
                    init_va_degree = "results"
                else:
                    self._pf_init = "auto"
                    init_vm_pu = None
                    init_va_degree = None
                if is_dc:
                    pp.rundcpp(self._grid, check_connectivity=False)
                    self._nb_bus_before = None  # if dc i start normally next time i call an ac powerflow
                else:
                    pp.runpp(self._grid,
                             check_connectivity=False,
                             init=self._pf_init)
                    self._nb_bus_before = nb_bus

                if self._grid.res_gen.isnull().values.any():
                    # sometimes pandapower does not detect divergence and put Nan.
                    raise p.powerflow.LoadflowNotConverged

                # I retrieve the data once for the flows, so has to not re read multiple dataFrame
                self.p_or = self._aux_get_line_info("p_from_mw", "p_hv_mw")
                self.q_or = self._aux_get_line_info("q_from_mvar", "q_hv_mvar")
                self.v_or = self._aux_get_line_info("vm_from_pu", "vm_hv_pu")
                self.a_or = self._aux_get_line_info("i_from_ka",
                                                    "i_hv_ka") * 1000
                self.a_or[~np.isfinite(self.a_or)] = 0.

                self.p_ex = self._aux_get_line_info("p_to_mw", "p_lv_mw")
                self.q_ex = self._aux_get_line_info("q_to_mvar", "q_lv_mvar")
                self.v_ex = self._aux_get_line_info("vm_to_pu", "vm_lv_pu")
                self.a_ex = self._aux_get_line_info("i_to_ka",
                                                    "i_lv_ka") * 1000
                self.a_ex[~np.isfinite(self.a_ex)] = 0.

                self.v_or *= self.lines_or_pu_to_kv
                self.v_ex *= self.lines_ex_pu_to_kv

                return self._grid.converged

        except pp.powerflow.LoadflowNotConverged:
            # of the powerflow has not converged, results are Nan
            self.p_or = np.full(self.n_lines,
                                dtype=np.float,
                                fill_value=np.NaN)
            self.q_or = self.p_or
            self.v_or = self.p_or
            self.a_or = self.p_or
            self.p_ex = self.p_or
            self.q_ex = self.p_or
            self.v_ex = self.p_or
            self.a_ex = self.p_or
            self._nb_bus_before = None
            return False
Ejemplo n.º 25
0
def OPA_model(net, f_bus, f_gen, f_load, f_line, f_trafo):

    # This variable allows to stop the function when a total blackout situation is reached
    total_blackout = 0

    # Set failed elements as out of service.
    # In the case of failed buses, all the elements connected to the bus are also removed
    f_bus = list(f_bus)
    pp.set_element_status(net, f_bus, in_service=False)
    f_gen = list(f_gen)
    net.gen.loc[f_gen, 'in_service'] = False
    f_load = list(f_load)
    net.load.loc[f_load, 'in_service'] = False
    f_line = list(f_line)
    net.line.loc[f_line, 'in_service'] = False
    f_trafo = list(f_trafo)
    net.trafo.loc[f_trafo, 'in_service'] = False

    # Variable for entering in the while loop
    cascade = True

    # Store the initial power level of each generator

    intermediate_gen_power = dict(net.gen.loc[:, 'p_mw'])
    order_dict_gen = collections.OrderedDict(
        sorted(intermediate_gen_power.items()))
    intermediate_gen_power = list(order_dict_gen.values())

    intermediate_load_power = dict(net.load.loc[:, 'p_mw'])
    order_dict_load = collections.OrderedDict(
        sorted(intermediate_load_power.items()))
    intermediate_load_power = list(order_dict_load.values())

    while cascade == True:

        # Create a networkx graph of the power network
        G = pp.topology.create_nxgraph(net)
        # Create a list of sets containing the islands of the network
        list_islands = list(nx.connected_components(G))

        # Create a list of buses with generators in service
        list_bus_with_gen_in_service = list(
            net.gen.bus[net.gen.in_service == True])
        list_bus_with_gen_in_service = list(set(list_bus_with_gen_in_service))
        list_bus_with_gen_in_service.sort()
        list_bus_with_slack_gen_in_service = list(
            net.gen.bus[net.gen.in_service == True][net.gen.slack == True])

        # Check the configuration of each island in the power network
        for island in list_islands:
            #print(island)
            island = list(island)

            # Check if the island has an external grid. If yes, it is ok and you can proceed to the next island.
            # If no, check if there is an availabl generator in the island. If yes, turn it into an external grid.
            # If no, go to the next island.
            if set(list_bus_with_slack_gen_in_service).isdisjoint(island):
                if set(list_bus_with_gen_in_service).isdisjoint(island):
                    pass
                else:
                    set_island = set(island)
                    bus_with_gen_in_island = list(
                        set_island.intersection(list_bus_with_gen_in_service))
                    slack_gen = list(net.gen.index[net.gen.bus ==
                                                   bus_with_gen_in_island[0]])
                    net.gen.loc[slack_gen[0], 'slack'] = True
            else:
                pass

        # Set the isolated islands (without ext. grid/slack gen.) out of service
        pp.set_isolated_areas_out_of_service(net)

        # Try to run a DC OPF
        try:
            pp.rundcopp(net, verbose=False)
            # If it converges, save a the power level at each generators and ext grids
            intermediate_gen_power = dict(net.res_gen.loc[:, 'p_mw'])
            order_dict_gen = collections.OrderedDict(
                sorted(intermediate_gen_power.items()))
            intermediate_gen_power = list(order_dict_gen.values())

            intermediate_load_power = dict(net.res_load.loc[:, 'p_mw'])
            order_dict_load = collections.OrderedDict(
                sorted(intermediate_load_power.items()))
            intermediate_load_power = list(order_dict_load.values())

        # If the DC OPF does not converge, increase the loads costs
        # A while loop which decreases the loads costs until the DC OPF converges or the costs reach a value of 0
        except pp.OPFNotConverged:
            #print(f_line, f_bus, f_trafo)
            print('CONVERGENCE PROBLEMS')
            cost = 1
            load_cost = -100
            while cost == 1:
                load_cost += 2
                #print(load_cost)
                net.poly_cost.cp1_eur_per_mw[net.poly_cost.et ==
                                             'load'] = load_cost
                try:
                    pp.rundcopp(net)
                    #pp.rundcopp(net, SCPDIPM_RED_IT=100, PDIPM_COSTTOL = 1e-3, PDIPM_GRADTOL = 1e-3)
                    intermediate_gen_power = dict(net.res_gen.loc[:, 'p_mw'])
                    order_dict_gen = collections.OrderedDict(
                        sorted(intermediate_gen_power.items()))
                    intermediate_gen_power = list(order_dict_gen.values())

                    intermediate_load_power = dict(net.res_load.loc[:, 'p_mw'])
                    order_dict_load = collections.OrderedDict(
                        sorted(intermediate_load_power.items()))
                    intermediate_load_power = list(order_dict_load.values())

                    cost = 0
                except pp.OPFNotConverged:
                    pass
                # If the loads costs are set to 0, run a DC power flow with the last available generators power levels
                if load_cost == 0:
                    net.gen.loc[:, 'p_mw'] = intermediate_gen_power
                    net.load.loc[:, 'p_mw'] = intermediate_load_power
                    pp.rundcpp(net)
                    break

        # This is in case to generators is available (everything is failed basically)
        except UserWarning:
            total_blackout = 1
            break
        # If there is a total blackout situation, break the loop
        if total_blackout == 1:
            break

        # Create a list of lines still in service
        list_line_in_service = list(
            net.line.loc[net.line.in_service == True].index)
        list_line_in_service.sort()
        # This variable is to check if there are new failures due to overloads
        new_failure = 0
        for line in list_line_in_service:
            level_loading = net.res_line.loc[line, 'loading_percent']
            # If a line a loading >= the 99% of its maximum capacity, it is considered overloaded
            if level_loading >= 99:
                print('OVERLOADS')
                new_failure = 1
                net.line.loc[line, 'in_service'] = False

        # Same for transformer lines
        list_trafo_in_service = list(
            net.trafo.loc[net.trafo.in_service == True].index)
        list_trafo_in_service.sort()
        for trafo in list_trafo_in_service:
            level_loading = net.res_trafo.loc[trafo, 'loading_percent']
            if level_loading >= 99:
                print('OVERLOADS')
                new_failure = 1
                net.trafo.loc[trafo, 'in_service'] = False

        # If there are no overloads, break the while loop
        if new_failure == 0:
            break

    # Save the final power levels of each generator and load
    if total_blackout == 0:
        final_state_load = dict(net.res_load.loc[:, 'p_mw'])
        order_dict_load = collections.OrderedDict(
            sorted(final_state_load.items()))
        list_load_power = list(order_dict_load.values())

        final_state_gen = dict(net.res_gen.loc[:, 'p_mw'])
        order_dict_gen = collections.OrderedDict(
            sorted(final_state_gen.items()))
        list_gen_power = list(order_dict_gen.values())

        list_gen_power = np.array(list_gen_power)
        list_load_power = np.array(list_load_power)

        for i, j in enumerate(list_gen_power):
            if math.isnan(j):
                list_gen_power[i] = 0
        for i, j in enumerate(list_load_power):
            if math.isnan(j):
                list_load_power[i] = 0
    elif total_blackout == 1:
        list_gen_power = np.zeros(len(net.gen.index))
        list_load_power = np.zeros(len(net.load.index))

    return (list_gen_power, list_load_power)
Ejemplo n.º 26
0
def power_over_congestion(Grid, TypeElmnt, BranchIndTable, max_load_percent):
    """ Calculates delta power over from max power expected under the max_load_percent.
        Increases OverloadP_kW in 5% over max power branch limit.
    Returns (OverloadP_kW, loading_percent)
    """
    # FLUJO DE LINEA CAMBIA SIGNO. Absolute values requiered
    loading_percent = Grid['res_' + TypeElmnt].at[BranchIndTable,
                                                  'loading_percent']
    FluPAB_kW = abs(
        Grid['res_' + TypeElmnt].at[BranchIndTable,
                                    'p_from_kw'])  # da igual dirección (signo)
    MaxFluP_kW = FluPAB_kW * max_load_percent / loading_percent  # >= 0
    OverloadP_kW = FluPAB_kW - MaxFluP_kW
    OverloadP_kW += MaxFluP_kW * (0.05)  # increase 5% to compensate fpl error
    return OverloadP_kW, loading_percent


if __name__ == '__main__':
    # directly import conftest.py file (test only)
    import pandapower as pp
    from sys import path as sys__path
    sys__path.insert(0, "test/")

    # import test case
    from conftest import Sist5Bus
    Grid = Sist5Bus()
    redispatch(Grid, 'line', 0, max_load_percent=0.08)
    # redispatch(Grid, 'line', 0, max_load_percent = 2.8)
    pp.rundcpp(Grid)
def get_violation_number(grid3120, name):

    net = grid3120

    pp.rundcpp(net)
    ppc = net["_ppc"]

    ##### Setup Grid fluctuation parameters and constraints ########

    ## thresold on shift significance in DC-PF Eqs
    ## pwr = pwr_shf + np.real(bbus)*va
    ##

    shf_eps = 1e-4

    ## Std for fluctuating loads divided by their nominal values:
    ## for small grids values 0.5-1 are realistic
    ## larger grids have cov_std = 0.1 -- 0.3 or less
    ##

    cov_std = 0.25

    ## Phase angle difference limit
    ## small grids: pi/8 -- pi/6
    ## large grids: pi/3 -- pi/4
    ##

    bnd = math.pi / 2

    ### Cut small probabilities threshold
    ### discard all probabilities than thrs* prb(closest hyperplane)
    ###
    ###
    ### Crucially affects time performance
    ###

    thrs = 0.001

    ### Number of samples used in experiments
    ### 500 is often enough
    ### 10000 is a default value supresses the variance

    nsmp = 500

    ### Step-sizes for KL and Var minimization
    ### works well with 0.1-0.01

    eta_vm = 0.1
    eta_kl = 0.1

    ### Rounding threshold in optimization:
    ### if a (normalized on the simplex) hpl probability becomes lower then 0.001
    ### we increase it to this level
    ###
    ### Crucially affects numerical stability
    ###

    eps = 0.001

    ##### Setup power grid case in a convenient form for further sampling ########

    ### find number of lines (m) and buses(n)

    m = net.line['to_bus'].size
    n = net.res_bus['p_mw'].size

    ### Construct adjacency matrix
    ###

    adj = np.zeros((2 * m, n))
    for i in range(0, m):
        adj[i, net.line['to_bus'][i]] = 1
        adj[i, net.line['from_bus'][i]] = -1
        adj[i + m, net.line['to_bus'][i]] = -1
        adj[i + m, net.line['from_bus'][i]] = 1

    ### DC power flow equations have a form:
    ###
    ### pwr = pwr_shf + np.real(bbus)*va
    ### (compute all parameters)

    bbus = np.real(ppc['internal']['Bbus'])
    va = math.pi * net.res_bus['va_degree'] / 180
    pwr = -net.res_bus['p_mw']
    pwr_shf = pwr - bbus @ va

    ### pwr_shf is significant or not:
    ###
    ### if the shift is small: zero it out
    ### (simplifies testing and removes "math zeros")

    print("significant shift: ", np.max(pwr_shf) - np.min(pwr_shf) > shf_eps)
    if (np.max(pwr_shf) - np.min(pwr_shf) < shf_eps):
        pwr_shf[range(0, n)] = 0

    ### Phase angle differences:
    ###
    ### va = pinv(bbus)*(pwr - pwr_shf)
    ### va_d = adj*va = adj*pinv(bbus)*(pwr - pwr_shf)
    ### va_d = pf_mat*pwr - va_shf

    bbus_pinv = pinvh(bbus.todense())
    pf_mat = adj @ bbus_pinv
    va_shf = pf_mat @ pwr_shf

    ### Voltage angle differences:
    ###

    va_d = pf_mat @ pwr - va_shf

    ##### Distribution of fluctuations ######

    ### assume the only one slack (a higher-level grid) in the grid
    ### supress all its fluctuations and balance the grid
    ###
    ### TODO: adjust to a general case
    ###

    slck = net.ext_grid['bus']
    slck_mat = np.eye(n)
    slck_mat[slck] = -1
    ## assign values to the whole array
    slck_mat[slck, slck] = 0
    # and zero out for the slack itself

    ### set fluctuating components: either loads or gens or both
    ###

    loads = np.zeros(n)
    gens = np.zeros(n)
    ctrls = np.zeros(n)
    ## controllable loads + gens

    loads[net.load['bus']] = -net.res_load['p_mw']
    gens[net.gen['bus']] = net.res_gen['p_mw']
    ctrls = loads + gens

    ### assume only loads are fluctuating
    ###

    xi = loads

    ### Set covariance matrix and mean
    ###
    ### cov_sq = square of the covariance matrix
    ### Gaussian rv with covariance \Sigma is \Sigma^{1/2} * std_normal_rv
    ###
    ### TODO: change to LU/cholesky factorization
    ###

    cov_sq = cov_std * np.diag(np.abs(xi))

    ### Final equations with fluctuations xi are then
    ###
    ### w/o fluctuations:
    ### va_d = pf_mat*pwr - va_shf
    ### with fluctuations:
    ### va_d = pf_mat@(pwr + slck_mat*cov_sq*xi) - va_shf
    ### va_d = pf_mat@pwr - va_shf + (pf_mat@(slck_mat@cov_sq))@xi_std
    ### va_d = mu + A@xi_std
    ### where xi_std is a standard normal with only fluctuating components
    ###

    A = (pf_mat @ slck_mat) @ cov_sq
    mu = pf_mat @ pwr - va_shf

    ### Feasibility Polytope Inequalities
    ### bnd \ge va_d = mu_f + A_f@xi_std
    ### incorporates both va_d \le b and va_d \ge -b as we have va_d's with 2 signs
    ###

    b = np.ones(2 * m) * bnd

    ### normalize the matrices to make it easier to compute a failure probability
    ###

    ### compute row norms of A
    nrms = np.maximum(la.norm(A, axis=1), 1e-20)

    ### normalize A and b so that b_n\ge A_n*xi_std
    b_n = (b - mu) / nrms
    A_n = [A[i] / nrms[i] for i in range(0, 2 * m)]

    ##### Assest equations feasibility #######

    ### Power balance check
    ###

    print("Eqs balance check:", 0 == np.sum(np.sign(mu)))

    ### check positiveness of bnd - mu_f = RHS - LHS
    ###

    print("Inqs. feasibility check: ", np.min(b - mu) > 0)
    print("Min gap in phase angles = min(RHS - LHS)",
          np.min(b - mu))  ## positive value, otherwise the grid fails whp
    print("The RHS (phase angle diff max) = ", bnd)

    ### Compute probabilities:
    ### prb: probability of each hpl failure
    ### p_up, p_dwn: upper and lower bounds
    ###

    prb = norm.cdf(-b_n)
    p_up = np.sum(prb)
    p_dwn = np.max(prb)

    print("the union bound (upper):", p_up)
    print("the max bound (lower):", p_dwn)

    ### Keep only valuable probabilities:
    ### - use the union bound for all the rest
    ### - keep only the prbs higher than the thrs* p_dwn

    prbh_id = (prb > thrs * p_dwn)
    prb_rmd = np.sum(prb[~(prb > thrs * p_dwn)])

    print("Remainder probability (omitted):", prb_rmd)

    ############ Preliminary steps for Sampling and Importance Sampling ############

    ### normalize all active probabilities to one
    ### as we only play a hyperplane out of them
    ###
    ### NB: crucial steps in performance optimization
    ###

    x_id = np.where(prbh_id == True)[0]

    ### local normalized versions of A and b,
    ### reduced in size: number of rows now is equal to a number of constraints
    ### that have a high probability of violation
    ###

    x_bn = b_n[x_id]

    ### we do not care about the full matrix A and vector b
    ### only about important parts of them
    A_n = np.array(A_n)
    x_An = A_n[x_id]

    print("# hpls we care of: ", len(x_bn))

    ############# Monte-Carlo ##################

    rv = norm()
    x_std = norm.rvs(size=[n, nsmp])
    smp = x_An @ x_std

    ### fls_mc = failures in Monte-Carlo, e.g.
    ### when MC discovers a failure
    ###

    fls_mc = sum((x_bn <= smp.T[:]).T)
    print("Max # of hlps a sample if out of: ", np.max(fls_mc))

    ### MC failure expectation and std
    ###

    mc_exp = (1 - np.sum(fls_mc == 0) / nsmp) * (1 - prb_rmd) + prb_rmd
    mc_std = (1 - prb_rmd) / math.sqrt(nsmp)
    violation_dict = {}
    for i in range(0, np.max(fls_mc) + 1):
        print(i, "hpls violated (exactly) vs # cases", np.sum(fls_mc == i))
        violation_dict[i] = int(np.sum(fls_mc == i))

    print("\nMC(exp, std):", (mc_exp, mc_std))

    ## write into file
    #path_to_viol_dirs = os.path.join("results", "hplns_violations")

    violation_dict["Ineqs. Feasibility Check"] = bool(np.min(b - mu) > 0)
    violation_dict["Significant shift"] = bool(
        np.max(pwr_shf) - np.min(pwr_shf) > shf_eps)
    violation_dict["Min gap in phase angles = min(RHS - LHS)"] = float(
        np.min(b - mu))
    violation_dict["The RHS (phase angle diff max) = "] = float(bnd)
    violation_dict["Probability"] = mc_exp

    ############# ALOE ##################
    ###
    ### Exactly follows to the Owen/Maximov/Chertkov paper, EJOS'19
    ###
    ### sample z ~ N(0, I_n)
    ### sample u ~ U(0,1)
    ### compute y = F^{-1}(u F(-b_i))
    ### compute x = - (a_i * y + (I - a_i.T * a_i) z)
    ###
    ### Ouput: union bound divided by the expected failure multiplicity
    ###

    ### Initialize samplers
    ###
    ### sample z ~ N(0, I_n) and u ~ U(0,1)
    ###

    rv = norm()
    rv_u = uniform()
    z = norm.rvs(size=[nsmp, n])
    u = uniform.rvs(size=[nsmp])

    ### x_alph is a vector of ALOE probabilities
    ### normalized by a unit simplex
    ###

    x_alph = prb[prbh_id] / np.sum(prb[prbh_id])
    print("ALOE prbs for major hpls: ", x_alph)

    ### _hpl: how many smpls beyond each of the hpls
    ###

    _hpl = multinomial.rvs(n=nsmp, p=x_alph)

    ### print("# samples per hpl", _hpl)

    ### Get cummulative sums, which are easier to work with
    _hpl = list(itertools.accumulate(_hpl))
    _hpl = np.array(_hpl)

    ### print("cusum of # hpls", _hpl)

    ### Generate samples
    ### x_aloe -- samples generated by ALOE
    ###
    ### TODO: seems optimizable, but I am not sure about memory mgmnt in python
    x_aloe = np.zeros([nsmp, n])

    # index of the active hyperplane
    hpl_id = 0

    ### get samples x_aloe according to the algorithm
    for i in range(0, nsmp):
        ### get index of a hyperplane to sample beyond
        hpl_id = (hpl_id, hpl_id + 1)[i >= _hpl[hpl_id]]
        y = norm.ppf(u[i] * norm.cdf(-x_bn[hpl_id]))
        x_aloe[i] = -x_An[hpl_id] * y - z[i] + np.outer(
            x_An[hpl_id], x_An[hpl_id]) @ z[i]

    ### test how many constraints are violated
    smp = x_An @ x_aloe.T

    ### compute expectation and std
    aloe_exp = p_up * np.sum(
        1. / np.sum(x_bn <= smp.T[:], axis=1)) / nsmp + prb_rmd
    aloe_std = p_up * math.sqrt(2 * len(_hpl)) / math.sqrt(nsmp)
    # indeed len(_hpl) instead of 2*m in the Thrm

    print("ALOE (exp, std)", (aloe_exp, aloe_std))

    ####### Optimization approach ######
    #######
    ####### Variance Minimization ######
    #######

    ### setup the initial values

    eta = eta_vm
    md_var = 0
    md_exp = 0
    grad = np.zeros(len(x_bn))
    #gradient on each iteration
    _hpl = np.zeros(nsmp)
    # hpls choosen by the method

    ### intentionally use a copy instead of a reference
    ### alph is a vector of weigths to be updated in algorithm
    ###

    alph = x_alph[:]

    # values for Phi (x_bn)
    x_phi = [norm.cdf(-x_bn[i]) for i in range(0, len(x_bn))]

    ### grad normalization by prbs[i] factor is introduced to make computations numerically stable
    ###

    prbs = prb[prbh_id]

    for i in range(0, nsmp):

        ### sample x according to current alph
        hpl_id = np.where(
            multinomial.rvs(n=1, p=alph, size=1, random_state=None)[0] == 1)[0]
        _hpl[i] = hpl_id

        ### generate a sample following to the ALOE procedure
        y = norm.ppf(u[i] * norm.cdf(-x_bn[hpl_id]))
        x_smp = -x_An[hpl_id] * y - z[i] + np.outer(x_An[hpl_id],
                                                    x_An[hpl_id]) @ z[i]

        ### the RHS' to be compared with x_bn
        x_smp = x_An @ x_smp.T

        ### results of constraints violations for each generated object
        cns_vlt = (x_bn <= x_smp.T[:])[0]

        ### weight vector defined by the multiplicity of constraint violation for each sample
        wgt = 1. / np.sum(np.multiply(cns_vlt, np.multiply(alph, 1. / x_alph)))

        ### compute gradient of the variance, see the paper (our + OMC) for details
        grad = [
            -p_up * p_up * wgt * wgt * norm.pdf(x_smp[k])[0] * cns_vlt[k] /
            prbs[k] for k in range(len(x_smp))
        ]
        grad = np.array(grad)

        ### The gradient is high -- signal about emergency as it can zero out all weights
        if (la.norm(eta * grad) > 1e4):
            print(
                "\n##############    Extremely high gradient      ############\n"
            )
            print("Iteration: ", i, "\nGradient:", grad)

        ### make a ``simplex MD'' update
        alph = [
            math.exp(-eta * grad[k]) * alph[k] for k in range(0, len(x_smp))
        ]

        ### enter if some coordinates are too small and may cause numerical instability
        ### increase the corresponding weigths
        if (np.min(alph) < eps):
            print("###########  some coordinates are small  #################")
            alph = [alph[k] + eps for k in range(0, len(x_bn))]

        ### make a projection to the unit simplex
        alph = alph / np.sum(alph)

        ### adjust contribution to the errors
        md_exp = md_exp + wgt
        md_var = md_var + p_up * np.dot(grad.T, grad)

    print("Optimal weigths of MD-Var minimization: ", alph)
    print("Optimal weigths of ALOE", x_alph)

    ### normalize errors, compute standard deviation
    md_exp = p_up * md_exp / nsmp + prb_rmd
    md_std = p_up * math.sqrt(md_var) / nsmp

    print("MD-Var (exp, std)", (md_exp, md_std))
    #print("assert normalization:", np.sum(alph), np.sum(x_alph))

    ####### Optimization approach ######
    #######
    ####### KL Minimization ######
    #######

    ### SMD step-size
    eta = eta_kl

    ### setup initial values
    kl_exp = 0
    kl_var = 0
    grad = np.zeros(len(x_bn))
    _hpl = np.zeros(nsmp)
    ## _hpl[i] = beyond which hpl we sample on iteration i

    ### intentionally use a copy instead of a reference
    ### alph is an optimization variable
    alph = x_alph[:]

    ### this normalization factor is introduced to make computations numerically stable
    prbs = prb[prbh_id]

    for i in range(0, nsmp):  #,miniters=500):

        ### sample x according to current alph
        hpl_id = np.where(
            multinomial.rvs(n=1, p=alph, size=1, random_state=None)[0] == 1)[0]
        _hpl[i] = hpl_id

        ### generate a sample accordint to ALOE
        y = norm.ppf(u[i] * norm.cdf(-x_bn[hpl_id]))
        x_smp = -x_An[hpl_id] * y - z[i] + np.outer(x_An[hpl_id],
                                                    x_An[hpl_id]) @ z[i]

        ### RHS to compare with x_bn
        x_smp = x_An @ x_smp.T

        ### results of constraints violations for the generated object
        cns_vlt = (x_bn <= x_smp.T[:])[0]

        ### object weight which is set according to ALOE
        wgt = 1. / np.sum(np.multiply(cns_vlt, np.multiply(alph, 1. / x_alph)))

        # the KL divergence's gradient
        grad = [
            -p_up * wgt * norm.pdf(x_smp[k])[0] * cns_vlt[k] / prbs[k]
            for k in range(len(x_smp))
        ]
        grad = np.array(grad)

        ### The gradient is high -- signal about emergency as it can zero out all weights
        if (la.norm(eta * grad) > 1e4):
            print(
                "\n##############    Extremely high gradient      ############\n"
            )
            print("Iteration: ", i, "\nGradient:", grad)

        ### make a ``simplex MD'' update
        alph = [
            math.exp(-eta * grad[k]) * alph[k] for k in range(0, len(x_smp))
        ]

        ### enter if some coordinates are too small and may cause numerical instability
        ### increase the corresponding weigths
        if (np.min(alph) < eps):
            print("###########  some coordinates are small  #################")
            alph = [alph[k] + eps for k in range(0, len(x_bn))]

        ### make a projection to the unit simplex
        alph = alph / np.sum(alph)

        ### adjust contribution to the errors
        kl_exp = kl_exp + wgt
        kl_var = kl_var + p_up * np.dot(grad.T, grad) * wgt
    alph_KL = alph
    print("Optimal weigths of MD-KL minimization: ", alph_KL)
    print("Optimal weigths of ALOE", x_alph)

    ### normalize errors
    kl_exp = p_up * kl_exp / nsmp + prb_rmd
    kl_std = p_up * math.sqrt(kl_var) / nsmp
    print("MD-KL (exp, std)", (kl_exp, kl_std))

    #print("assert normalization:", np.sum(alph), np.sum(x_alph))

    ##############  Output all probabilities  ##################

    print("the union bound (up):", p_up)
    print("the max bound (lower):", p_dwn)

    print("MC(exp, std):", mc_exp, mc_std)
    print("ALOE(exp, std)", aloe_exp, aloe_std)

    print("MD-Var(exp, var)", md_exp, md_std)
    print("MD-KL(exp, var)", kl_exp, kl_std)
    violation_dict["MD-Var"] = (md_exp, md_std)
    violation_dict["MD-KL"] = (kl_exp, kl_std)
    violation_dict["ALOE"] = (aloe_exp, aloe_std)
    violation_dict["MD-Var-W"] = [float(a) for a in alph]
    violation_dict["MD-KL-W"] = [float(a) for a in alph_KL]
    violation_dict["ALOE-W"] = [float(a) for a in x_alph]
    with open(name + ".json", 'w+') as fp:
        json.dump(violation_dict, fp)
Ejemplo n.º 28
0
    def runpf(self, is_dc=False):
        """
        .. warning:: /!\\\\ Internal, do not use unless you know what you are doing /!\\\\

        Run a power flow on the underlying _grid. This implements an optimization of the powerflow
        computation: if the number of
        buses has not changed between two calls, the previous results are re used. This speeds up the computation
        in case of "do nothing" action applied.
        """
        conv = True
        nb_bus = self.get_nb_active_bus()
        try:
            with warnings.catch_warnings():
                # remove the warning if _grid non connex. And it that case load flow as not converged
                warnings.filterwarnings("ignore", category=scipy.sparse.linalg.MatrixRankWarning)
                warnings.filterwarnings("ignore", category=RuntimeWarning)
                if self._nb_bus_before is None:
                    self._pf_init = "dc"
                elif nb_bus == self._nb_bus_before:
                    self._pf_init = "results"
                else:
                    self._pf_init = "auto"

                if np.any(~self._grid.load["in_service"]):
                    # TODO see if there is a better way here -> do not handle this here, but rather in Backend._next_grid_state
                    raise pp.powerflow.LoadflowNotConverged("Isolated load")
                if np.any(~self._grid.gen["in_service"]):
                    # TODO see if there is a better way here -> do not handle this here, but rather in Backend._next_grid_state
                    raise pp.powerflow.LoadflowNotConverged("Isolated gen")

                if is_dc:
                    pp.rundcpp(self._grid, check_connectivity=False)
                    self._nb_bus_before = None  # if dc i start normally next time i call an ac powerflow
                else:
                    pp.runpp(self._grid, check_connectivity=False, init=self._pf_init, numba=numba_)
                if "_ppc" in self._grid:
                    if "et" in self._grid["_ppc"]:
                        self.comp_time += self._grid["_ppc"]["et"]

                if self._grid.res_gen.isnull().values.any():
                    # TODO see if there is a better way here -> do not handle this here, but rather in Backend._next_grid_state
                    # sometimes pandapower does not detect divergence and put Nan.
                    raise pp.powerflow.LoadflowNotConverged("Isolated gen")

                self.prod_p[:], self.prod_q[:], self.prod_v[:] = self._gens_info()
                self.load_p[:], self.load_q[:], self.load_v[:] = self._loads_info()
                if not is_dc:
                    if not np.all(np.isfinite(self.load_v)):
                        # TODO see if there is a better way here
                        # some loads are disconnected: it's a game over case!
                        raise pp.powerflow.LoadflowNotConverged("Isolated load")
                else:
                    # fix voltages magnitude that are always "nan" for dc case
                    # self._grid.res_bus["vm_pu"] is always nan when computed in DC
                    self.load_v[:] = self.load_pu_to_kv  # TODO
                    # need to assign the correct value when a generator is present at the same bus
                    # TODO optimize this ugly loop
                    for l_id in range(self.n_load):
                        if self.load_to_subid[l_id] in self.gen_to_subid:
                            ind_gens = np.where(self.gen_to_subid == self.load_to_subid[l_id])[0]
                            for g_id in ind_gens:
                                if self._topo_vect[self.load_pos_topo_vect[l_id]] == self._topo_vect[self.load_pos_topo_vect[g_id]]:
                                    self.load_v[l_id] = self.prod_v[g_id]
                                    break

                self.line_status[:] = self._get_line_status()
                # I retrieve the data once for the flows, so has to not re read multiple dataFrame
                self.p_or[:] = self._aux_get_line_info("p_from_mw", "p_hv_mw")
                self.q_or[:] = self._aux_get_line_info("q_from_mvar", "q_hv_mvar")
                self.v_or[:] = self._aux_get_line_info("vm_from_pu", "vm_hv_pu")
                self.a_or[:] = self._aux_get_line_info("i_from_ka", "i_hv_ka") * 1000
                self.a_or[~np.isfinite(self.a_or)] = 0.
                self.v_or[~np.isfinite(self.v_or)] = 0.

                self.p_ex[:] = self._aux_get_line_info("p_to_mw", "p_lv_mw")
                self.q_ex[:] = self._aux_get_line_info("q_to_mvar", "q_lv_mvar")
                self.v_ex[:] = self._aux_get_line_info("vm_to_pu", "vm_lv_pu")
                self.a_ex[:] = self._aux_get_line_info("i_to_ka", "i_lv_ka") * 1000
                self.a_ex[~np.isfinite(self.a_ex)] = 0.
                self.v_ex[~np.isfinite(self.v_ex)] = 0.

                # it seems that pandapower does not take into account disconencted powerline for their voltage
                self.v_or[~self.line_status] = 0.
                self.v_ex[~self.line_status] = 0.

                self.v_or[:] *= self.lines_or_pu_to_kv
                self.v_ex[:] *= self.lines_ex_pu_to_kv

                self._nb_bus_before = None
                self._grid._ppc["gen"][self._iref_slack, 1] = 0.
                self._topo_vect[:] = self._get_topo_vect()
                return self._grid.converged

        except pp.powerflow.LoadflowNotConverged as exc_:
            # of the powerflow has not converged, results are Nan
            self.p_or[:] = np.NaN
            self.q_or[:] = np.NaN
            self.v_or[:] = np.NaN
            self.a_or[:] = np.NaN
            self.p_ex[:] = np.NaN
            self.q_ex[:] = np.NaN
            self.v_ex[:] = np.NaN
            self.a_ex[:] = np.NaN
            self.prod_p[:] = np.NaN
            self.prod_q[:] = np.NaN
            self.prod_v[:] = np.NaN
            self.load_p[:] = np.NaN
            self.load_q[:] = np.NaN
            self.load_v[:] = np.NaN

            self._nb_bus_before = None
            return False
Ejemplo n.º 29
0
 def run_ref_pf(self, net):
     with warnings.catch_warnings():
         warnings.filterwarnings("ignore")
         pp.rundcpp(net, init="flat")
Ejemplo n.º 30
0
    def runpf(self, is_dc=False):
        """
        Run a power flow on the underlying _grid. This implements an optimization of the powerflow
        computation: if the number of
        buses has not changed between two calls, the previous results are re used. This speeds up the computation
        in case of "do nothing" action applied.
        """
        conv = True
        nb_bus = self.get_nb_active_bus()
        try:
            with warnings.catch_warnings():
                # remove the warning if _grid non connex. And it that case load flow as not converged
                warnings.filterwarnings(
                    "ignore", category=scipy.sparse.linalg.MatrixRankWarning)
                warnings.filterwarnings("ignore", category=RuntimeWarning)
                if self._nb_bus_before is None:
                    self._pf_init = "dc"
                elif nb_bus == self._nb_bus_before:
                    self._pf_init = "results"
                else:
                    self._pf_init = "auto"
                if is_dc:
                    pp.rundcpp(self._grid, check_connectivity=False)
                    self._nb_bus_before = None  # if dc i start normally next time i call an ac powerflow
                else:
                    pp.runpp(self._grid,
                             check_connectivity=False,
                             init=self._pf_init,
                             numba=numba_)

                if self._grid.res_gen.isnull().values.any():
                    # TODO see if there is a better way here -> do not handle this here, but rather in Backend._next_grid_state
                    # sometimes pandapower does not detect divergence and put Nan.
                    raise pp.powerflow.LoadflowNotConverged("Isolated gen")

                self.load_p[:], self.load_q[:], self.load_v[:] = self._loads_info(
                )
                if not is_dc:
                    if not np.all(np.isfinite(self.load_v)):
                        # TODO see if there is a better way here
                        # some loads are disconnected: it's a game over case!
                        raise pp.powerflow.LoadflowNotConverged(
                            "Isolated load")

                self.line_status[:] = self._get_line_status()
                # I retrieve the data once for the flows, so has to not re read multiple dataFrame
                self.p_or[:] = self._aux_get_line_info("p_from_mw", "p_hv_mw")
                self.q_or[:] = self._aux_get_line_info("q_from_mvar",
                                                       "q_hv_mvar")
                self.v_or[:] = self._aux_get_line_info("vm_from_pu",
                                                       "vm_hv_pu")
                self.a_or[:] = self._aux_get_line_info("i_from_ka",
                                                       "i_hv_ka") * 1000
                self.a_or[~np.isfinite(self.a_or)] = 0.
                self.v_or[~np.isfinite(self.v_or)] = 0.

                # it seems that pandapower does not take into account disconencted powerline for their voltage
                self.v_or[~self.line_status] = 0.
                self.v_ex[~self.line_status] = 0.

                self.p_ex[:] = self._aux_get_line_info("p_to_mw", "p_lv_mw")
                self.q_ex[:] = self._aux_get_line_info("q_to_mvar",
                                                       "q_lv_mvar")
                self.v_ex[:] = self._aux_get_line_info("vm_to_pu", "vm_lv_pu")
                self.a_ex[:] = self._aux_get_line_info("i_to_ka",
                                                       "i_lv_ka") * 1000
                self.a_ex[~np.isfinite(self.a_ex)] = 0.
                self.v_ex[~np.isfinite(self.v_ex)] = 0.

                self.v_or[:] *= self.lines_or_pu_to_kv
                self.v_ex[:] *= self.lines_ex_pu_to_kv

                self.prod_p[:], self.prod_q[:], self.prod_v[:] = self._gens_info(
                )

                self._nb_bus_before = None
                self._grid._ppc["gen"][self._iref_slack, 1] = 0.
                self._topo_vect[:] = self._get_topo_vect()
                return self._grid.converged

        except pp.powerflow.LoadflowNotConverged as exc_:
            # of the powerflow has not converged, results are Nan
            self.p_or[:] = np.NaN
            self.q_or[:] = np.NaN
            self.v_or[:] = np.NaN
            self.a_or[:] = np.NaN
            self.p_ex[:] = np.NaN
            self.q_ex[:] = np.NaN
            self.v_ex[:] = np.NaN
            self.a_ex[:] = np.NaN
            self.prod_p[:] = np.NaN
            self.prod_q[:] = np.NaN
            self.prod_v[:] = np.NaN
            self.load_p[:] = np.NaN
            self.load_q[:] = np.NaN
            self.load_v[:] = np.NaN

            self._nb_bus_before = None
            return False