powergrid_synth.core
Core utilities shared by both transmission and distribution synthesis pipelines.
Submodules
Package Contents
- class powergrid_synth.core.DCPowerFlow(graph)[source]
Lightweight DC Power Flow (DCPF) solver.
Solves the linearised power flow equations
\[\mathbf{P} = \mathbf{B}\,\boldsymbol{\theta}, \qquad F_{ij} = \frac{\theta_i - \theta_j}{x_{ij}}\]where \(\mathbf{B}\) is the bus susceptance matrix, \(\boldsymbol{\theta}\) the vector of voltage angles (radians), \(\mathbf{P}\) the vector of net real-power injections (per-unit on a 100 MVA base), and \(F_{ij}\) the real-power flow on branch \((i, j)\).
The slack bus (reference angle \(\theta = 0\)) is chosen as the bus hosting the largest generator. The solver uses a sparse direct factorisation via
scipy.sparse.linalg.spsolve.This class is used by
TransmissionLineAllocatorto compute the flow distribution needed for impedance swapping and capacity assignment, following the methodology of Sadeghian et al. (2018).- Parameters:
graph (networkx.Graph) – Power grid graph. Each edge must have an
'x'attribute (per-unit reactance). Each node may have'pg'(generation MW) and'pl'(load MW) attributes.
See also
powergrid_synth.transmission.TransmissionLineAllocatorUses DCPF for impedance swapping and capacity assignment.
- run()[source]
Execute the DC power flow and return branch flows and bus angles.
Algorithm
Build the susceptance matrix \(\mathbf{B}\) from branch reactances: \(B_{ij} = -1/x_{ij}\), \(B_{ii} = \sum_j 1/x_{ij}\).
Form the net injection vector \(P_i = (P_{g_i} - P_{L_i}) / S_{\text{base}}\).
Select the slack bus (largest generator), remove its row/column, and solve \(\mathbf{B}_{\text{red}}\, \boldsymbol{\theta}_{\text{red}} = \mathbf{P}_{\text{red}}\).
Compute branch flows \(F_{ij} = (\theta_i - \theta_j) / x_{ij} \times S_{\text{base}}\) (MW).
- returns:
flows (dict[tuple[int, int], float]) – Branch power flows in MW, keyed by
(u, v)node pairs.angles (dict[int, float]) – Bus voltage angles in radians, keyed by node id.
- class powergrid_synth.core.DistributionGrid(incoming_graph_data=None, **attr)[source]
Bases:
PowerGridGraphGraph representation of a radial distribution feeder.
Inherits from
PowerGridGraphand adds convenience properties for radial-tree distribution grids annotated with hop distances, node types, and cable parameters (Schweitzer et al. 2017 format).- classmethod from_nx(G)[source]
Create a DistributionGrid from any NetworkX graph.
All node, edge, and graph attributes are copied.
- Parameters:
G (networkx.Graph)
- Return type:
- nodes_at_hop(h)[source]
Return list of nodes at the given hop distance.
- Parameters:
h (int)
- Return type:
list
- nodes_by_type(node_type)[source]
Return list of nodes with the given
node_typeattribute.- Parameters:
node_type (str) – One of
'load','injection', or'intermediate'.- Return type:
list
- property is_radial: bool
True if the graph is a connected tree.
- Return type:
bool
- property max_hop: int
Maximum hop distance in the feeder.
- Return type:
int
- property root
Return the root node (hop distance 0).
- property total_gen_mw: float
Total real-power generation (MW) across all injection nodes.
- Return type:
float
- property total_load_mw: float
Total real-power load (MW) across all load nodes.
- Return type:
float
- class powergrid_synth.core.GraphComparator(synth_graph, ref_graph, synth_label='Synthetic', ref_label='Reference (Real)')[source]
Compares a synthetic power grid against a reference (real-world) graph. Provides tabular metric comparisons and visual distribution overlaps, both globally and per voltage level.
- Parameters:
synth_graph (networkx.Graph)
ref_graph (networkx.Graph)
synth_label (str)
ref_label (str)
- _get_comparison_data(graph1, graph2)[source]
Helper to generate the dataframe for two specific graphs.
- Parameters:
graph1 (networkx.Graph)
graph2 (networkx.Graph)
- Return type:
pandas.DataFrame
- compare_degree_distributions(show_pvalue=False)[source]
Computes Kolmogorov-Smirnov (KS) and Relative Hausdorff (RH) statistics between the degree distributions of the synthetic and reference graphs, per voltage level. Prints and returns the results table.
- Parameters:
show_pvalue (bool) – If True, include the KS p-value column. Default False.
- Returns:
pd.DataFrame with columns Level, KS Statistic, RH Distance (and KS p-value if show_pvalue is True).
- Return type:
pandas.DataFrame
- plot_all_levels_comparison(log_scale=True)[source]
Plots degree comparison for all common voltage levels in a single figure.
- Parameters:
log_scale (bool)
- plot_degree_comparison(synth_graph=None, ref_graph=None, ax=None, log_scale=True, fig_size=(8, 5), show_lines=False, title='Degree Distribution Comparison')[source]
Plots overlaid degree distributions.
- Parameters:
synth_graph (Optional[networkx.Graph]) – Custom synthetic graph (or None for self.synth_graph).
ref_graph (Optional[networkx.Graph]) – Custom reference graph (or None for self.ref_graph).
ax (Optional[matplotlib.pyplot.Axes]) – Matplotlib axis to plot on. If None, creates new figure.
log_scale (bool) – Whether to use log-log scale (default True).
title (str) – Title for the plot.
fig_size (Tuple)
show_lines (bool)
- plot_level_topology_comparison(figsize=(15, 10))[source]
Plots side-by-side bar comparisons for topology metrics per voltage level: Nodes, Edges, Diameter, Avg Path Length, Avg Clustering.
- Parameters:
figsize (Tuple[int, int])
- print_level_metrics()[source]
Iterates through voltage levels found in both graphs and prints metrics. Does NOT plot.
- class powergrid_synth.core.GridAnalyzer(graph)[source]
A class to perform topological analysis on power grid graphs. Can be used for both synthetic and real-world grids.
- Parameters:
graph (nx.Graph) – The networkx graph object representing the power grid.
- get_basic_stats()[source]
Returns fundamental counts (nodes, edges, density).
- Returns:
A dictionary containing ‘num_nodes’, ‘num_edges’, and ‘density’.
- Return type:
Dict[str, Any]
- get_clustering_metrics()[source]
Calculates global and average local clustering coefficients.
- Return type:
Dict[str, float]
- get_path_metrics()[source]
Calculates path-based metrics: Diameter and Average Shortest Path Length.
- Return type:
Dict[str, Any]
- plot_degree_distribution(ax=None, log_scale=True, figsize=(6, 4), title='Degree Distribution')[source]
Plots the degree distribution.
- Parameters:
ax (Optional[matplotlib.pyplot.Axes]) – Matplotlib axes to plot on. If None, creates a new figure.
log_scale (bool) – If True, plots log-log. If False, plots linear histogram.
figsize (tuple) – Size of figure if creating a new one.
title (str) – Title of the plot.
- class powergrid_synth.core.GridVisualizer[source]
Visualization module for synthetic power grids. Allows plotting the grid with different layouts including Yifan Hu, Kamada-Kawai, and Voltage Layered.
- _create_interactive_window(graph, title, figsize)[source]
Helper to create a figure with a Dropdown menu for layout selection.
- Parameters:
graph (networkx.Graph)
title (str)
figsize (Tuple[int, int])
- _draw_bus_types_on_ax(ax, graph, layout_name, title, legend_loc='center left', legend_bbox=(1, 0.5), bbox_transform=None, show_impedance=False)[source]
Helper to draw bus type visualization on a specific axis.
- Parameters:
graph (networkx.Graph)
layout_name (str)
title (str)
show_impedance (bool)
- _draw_graph_on_ax(ax, graph, layout_name, title, show_labels, legend_loc='upper right', legend_bbox=None, bbox_transform=None, show_impedance=False)[source]
Helper to draw graph on a specific axis.
- Parameters:
show_impedance (bool)
- _find_tree_root(tree)[source]
Find the best root for a tree: prefer lowest voltage_level, then highest degree.
- Parameters:
tree (networkx.Graph)
- Return type:
Any
- _get_layered_layout(graph)[source]
Custom layout: Places nodes in horizontal bands based on voltage level.
- Parameters:
graph (networkx.Graph)
- Return type:
Dict[int, numpy.ndarray]
- _get_node_colors(graph)[source]
Assigns colors to nodes based on their ‘voltage_level’ attribute.
- Parameters:
graph (networkx.Graph)
- Return type:
List[Any]
- _hierarchical_tree_layout(graph, layer_sep=1.0, node_sep=1.0)[source]
Hierarchical top-down layout suitable for tree/forest graphs.
Root at the top, children below. Handles disconnected forests by placing each component side-by-side.
- Parameters:
graph (networkx.Graph)
layer_sep (float)
node_sep (float)
- Return type:
Dict[Any, numpy.ndarray]
- _radial_tree_layout(graph, radius_step=1.0)[source]
Radial layout suitable for tree/forest graphs.
Root at the center, each BFS layer on a concentric circle. Handles disconnected forests by rotating each component into its own sector.
- Parameters:
graph (networkx.Graph)
radius_step (float)
- Return type:
Dict[Any, numpy.ndarray]
- _yifan_hu_layout(G, iterations=100, k=None)[source]
Implementation of the Yifan Hu force-directed layout algorithm.
- Parameters:
G (networkx.Graph)
iterations (int)
k (Optional[float])
- Return type:
Dict[int, numpy.ndarray]
- plot_bus_types(graph, layout='kamada_kawai', title='Bus Type Visualization', show_impedance=False, figsize=(12, 10))[source]
Visualizes the grid coloring nodes by their Bus Type (Static). Option to show impedance on edges.
- Parameters:
graph (networkx.Graph)
layout (str)
title (str)
show_impedance (bool)
figsize (Tuple[int, int])
- plot_grid(graph, layout='kamada_kawai', title='Grid', show_labels=False, show_bus_types=False, show_impedance=False, figsize=(12, 10))[source]
Static plot function for grid topology. Options allow overlaying bus types or impedance features.
- Parameters:
graph (networkx.Graph)
layout (str)
title (str)
show_labels (bool)
show_bus_types (bool)
show_impedance (bool)
figsize (Tuple[int, int])
- plot_impedance(grid, layout='kamada_kawai', title='Transmission Line Impedance', figsize=(12, 10))[source]
Plots the grid with edges colored by their impedance magnitude (Z). Blue = Low Impedance (Strong), Red = High Impedance (Weak).
- Parameters:
grid (networkx.Graph)
layout (str)
title (str)
figsize (Tuple[int, int])
- plot_interactive(graph, title='Interactive Grid', figsize=(14, 10))[source]
Opens an interactive window for the full grid.
- Parameters:
graph (networkx.Graph)
title (str)
figsize (Tuple[int, int])
- plot_interactive_bus_types(graph, title='Interactive Bus Type Visualization', figsize=(14, 10))[source]
Opens an interactive window for Bus Type Visualization with layout selection.
- Parameters:
graph (networkx.Graph)
title (str)
figsize (Tuple[int, int])
- plot_interactive_voltage_level(graph, level, title=None, figsize=(12, 10))[source]
Opens an interactive window for a specific voltage level.
- Parameters:
graph (networkx.Graph)
level (int)
title (Optional[str])
figsize (Tuple[int, int])
- plot_load_gen_bubbles(grid, layout='kamada_kawai', title='Generation vs Load', show_impedance=False, figsize=(12, 10))[source]
Bubble plot showing generation and load magnitudes. Generators are blue squares, Loads are red circles. Size is proportional to capacity/load. Optionally plots impedance on edges.
- Parameters:
grid (networkx.Graph)
layout (str)
title (str)
show_impedance (bool)
figsize (Tuple[int, int])
- plot_subgraphs(grid, layout='kamada_kawai', title='Subgraphs by Voltage Level', show_impedance=False, figsize=(15, 5))[source]
Plots subgraphs for each voltage level side-by-side (max 3 per row).
- Parameters:
grid (nx.Graph) – The main power grid graph.
layout (str) – Layout algorithm to use.
title (str) – Main title for the figure.
show_impedance (bool) – Whether to color edges by impedance.
figsize (Tuple[int, int]) – Base size for the figure (width, height for one row). Height will scale with the number of rows.
- class powergrid_synth.core.HierarchicalAnalyzer(graph)[source]
A wrapper class that manages analysis for multi-level power grids. It can perform a global analysis and then iterate through each voltage level to perform subgraph analysis.
- Parameters:
graph (networkx.Graph)
- plot_all_levels(log_scale=True)[source]
Plots degree distributions for all voltage levels in a single figure (subplots).
- Parameters:
log_scale (bool) – If True, uses log-log scale. If False, uses linear scale.
- class powergrid_synth.core.PowerGridGraph(incoming_graph_data=None, **attr)[source]
Bases:
networkx.GraphCustom NetworkX Graph for Power Grids. Extends nx.Graph to support subgraph extraction by voltage level.
- class powergrid_synth.core.TransmissionGrid(incoming_graph_data=None, **attr)[source]
Bases:
PowerGridGraphGraph representation of a transmission-level power grid.
Inherits from
PowerGridGraphand adds convenience methods specific to meshed, multi-voltage-level transmission networks.- property n_levels: int
Number of distinct voltage levels.
- Return type:
int
- property voltage_levels: list[int]
Sorted list of distinct voltage levels present in the grid.
- Return type:
list[int]
- powergrid_synth.core.extract_topology_params_from_graph(G)[source]
Extract CLC model inputs from an existing power grid graph.
This is “operation mode I”, where the generator is configured to mimic an existing reference grid. The function extracts per-level degree sequences and diameters (Phase 1 inputs), as well as pairwise transformer degree sequences (Phase 2 inputs).
- Parameters:
G (networkx.Graph) – Power grid graph with a
'voltage_level'attribute on every node.- Returns:
'degrees_by_level'list of list of intIntra-level degree sequences (one per voltage level, ordered by ascending voltage label).
'diameters_by_level'list of intDiameter of the largest connected component of each same-voltage subgraph.
'transformer_degrees'dict{(i, j): (deg_i_to_j, deg_j_to_i)}for each pair of voltage levels that has at least one transformer edge.
- Return type:
dict