VeraGridEngine.Topology.Procedural package

Submodules

VeraGridEngine.Topology.Procedural.procedural_grid_creation module

class VeraGridEngine.Topology.Procedural.procedural_grid_creation.ProceduralGrid[source]

Bases: object

Class to chracterize and create grids procedurally

state_index: Dict[DeviceType, int]
states: List[DeviceType]
train(grid: MultiCircuit)[source]

Fill the transition probabilities with the grid information :param grid: :return:

transition_probabilities: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[int, int], dtype[float64]]

VeraGridEngine.Topology.Procedural.procedural_grid_debugger module

class VeraGridEngine.Topology.Procedural.procedural_grid_debugger.ProceduralGridDebugger(enabled: bool = True)[source]

Bases: object

Helper class for plotting and validating intermediate results during procedural grid generation.

This class should only contain debug/inspection utilities and must not modify the production objects.

enabled
get_added_element_names(grid: MultiCircuit, previous_names: set[str]) list[str][source]

Return the names of the elements that were added to the grid after a previous snapshot.

Parameters:
  • grid – MultiCircuit instance

  • previous_names – Snapshot of names taken before modification

Returns:

Sorted list of newly added element names

plot_mst_graph(coords_final_network: ndarray, edges: List[Tuple[int, int]], n_candidate: int, n_target: int, final_steiner_pts: ndarray, title: str = 'Procedural Grid Graph', show_labels: bool = True) None[source]

Plot the graph defined by node coordinates and edge list.

Parameters:
  • coords_final_network – Array of shape (n_nodes, 2) with [lon, lat]

  • edges – List of node index pairs

  • n_candidate – Number of candidate buses

  • n_target – Number of target buses

  • final_steiner_pts – Array of Steiner point coordinates

  • title – Plot title

  • show_labels – Whether to label nodes with their indices

snapshot_grid_element_names(grid: MultiCircuit) set[str][source]

Take a snapshot of the current element names in the grid.

Parameters:

grid – MultiCircuit instance

Returns:

Set of element names currently present in the grid

VeraGridEngine.Topology.Procedural.procedural_grid_engine module

class VeraGridEngine.Topology.Procedural.procedural_grid_engine.ProceduralGridComputationEngine(grid: MultiCircuit, method: ProceduralGridMethods, targets: List[dev.Substation], candidates: List[dev.Substation], logger: Logger | None = None)[source]

Bases: object

Core engine for procedural grid expansion calculations.

get_buses() List[Bus][source]

Get list of all the incumbent buses in the calculation :return:

get_existing_fixed_bus_connections() set[tuple[int, int]][source]

Build the set of existing direct connections between fixed buses (candidate + target) in graph-index form.

The returned index pairs are expressed in the same ordering used by ProceduralGridGraph.base_coords:

[candidate_buses…, target_buses…]

Returns:

Set of existing fixed-bus connections as index pairs

get_new_buses() List[Bus][source]

Get only the newly created buses (Steiner points + Markov intermediate buses). These have no substation assigned and need one for map rendering. :return:

get_new_lines() List[Line][source]

Get only the newly created Line objects added during topology generation. :return:

get_new_transformers() List[Transformer2W][source]

Get only the newly created Transformer2W objects added during topology generation. :return:

run_steiner_alone()[source]

Executes the Steiner Tree algorithm without further optimization.

run_steiner_tree_and_optimization(pf_options: PowerFlowOptions, max_eval_per_var: int) MultiCircuit[source]

Execute the Steiner tree topology generation first, then run an NSGA-3 catalogue-template optimization over the newly created branches.

The two-stage flow mirrors what the engine offers piecewise: first the topology is grown via run_steiner_alone(), which populates self.new_lines and self.new_transformers; then a synchronous catalogue optimization tunes the per-branch templates of those new branches only (existing infrastructure is left untouched). On completion the grid is left at the best Pareto member’s templates so the caller observes the optimizer’s top recommendation.

Parameters:
  • pf_options – power flow options used by the inner PF evaluations performed by the catalogue problem.

  • max_eval_per_var – per-decision-variable evaluation budget. The actual NSGA-3 evaluation cap becomes max_eval_per_var * problem.n_vars().

Returns:

the (in-place mutated) MultiCircuit reference.

class VeraGridEngine.Topology.Procedural.procedural_grid_engine.ProceduralGridGraph(target_buses: List[Bus], candidate_buses: List[Bus], max_iterations: int = 1000, logger: Logger | None = None)[source]

Bases: object

calculate_fitness(mu_lon: ndarray[tuple[Any, ...], dtype[float64]], mu_lat: ndarray[tuple[Any, ...], dtype[float64]])[source]

VSA Fitness: MST Length + Degree Penalty. :param mu_lat: steiner points latitudes :param mu_lon: steiner points longitudes

prune_redundant_nodes(steiner_coords: ndarray[tuple[Any, ...], dtype[float64]] | ndarray[tuple[int, int], dtype[float64]])[source]

Iteratively removes Steiner points with Degree <= 2. :param steiner_coords: steiner points coordinates (dim, (lon, lat))

remove_existing_edges(mst_matrix: ndarray, existing_connections: set[tuple[int, int]], n_fixed: int) ndarray[source]

Remove MST edges that already exist in the incumbent grid.

This method is graph-only: it does not know anything about VeraGrid objects. It only receives: - the MST matrix, - the set of existing fixed-node connections, - the number of fixed nodes (candidate + target).

Only edges between fixed nodes are checked. Edges involving Steiner nodes are always kept.

Parameters:
  • mst_matrix – MST adjacency matrix

  • existing_connections – Set of existing graph edges as index pairs

  • n_fixed – Number of fixed nodes at the beginning of the node ordering

Returns:

Filtered MST adjacency matrix

run_vsa()[source]
Returns:

best_solution (dim, (lat, lon))

class VeraGridEngine.Topology.Procedural.procedural_grid_engine.Topology(edges: list[tuple[int, int]], all_buses: List[dev.Bus], grid: MultiCircuit, transition_matrix: TransitionMatrix, discretization: float = 25.0, logger: Logger | None = None)[source]

Bases: object

Represents the physical layout using domain objects. Contains a Graph instance via composition.

add_branch_to_grid(branch) None[source]

Add a branch object to the correct container of the expansion grid.

find_voltage_path(start_v: float, end_v: float) list[float] | None[source]

Find a voltage path between start_v and end_v using the transitions available in template_dict.

Parameters:
  • start_v – Initial voltage

  • end_v – Final voltage

Returns:

List of voltages [start_v, …, end_v] or None if no path exists

generate_markov()[source]

Generates combinations that are valid by construction.

last_bus_fix(current_bus: Bus, output_bus: Bus, edge: tuple[int, int], intermediate_bus_counter: int) tuple[Bus, int][source]

Create a voltage bridge near the output bus so that the last geographical segment can still be connected and the final output voltage can be reached.

Strategy: - create a first bridge bus at the output coordinates with the same voltage

as current_bus,

  • connect current_bus to that first bridge bus later using the normal last line section,

  • create the remaining zero-length voltage transition chain from that first bridge bus to output_bus.

Parameters:
  • current_bus – Current bus at the start of the last slot

  • output_bus – Final target bus

  • edge – Edge being processed

  • intermediate_bus_counter – Counter for naming intermediate buses

Returns:

(first_bridge_bus, updated_intermediate_bus_counter)

class VeraGridEngine.Topology.Procedural.procedural_grid_engine.TransitionMatrix(grid: MultiCircuit)[source]

Bases: object

at(V1: float, V2: float)[source]

Get probability associated to V1, transitioning to V2 :param V1: Voltage Source :param V2: Voltage target :return: Probability of transition

get_most_likely_transition_voltage(V: float)[source]

Get the most likely voltage to transition to, given a voltage :param V: Some voltage source :return: The most likely voltage target

static template_dictionary(grid: MultiCircuit) Dict[float, Dict[float, List[tuple[object, float]]]][source]

Build a nested dictionary of branch templates grouped by voltage transition.

The outer key is the lower voltage (kV) and the inner key is the higher voltage (kV), so (132 kV β†’ 220 kV) is stored as template_dict[132.0][220.0]. Both voltages are sorted so that (132, 220) and (220, 132) map to the same entry.

The values are lists of (branch_object, probability) tuples where probability is assigned uniformly among all branches that share the same voltage transition.

Parameters:

grid – MultiCircuit instance

Returns:

Nested dict {v_lo: {v_hi: [(branch_object, probability), …]}}

VeraGridEngine.Topology.Procedural.procedural_grid_engine.coord_calc(current_bus_lon: float, current_bus_lat: float, length: float, coord_out: ndarray[tuple[Any, ...], dtype[float64]]) ndarray[tuple[Any, ...], dtype[float64]][source]

Calculate the coordinates of the next bus based on the current bus, the length to be covered (in km), and the output coordinates (in degrees).

The bearing must be computed in physical km space (not raw degree space) so that intermediate buses lie on the geographic straight line between the two endpoints. Using raw degree differences would distort the direction because 1Β° of longitude is shorter in km than 1Β° of latitude at non-equatorial latitudes.

Parameters:
  • current_bus_lon – Longitude of the current bus in degrees.

  • current_bus_lat – Latitude of the current bus in degrees.

  • length – Distance to advance toward coord_out in km.

  • coord_out – Target coordinates as [longitude, latitude] in degrees.

Returns:

New coordinates as [longitude, latitude] in degrees.

VeraGridEngine.Topology.Procedural.procedural_grid_engine.instantiate_branch_from_template(template_branch, current_bus: Bus, next_bus: Bus, length: float)[source]

Create a new branch object using an existing branch as template.

Module contents