import pandapower as pp
#create empty net
net = pp.create_empty_network()
#create buses
bus1 = pp.create_bus(net, vn_kv=20., name="Bus 1")
bus2 = pp.create_bus(net, vn_kv=0.4, name="Bus 2")
bus3 = pp.create_bus(net, vn_kv=0.4, name="Bus 3")
#create bus elements
pp.create_ext_grid(net, bus=bus1, vm_pu=1.02, name="Grid Connection")
pp.create_load(net, bus=bus3, p_mw=0.100, q_mvar=0.05, name="Load")
#create branch elements
trafo = pp.create_transformer(net, hv_bus=bus1, lv_bus=bus2, std_type="0.4 MVA 20/0.4 kV", name="Trafo")
line = pp.create_line(net, from_bus=bus2, to_bus=bus3, length_km=0.1, std_type="NAYY 4x50 SE", name="Line")
Each dataframe in a pandapower net object contains the information about one pandapower element, such as line, load transformer etc.
net.bus
name | vn_kv | type | zone | in_service | |
---|---|---|---|---|---|
0 | Bus 1 | 20.0 | b | None | True |
1 | Bus 2 | 0.4 | b | None | True |
2 | Bus 3 | 0.4 | b | None | True |
net.line
name | std_type | from_bus | to_bus | length_km | r_ohm_per_km | x_ohm_per_km | c_nf_per_km | g_us_per_km | max_i_ka | df | parallel | type | in_service | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Line | NAYY 4x50 SE | 1 | 2 | 0.1 | 0.642 | 0.083 | 210.0 | 0.0 | 0.142 | 1.0 | 1 | cs | True |
net.trafo
name | std_type | hv_bus | lv_bus | sn_mva | vn_hv_kv | vn_lv_kv | vk_percent | vkr_percent | pfe_kw | ... | tap_neutral | tap_min | tap_max | tap_step_percent | tap_step_degree | tap_pos | tap_phase_shifter | parallel | df | in_service | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Trafo | 0.4 MVA 20/0.4 kV | 0 | 1 | 0.4 | 20.0 | 0.4 | 6.0 | 1.425 | 1.35 | ... | 0 | -2 | 2 | 2.5 | 0.0 | 0 | False | 1 | 1.0 | True |
1 rows × 23 columns
net.load
name | bus | p_mw | q_mvar | const_z_percent | const_i_percent | sn_mva | scaling | in_service | type | |
---|---|---|---|---|---|---|---|---|---|---|
0 | Load | 2 | 0.1 | 0.05 | 0.0 | 0.0 | NaN | 1.0 | True | wye |
Note that line and transformer are created with standard types, so thath the electric parameters of are automatically filled in from the standard type library.
We now run a power flow:
pp.runpp(net)
And check out at the results for buses, lines an transformers:
net.res_bus
vm_pu | va_degree | p_mw | q_mvar | |
---|---|---|---|---|
0 | 1.020000 | 0.000000 | -0.107265 | -0.052675 |
1 | 1.008843 | -0.760126 | 0.000000 | 0.000000 |
2 | 0.964431 | 0.115859 | 0.100000 | 0.050000 |
net.res_line
p_from_mw | q_from_mvar | p_to_mw | q_to_mvar | pl_mw | ql_mvar | i_from_ka | i_to_ka | i_ka | vm_from_pu | va_from_degree | vm_to_pu | va_to_degree | loading_percent | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.105392 | 0.050696 | -0.1 | -0.05 | 0.005392 | 0.000696 | 0.167325 | 0.167326 | 0.167326 | 1.008843 | -0.760126 | 0.964431 | 0.115859 | 117.835208 |
net.res_trafo
p_hv_mw | q_hv_mvar | p_lv_mw | q_lv_mvar | pl_mw | ql_mvar | i_hv_ka | i_lv_ka | vm_hv_pu | va_hv_degree | vm_lv_pu | va_lv_degree | loading_percent | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.107265 | 0.052675 | -0.105392 | -0.050696 | 0.001873 | 0.001979 | 0.003382 | 0.167325 | 1.02 | 0.0 | 1.008843 | -0.760126 | 29.289513 |
We now lower the tap changer position, from position 0 to -1 and run another power flow:
net.trafo.tap_pos.at[trafo] = -1
pp.runpp(net)
Looking at the results shows that bus voltages at the low voltage side of the transformer have increased:
net.res_bus
vm_pu | va_degree | p_mw | q_mvar | |
---|---|---|---|---|
0 | 1.020000 | 0.000000 | -0.107015 | -0.052529 |
1 | 1.035301 | -0.720245 | 0.000000 | 0.000000 |
2 | 0.992135 | 0.109513 | 0.100000 | 0.050000 |
We now create an open switch at the load bus:
pp.create_switch(net, bus=bus3, element=line, et="l", closed=False)
0
The open switch cuts the load bus from power supply:
This can be verified by running a power flow and inspecting the results. The voltage at bus 2 is given as NaN:
pp.runpp(net)
net.res_bus
vm_pu | va_degree | p_mw | q_mvar | |
---|---|---|---|---|
0 | 1.020000 | 0.000000 | -0.001477 | 0.000001 |
1 | 1.046129 | -0.005637 | 0.000000 | 0.000000 |
2 | NaN | NaN | 0.000000 | 0.000000 |
The load does not feed in:
net.res_load
p_mw | q_mvar | |
---|---|---|
0 | 0.0 | 0.0 |
And the line is in open loop operation:
net.res_line
p_from_mw | q_from_mvar | p_to_mw | q_to_mvar | pl_mw | ql_mvar | i_from_ka | i_to_ka | i_ka | vm_from_pu | va_from_degree | vm_to_pu | va_to_degree | loading_percent | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1.230380e-13 | -0.000001 | -4.645745e-16 | 4.580705e-20 | 1.225734e-13 | -0.000001 | 0.000002 | 6.409876e-16 | 0.000002 | 1.046129 | -0.005637 | 1.046129 | -0.005649 | 0.001122 |
The structure of the network can also be directly analyzed with the topology package. It uses an interface to the NetworkX library for graph searches. There are some predefined search algorithms, such as searching for unsupplied buses:
import pandapower.topology as top
top.unsupplied_buses(net)
{2}
The package correctly determines that bus 2 is cut from power supply. When we close the switch, there are no unsupplied buses anymore:
net.switch.closed.at[0] = True
top.unsupplied_buses(net)
set()
Apart from predefined search functions, it is also possible to translate the pandapower network into a NetworkX graph and run searches directly on that graph.
Suppose we want to find all buses that are on the same voltage level as the load bus. We then translate the grid into a graph but excluding the transformer:
mg = top.create_nxgraph(net, include_trafos=False)
And search for all buses that are connected to the load bus in that graph:
list(top.connected_component(mg, 2))
[2, 1]
The graph search finds all buses that are on the same voltage level. Searches like these can be used for feeder identification and many more applications.
pandapower includes a short circuit module that complies with IEC 60909. To run a short circuit analysis, we need to define short circuit parameters for the external grid:
net.ext_grid["s_sc_max_mva"] = 100
net.ext_grid["rx_max"] = 0.1
Now we can calculate short circuits. Here, we calculate a three phase short circuit current with a fault impedance of 2 Ohms:
import pandapower.shortcircuit as sc
sc.calc_sc(net, case="max", ip=True, r_fault_ohm=2.)
Initial and peak short circuit currents are given for faults at all buses:
net.res_bus_sc
ikss_ka | skss_mw | ip_ka | rk_ohm | xk_ohm | |
---|---|---|---|---|---|
0 | 2.534707 | 87.804824 | 4.317318 | 2.437816 | 4.378164 |
1 | 0.126631 | 0.087733 | 0.182666 | 2.005930 | 0.025290 |
2 | 0.122698 | 0.085008 | 0.176991 | 2.070130 | 0.033590 |
This concludes a short walkthrough of some pandapower features. More in-depth tutorials can be found in the pandapower documentation: https://www.pandapower.org/start/#interactive-tutorials-