RadialReduction

In this tutorial the RadialReduction network reduction algorithm is presented. This reduction eliminates radial (dangling) buses and their associated branches from the power network while preserving the electrical behavior of the core network.

Before diving into this tutorial we encourage the user to load PowerNetworkMatrices, hit the ? key in the REPL terminal and look for the documentation of RadialReduction.

Understanding Radial Branches

Radial buses are leaf nodes in the network topology with only one connection. These buses do not affect the electrical behavior of the rest of the network and can be safely eliminated to simplify network matrices and improve computational efficiency.

Basic Usage of RadialReduction

The RadialReduction can be applied when constructing various network matrices. The most common use case is with the Ybus matrix:

julia> using PowerNetworkMatrices
julia> using PowerSystemCaseBuilder
julia> const PNM = PowerNetworkMatricesPowerNetworkMatrices
julia> const PSB = PowerSystemCaseBuilderPowerSystemCaseBuilder
julia> # Load a test system sys = PSB.build_system(PSB.PSITestSystems, "c_sys14");[ Info: Deserializing with InMemoryTimeSeriesStorage is currently not supported. Using HDF [ Info: Loaded time series from storage file existing=/home/runner/.julia/packages/PowerSystemCaseBuilder/QOo1f/data/serialized_system/8584b9e729c8aa68ee5405660c6258cde1f67ed3b68f114823707912e9a0d16c/c_sys14_time_series_storage.h5 new=/tmp/jl_XBrCVf compression=InfrastructureSystems.CompressionSettings(false, InfrastructureSystems.CompressionTypesModule.CompressionTypes.DEFLATE = 1, 3, true) ┌ Warning: Invalid range valid_info.struct_name = "ACBus" field_name = "magnitude" valid_range = "voltage_limits" valid_info.ist_struct = ACBus: Bus 6: number: 6 name: Bus 6 available: true bustype: PowerSystems.ACBusTypesModule.ACBusTypes.PV = 2 angle: -0.24818581963359368 magnitude: 1.07 voltage_limits: (min = 0.94, max = 1.06) base_voltage: 13.8 area: nothing load_zone: nothing ext: Dict{String, Any}() InfrastructureSystems.SystemUnitsSettings: base_value: 100.0 unit_system: InfrastructureSystems.UnitSystemModule.UnitSystem.SYSTEM_BASE = 0 has_supplemental_attributes: false has_time_series: false @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/h2Bwp/src/validation.jl:219 ┌ Warning: Invalid range valid_info.struct_name = "ACBus" field_name = "magnitude" valid_range = "voltage_limits" valid_info.ist_struct = ACBus: Bus 7: number: 7 name: Bus 7 available: true bustype: PowerSystems.ACBusTypesModule.ACBusTypes.PQ = 1 angle: -0.23335052099164186 magnitude: 1.062 voltage_limits: (min = 0.94, max = 1.06) base_voltage: 13.8 area: nothing load_zone: nothing ext: Dict{String, Any}() InfrastructureSystems.SystemUnitsSettings: base_value: 100.0 unit_system: InfrastructureSystems.UnitSystemModule.UnitSystem.SYSTEM_BASE = 0 has_supplemental_attributes: false has_time_series: false @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/h2Bwp/src/validation.jl:219 ┌ Warning: Invalid range valid_info.struct_name = "ACBus" field_name = "magnitude" valid_range = "voltage_limits" valid_info.ist_struct = ACBus: Bus 8: number: 8 name: Bus 8 available: true bustype: PowerSystems.ACBusTypesModule.ACBusTypes.PV = 2 angle: -0.2331759880664424 magnitude: 1.09 voltage_limits: (min = 0.94, max = 1.06) base_voltage: 18.0 area: nothing load_zone: nothing ext: Dict{String, Any}() InfrastructureSystems.SystemUnitsSettings: base_value: 100.0 unit_system: InfrastructureSystems.UnitSystemModule.UnitSystem.SYSTEM_BASE = 0 has_supplemental_attributes: false has_time_series: false @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/h2Bwp/src/validation.jl:219 ┌ Warning: rating 2000.0 MW for Trans4 is 2x larger than the max expected rating 115.0 MW for Transformer at a 69.0 kV Voltage level. @ PowerSystems ~/.julia/packages/PowerSystems/f1vEv/src/utils/IO/branchdata_checks.jl:208 ┌ Warning: Transformer Trans2 per-unit reactance 0.25202 is higher than the typical range (min = 0.05, max = 0.2). Check if the reactance source data is correct. @ PowerSystems ~/.julia/packages/PowerSystems/f1vEv/src/utils/IO/branchdata_checks.jl:228 ┌ Warning: rating 2000.0 MW for Trans2 is 2x larger than the max expected rating 115.0 MW for Transformer at a 69.0 kV Voltage level. @ PowerSystems ~/.julia/packages/PowerSystems/f1vEv/src/utils/IO/branchdata_checks.jl:208 ┌ Warning: Transformer Trans3 per-unit reactance 0.20912 is higher than the typical range (min = 0.05, max = 0.2). Check if the reactance source data is correct. @ PowerSystems ~/.julia/packages/PowerSystems/f1vEv/src/utils/IO/branchdata_checks.jl:228 ┌ Warning: rating 2000.0 MW for Trans3 is 2x larger than the max expected rating 115.0 MW for Transformer at a 69.0 kV Voltage level. @ PowerSystems ~/.julia/packages/PowerSystems/f1vEv/src/utils/IO/branchdata_checks.jl:208 ┌ Warning: Transformer Trans1 per-unit reactance 0.55618 is higher than the typical range (min = 0.05, max = 0.2). Check if the reactance source data is correct. @ PowerSystems ~/.julia/packages/PowerSystems/f1vEv/src/utils/IO/branchdata_checks.jl:228 ┌ Warning: rating 2000.0 MW for Trans1 is 2x larger than the max expected rating 115.0 MW for Transformer at a 69.0 kV Voltage level. @ PowerSystems ~/.julia/packages/PowerSystems/f1vEv/src/utils/IO/branchdata_checks.jl:208 ┌ Warning: Invalid range valid_info.struct_name = "ThermalStandard" field_name = "reactive_power" valid_range = "reactive_power_limits" valid_info.ist_struct = ThermalStandard: Bus1: name: Bus1 available: true status: true bus: ACBus: Bus 1 active_power: 2.0 reactive_power: -0.169 rating: 2.324 active_power_limits: (min = 0.0, max = 3.332) reactive_power_limits: (min = 0.0, max = 0.1) ramp_limits: nothing operation_cost: PowerSystems.ThermalGenerationCost composed of variable: InfrastructureSystems.CostCurve{InfrastructureSystems.QuadraticCurve} base_power: 100.0 time_limits: nothing must_run: false prime_mover_type: PowerSystems.PrimeMoversModule.PrimeMovers.ST = 20 fuel: PowerSystems.ThermalFuelsModule.ThermalFuels.COAL = 1 services: 0-element Vector{PowerSystems.Service} time_at_status: 10000.0 dynamic_injector: nothing ext: Dict{String, Any}() InfrastructureSystems.SystemUnitsSettings: base_value: 100.0 unit_system: InfrastructureSystems.UnitSystemModule.UnitSystem.SYSTEM_BASE = 0 has_supplemental_attributes: false has_time_series: false @ InfrastructureSystems ~/.julia/packages/InfrastructureSystems/h2Bwp/src/validation.jl:219
julia> # Create Ybus with radial reduction ybus = Ybus(sys; network_reductions=[RadialReduction()]);ERROR: TypeError: in keyword argument network_reductions, expected Vector{NetworkReduction}, got a value of type Vector{RadialReduction}

Accessing Reduction Information

After applying the reduction, you can access information about which buses and branches were eliminated:

julia> # Get the network reduction data
       reduction_data = get_network_reduction_data(ybus);ERROR: UndefVarError: `ybus` not defined in `Main`
Suggestion: add an appropriate import or assignment. This global was declared but not assigned.
julia> # View the bus reduction mapping # This shows which buses were reduced to which parent buses get_bus_reduction_map(reduction_data)ERROR: UndefVarError: `reduction_data` not defined in `Main` Suggestion: add an appropriate import or assignment. This global was declared but not assigned.
julia> # View the reverse bus search mapping # This maps each reduced bus to its ultimate parent get_reverse_bus_search_map(reduction_data)ERROR: UndefVarError: `get_reverse_bus_search_map` not defined in `Main` Suggestion: check for spelling errors or missing imports.
julia> # View the removed arcs (branches) get_removed_arcs(reduction_data)ERROR: UndefVarError: `get_removed_arcs` not defined in `Main` Suggestion: check for spelling errors or missing imports.

Protecting Specific Buses from Reduction

In some cases, you may want to preserve certain buses even if they are radial. This can be done using the irreducible_buses parameter:

julia> # Create radial reduction that protects buses 101 and 205
       reduction = RadialReduction(irreducible_buses=[101, 205]);

Combining with Other Network Matrices

The RadialReduction can be applied to other network matrix types as well:

julia> # Apply to PTDF matrix
       ptdf = PTDF(sys; network_reductions=[RadialReduction()]);ERROR: TypeError: in keyword argument network_reductions, expected Vector{NetworkReduction}, got a value of type Vector{RadialReduction}
julia> # Apply to LODF matrix lodf = LODF(sys; network_reductions=[RadialReduction()]);ERROR: TypeError: in keyword argument network_reductions, expected Vector{NetworkReduction}, got a value of type Vector{RadialReduction}
julia> # Apply to Incidence Matrix incidence = IncidenceMatrix(sys; network_reductions=[RadialReduction()]);ERROR: TypeError: in keyword argument network_reductions, expected Vector{NetworkReduction}, got a value of type Vector{RadialReduction}

Benefits of Radial Reduction

Using RadialReduction provides several advantages:

  1. Smaller Matrices: Eliminates unnecessary rows and columns from network matrices
  2. Faster Computations: Reduced matrix dimensions lead to faster linear algebra operations
  3. Better Conditioning: Removing radial elements can improve numerical properties
  4. Memory Efficiency: Reduces storage requirements for large network models

Example: Comparing Matrix Sizes

julia> # Create Ybus without reduction
       ybus_full = Ybus(sys);[ Info: Finding subnetworks via iterative union find
julia> # Create Ybus with radial reduction ybus_reduced = Ybus(sys; network_reductions=[RadialReduction()]);ERROR: TypeError: in keyword argument network_reductions, expected Vector{NetworkReduction}, got a value of type Vector{RadialReduction}
julia> # Compare sizes size(get_ybus_data(ybus_full))ERROR: UndefVarError: `get_ybus_data` not defined in `Main` Suggestion: check for spelling errors or missing imports.
julia> size(get_ybus_data(ybus_reduced))ERROR: UndefVarError: `get_ybus_data` not defined in `Main` Suggestion: check for spelling errors or missing imports.

Combining Multiple Reductions

RadialReduction can be combined with other network reduction algorithms like DegreeTwoReduction:

julia> # Apply both radial and degree-two reductions
       reductions = [RadialReduction(), DegreeTwoReduction()];
julia> ybus_multi = Ybus(sys; network_reductions=reductions);[ Info: Finding subnetworks via iterative union find

Important Notes

  • Reference Bus Protection: Reference (slack) buses are automatically protected from elimination, regardless of their connectivity
  • Order Matters: When combining multiple reductions, they are applied in the order specified in the vector
  • Reversibility: The reduction maintains mapping information (bus_reduction_map and reverse_bus_search_map) that can be used for result interpretation
  • Electrical Equivalence: The reduced network maintains the same electrical behavior as the original network for all non-eliminated elements