<jupyter_start><jupyter_text>Use of the static grid equivalentsThis tutorial gives a quick overview of the grid equivalents function. This script gives an example to reduce a grid area using the IEEE case9 grid.  Determination of grid areasThe user can determine the grid area of interest (internal area), the grid area for the reduction (external area), and the boundary buses between them. The figure below schows an example of the grid with identified grid areas:- internal area (buses): [0, 3, 4, 8]- boundary buses: [4, 8] (boundary buses belong to the internal area)- external area (buses): [1, 2, 5, 6, 7] In order to identify the user-defined area, the boundary buses and one of the internal buses must be provided as inputs.  Required inputsThe most important inputs for grid equivalents are:- net: pandapower grid including power flow results- eq_type: the method used to determine the equivalent grid, e.g., "rei", "ward", "xward"- boundary_buses: indices of boundary buses (as a list) that divide the original grid into the internal areas and the external areas. Based on the figure above, boundary_buses = [4, 8] - internal_buses: bus indices (as a list), which are within the internal area. Based on the figure above, internal_buses = [0]. Just one of the internal buses is enough, the function will find and consider the remaining internal buses during the equivalent calculation. If 'internal_buses' is an empty list or None, the complete grid is treated as an external area.  Example: REI-equivalentIn the following, the reduction of the external grid (buses [1, 2, 5, 6, 7] of the grid case 9) in the figure above is shown.First, the necessary libraries need to be imported.<jupyter_code>import matplotlib.pyplot as plt

import pandapower as pp
import pandapower.networks
import pandapower.grid_equivalents<jupyter_output><empty_output><jupyter_text>Subsequently, the IEEE case 9 grid model is created, and its power flow is calculated.<jupyter_code>net = pp.networks.case9()
net.sn_mva = 1.0
pp.runpp(net)
net<jupyter_output><empty_output><jupyter_text>Next, we define the input parameters according to the figure above and obtain the REI-equivalent.<jupyter_code># equivalent type
eq_type = "rei"

# boundary buses
boundary_buses = [4, 8]

# internal buses 
internal_buses = [0]<jupyter_output><empty_output><jupyter_text>Next, the equivalent function is called, and the grid reduction is executed.<jupyter_code>net_eq = pp.grid_equivalents.get_equivalent(net, eq_type, boundary_buses, internal_buses)<jupyter_output>hp.pandapower.grid_equivalents.get_equivalent - INFO: rei equivalent calculation started
hp.pandapower.toolbox - INFO: dropped 2 gen elements
hp.pandapower.toolbox - INFO: dropped 5 lines with 0 line switches
hp.pandapower.toolbox - INFO: dropped 0 switches
hp.pandapower.toolbox - INFO: dropped 1 lines with 0 line switches
hp.pandapower.toolbox - INFO: dropped 1 load elements
hp.pandapower.toolbox - INFO: dropped 1 ext_grid elements
hp.pandapower.toolbox - INFO: dropped 2 lines with 0 line switches
hp.pandapower.toolbox - INFO: dropped 0 switches
hp.pandapower.toolbox - INFO: dropped 1 lines with 0 line switches
hp.pandapower.toolbox - INFO: dropped 3 impedance elements
hp.pandapower.toolbox - INFO: dropped 5 lines with 0 line switches
hp.pandapower.toolbox - INFO: dropped 0 switches
hp.pandapower.toolbox - INFO: dropped 3 impedance elements
hp.pandapower.toolbox - INFO: dropped 1 lines with 0 line switches
hp.pandapower.toolbox - INFO: dropped 0 lines with 0 line switches
hp.pandapowe[...]<jupyter_text>Now, the grid equivalent is obtained: "net_eq" is the REI-equivalent grid model. We can compare the power flow results between the original grid "net" and the reduced grid "net_eq".<jupyter_code>print("--- power flow (original grid) ---")
display(net.res_bus)
print("--- power flow (reduced grid) ---")
display(net_eq.res_bus)<jupyter_output>--- power flow (original grid) ---<jupyter_text>It can be seen that the power flow results (*vm_pu*, *va_degree*) of the internal buses [0, 3, 4, 8] in both grids are the same , i.e., the equivalent calculation is successful. The *p_mw* and *q_mvar* values at the boundary buses [4, 8] are different due to the equivalent devices. During the grid reduction, additional equivalent devices (e.g., additional buses [9, 10, 11], impedance, shunts, etc.) are created, representing the interaction between the internal area and the external area, and maintaining the grid states in the internal area. We can see the additional shunts in the grid equivalent:<jupyter_code>print("--- shunts (original grid) ---")
display(net.shunt)
print("--- shunts (reduced grid) ---")
display(net_eq.shunt)<jupyter_output>--- shunts (original grid) ---<jupyter_text>Example: (X)Ward-equivalent In the following, we demonstrate an example for the (x)ward-equivalent. We change the equivalent type and repeat the equivalent calculation.<jupyter_code># equivalent type
eq_type = "ward"   # for xward-equivalent: eq_type = "xward"

# run equivalent calculation
net_eq_ward = pp.grid_equivalents.get_equivalent(net, eq_type, boundary_buses, 
                                                 internal_buses)<jupyter_output>hp.pandapower.grid_equivalents.get_equivalent - INFO: ward equivalent calculation started
hp.pandapower.toolbox - INFO: dropped 2 gen elements
hp.pandapower.toolbox - INFO: dropped 5 lines with 0 line switches
hp.pandapower.toolbox - INFO: dropped 0 switches
hp.pandapower.toolbox - INFO: dropped 1 lines with 0 line switches
hp.pandapower.toolbox - INFO: dropped 1 load elements
hp.pandapower.toolbox - INFO: dropped 1 ext_grid elements
hp.pandapower.toolbox - INFO: dropped 2 lines with 0 line switches
hp.pandapower.toolbox - INFO: dropped 0 switches
hp.pandapower.toolbox - INFO: dropped 1 lines with 0 line switches
hp.pandapower.toolbox - INFO: dropped 2 gen elements
hp.pandapower.toolbox - INFO: dropped 5 lines with 0 line switches
hp.pandapower.toolbox - INFO: dropped 0 switches
hp.pandapower.toolbox - INFO: dropped 1 lines with 0 line switches
hp.pandapower.toolbox - INFO: dropped 1 load elements
hp.pandapower.toolbox - INFO: dropped 0 lines with 0 line switches
hp.pandapower.toolbox [...]<jupyter_text>Now, the ward equivalent is obtained. We can verify the power flow results.<jupyter_code>print("--- power flow (original grid) ---")
display(net.res_bus)
print("--- power flow (reduced grid) ---")
display(net_eq_ward.res_bus)<jupyter_output>--- power flow (original grid) ---<jupyter_text>The power flow results (*vm_pu*, *va_degree*) for the internal buses [0, 3, 4, 8] in both grids are the same. The external area is represented by the addtional *ward* elements in the grid model "net_eq_ward", attached at the boundary buses [4, 8]:<jupyter_code>print("--- ward (original grid) ---")
display(net.ward)
print("--- ward (reduced grid) ---")
display(net_eq_ward.ward)<jupyter_output>--- ward (original grid) ---<jupyter_text>Defining the zones based on boundary branchesFor this example we will use the lines between the buses 4 ... 5 and 7 ... 8With the function *set_bus_zone_by_boundary_branches* we first define the zones of the grid based on this separation. Thereafter, with the function *get_boundaries_by_bus_zone_with_boundary_branches*, we obtain the boundary buses that we can use with the functions for obtaining the grid equivalents, as showed in previous sections.<jupyter_code>boundary_branches = {"line": [2, 7]}
pp.grid_equivalents.set_bus_zone_by_boundary_branches(net, boundary_branches)
buses, branches = pp.grid_equivalents.get_boundaries_by_bus_zone_with_boundary_branches(net)<jupyter_output><empty_output><jupyter_text>The dictionary *buses* contains the biundary buses, internal buses and external buses from the point of view of each of the zones.<jupyter_code>buses<jupyter_output><empty_output><jupyter_text>The resulting separation can be seen in the figure below. The green buses are the nodes of the boundary lines that are part of the internal zone. The red buses are the nodes of the boundary lines that are in the external zone. The red dashed lines are the boundary lines.<jupyter_code>zone = 1

pp.plotting.generic_geodata.create_generic_coordinates(net, overwrite=True)
pp.plotting.plotting_toolbox.set_line_geodata_from_bus_geodata(net, overwrite=True)
pp.plotting.geo.convert_geodata_to_gis(net)

fig, ax=plt.subplots(figsize=(7,11))

net.line_geodata.plot(ax=ax)
net.line_geodata.loc[list(boundary_branches["line"])].plot(ax=ax, color='red', linestyle="--")
net.bus_geodata.plot(column=net.bus.zone.values, ax=ax,zorder=10)
net.bus_geodata.loc[net.ext_grid.bus.values].plot(ax=ax, color='k', marker="s", markersize=200)

net.bus_geodata.loc[list(buses[zone]["external"])].plot(color='r', ax=ax, zorder=100, markersize=100)
net.bus_geodata.loc[list(buses[zone]["internal"])].plot(color='g', ax=ax, zorder=100, markersize=100)<jupyter_output><empty_output><jupyter_text>Now, we can obtain the grid equivalent to reduce the zone 0<jupyter_code>b_internal = [net.bus.loc[net.bus.zone==1].index[0]]
net_eq = pp.grid_equivalents.get_equivalent(net, "rei", buses[1]["internal"], b_internal)
net_eq.bus<jupyter_output><empty_output><jupyter_text>Grid equivalents with DC lines<jupyter_code>pp.drop_lines(net, [2])
pp.create_dcline(net, 4, 5, 50, 0.5, 0.7, 1.0, 1.0)
pp.runpp(net)
net_eq = pp.grid_equivalents.get_equivalent(net, "rei", [4,8], [0])
net_eq.bus<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09530372097953992, 'fraction_numerical': 0.014417470581999364, 'mean_word_length': 5.331543624161074, 'pattern_counts': {'":': 1, '<': 51, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '268472', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 3077, 'n_tokens_neox': 2876, 'n_words': 1048, 'path': 'tutorials/grid_equivalents.ipynb', 'repo_name': 'flohirschmann8/pandapower', 'size': '9433'}