Examples

The combination of a suitable MultiGraph and the availabe topology functions enables you to perform a wide range of topological searches and analyses.

Here are a few examples of what you can do:

basic example network

import pandapower as pp

net = pp.create_empty_network()

pp.create_bus(net, name = "110 kV bar", vn_kv = 110, type = 'b')
pp.create_bus(net, name = "20 kV bar", vn_kv = 20, type = 'b')
pp.create_bus(net, name = "bus 2", vn_kv = 20, type = 'b')
pp.create_bus(net, name = "bus 3", vn_kv = 20, type = 'b')
pp.create_bus(net, name = "bus 4", vn_kv = 20, type = 'b')
pp.create_bus(net, name = "bus 5", vn_kv = 20, type = 'b')
pp.create_bus(net, name = "bus 6", vn_kv = 20, type = 'b')

pp.create_ext_grid(net, 0, vm_pu = 1)

pp.create_line(net, name = "line 0", from_bus = 1, to_bus = 2, length_km = 1, std_type = "NAYY 150")
pp.create_line(net, name = "line 1", from_bus = 2, to_bus = 3, length_km = 1, std_type = "NAYY 150")
pp.create_line(net, name = "line 2", from_bus = 3, to_bus = 4, length_km = 1, std_type = "NAYY 150")
pp.create_line(net, name = "line 3", from_bus = 4, to_bus = 5, length_km = 1, std_type = "NAYY 150")
pp.create_line(net, name = "line 4", from_bus = 5, to_bus = 6, length_km = 1, std_type = "NAYY 150")
pp.create_line(net, name = "line 5", from_bus = 6, to_bus = 1, length_km = 1, std_type = "NAYY 150")

pp.create_transformer_from_parameters(net, hv_bus = 0, lv_bus = 1, i0_percent= 0.038, pfe_kw = 11.6,
        vscr_percent = 0.322, sn_kva = 40000.0, vn_lv_kv = 22.0,
        vn_hv_kv = 110.0, vsc_percent = 17.8)

pp.create_load(net, 2, p_kw = 1000, q_kvar = 200, name = "load 0")
pp.create_load(net, 3, p_kw = 1000, q_kvar = 200, name = "load 1")
pp.create_load(net, 4, p_kw = 1000, q_kvar = 200, name = "load 2")
pp.create_load(net, 5, p_kw = 1000, q_kvar = 200, name = "load 3")
pp.create_load(net, 6, p_kw = 1000, q_kvar = 200, name = "load 4")

pp.create_switch(net, bus = 1, element = 0, et = 'l')
pp.create_switch(net, bus = 2, element = 0, et = 'l')
pp.create_switch(net, bus = 2, element = 1, et = 'l')
pp.create_switch(net, bus = 3, element = 1, et = 'l')
pp.create_switch(net, bus = 3, element = 2, et = 'l')
pp.create_switch(net, bus = 4, element = 2, et = 'l')
pp.create_switch(net, bus = 4, element = 3, et = 'l', closed = 0)
pp.create_switch(net, bus = 5, element = 3, et = 'l')
pp.create_switch(net, bus = 5, element = 4, et = 'l')
pp.create_switch(net, bus = 6, element = 4, et = 'l')
pp.create_switch(net, bus = 6, element = 5, et = 'l')
pp.create_switch(net, bus = 1, element = 5, et = 'l')

Using NetworkX algorithms: shortest path

For many basic network analyses the algorithms that come with the NetworkX package will work just fine and you won’t need one of the spezialised topology functions. Finding the shortest path between two buses is a good example for that.

import pandapower.topology as top
import networkx as nx

mg = top.create_nxgraph(net)
nx.shortest_path(mg, 0, 5)
Out: [0, 1, 6, 5]
alternate Text

Find disconnected buses

With unsupplied_buses you can easily find buses that are not connected to an external grid.

import pandapower.topology as top

net.switch.closed.at[11] = 0
top.unsupplied_buses(net)
Out: {5, 6}
alternate Text

Calculate distances between buses

calc_distance_to_bus allows you to calculate the distance ( = shortest network route) from one bus all other ones. This is possible since line lengths are being transferred into the MultiGraph as an edge attribute. (Note: bus-bus-switches and trafos are interpreted as edges with length = 0)

import pandapower.topology as top

net.switch.closed.at[6] = 1
net.switch.closed.at[8] = 0
top.calc_distance_to_bus(net, 1)
Out:
0    0
1    0
2    1
3    2
4    3
5    4
6    1

Interpretation: The distance between bus 1 and itself is 0 km. Bus 1 is also 0 km away from bus 0, since they are connected with a transformer. The shortest path between bus 1 and bus 5 is 4 km long.

alternate Text

Find connected buses with the same voltage level

import pandapower.topology as top

mg_no_trafos = top.create_nxgraph(net, include_trafos = False)
cc = top.connected_components(mg_no_trafos)
In      : next(cc)
Out     : {0}
In      : next(cc)
Out     : {1, 2, 3, 4, 5, 6}
alternate Text

Find rings and ring sections

Another example of what you can do with the right combination of input arguments when creating the MultiGraph is finding rings and ring sections in your network. To achieve that for our example network, the trafo buses needs to be set as a nogobuses. With respect_switches = True you get the ring sections, with respect_switches = False the whole ring.

import pandapower.topology as top

mg_ring_sections = top.create_nxgraph(net, nogobuses = [0, 1])
cc_ring_sections = top.connected_components(mg_ring_sections)
In      : next(cc_ring_sections)
Out     : {2, 3, 4}

In      : next(cc_ring_sections)
Out     : {5, 6}
alternate Text
import pandapower.topology as top

mg_ring = top.create_nxgraph(net, respect_switches = False, nogobuses = [0,1])
cc_ring = top.connected_components(mg_ring)
In      : next(cc_ring)
Out     : {2, 3, 4, 5, 6}
alternate Text

Find stubs

determine_stubs lets you identify buses and lines that are stubs. Open switches are being ignored. Busses that you want to exclude should be defined as roots. Ext_grid buses are roots by default.

This is a small extension for the example network:

pp.create_bus(net, name = "bus 7", vn_kv = 20, type = 'b')
pp.create_bus(net, name = "bus 8", vn_kv = 20, type = 'b')

pp.create_line(net, name = "line 6", from_bus = 6, to_bus = 7, length_km = 1, std_type = "NAYY 150")
pp.create_line(net, name = "line 7", from_bus = 7, to_bus = 8, length_km = 1, std_type = "NAYY 150")

pp.create_load(net, 7, p_kw = 1000, q_kvar = 200, name = "load 5")
pp.create_load(net, 8, p_kw = 1000, q_kvar = 200, name = "load 6")
import pandapower.topology as top
top.determine_stubs(net, roots = [0,1])
In: net.bus

Out:
         name  vn_kv  min_vm_pu  max_vm_pu type  zone in_service auf_stich
0  110 kV bar    110      NaN      NaN    b  None       True     False
1   20 kV bar     20      NaN      NaN    b  None       True     False
2       bus 2     20      NaN      NaN    b  None       True     False
3       bus 3     20      NaN      NaN    b  None       True     False
4       bus 4     20      NaN      NaN    b  None       True     False
5       bus 5     20      NaN      NaN    b  None       True     False
6       bus 6     20      NaN      NaN    b  None       True     False
7       bus 7     20      NaN      NaN    b  None       True      True
8       bus 8     20      NaN      NaN    b  None       True      True

In: net.line

Out:
     name  std_type  from_bus  to_bus  length_km  r_ohm_per_km  x_ohm_per_km  c_nf_per_km  max_i_ka  df type in_service is_stich
0  line 0  NAYY 150         1       2          1         0.206         0.091            0    0.284   1   cs       True    False
1  line 1  NAYY 150         2       3          1         0.206         0.091            0    0.284   1   cs       True    False
2  line 2  NAYY 150         3       4          1         0.206         0.091            0    0.284   1   cs       True    False
3  line 3  NAYY 150         4       5          1         0.206         0.091            0    0.284   1   cs       True    False
4  line 4  NAYY 150         5       6          1         0.206         0.091            0    0.284   1   cs       True    False
5  line 5  NAYY 150         6       1          1         0.206         0.091            0    0.284   1   cs       True    False
6  line 6  NAYY 150         6       7          1         0.206         0.091            0    0.284   1   cs       True     True
7  line 7  NAYY 150         7       8          1         0.206         0.091            0    0.284   1   cs       True     True
alternate Text