Decomposing Problems
Methods to decompose and solve the SinglePhase
Branch Flow Model are provided based on the work in [2]. These methods are most advantageous when solving the non-linear (unrelaxed) power flow equations and are only valid(?) in radial networks.
CommonOPF.split_network
— Functionsplit_network(net::Network, bus::String)::Tuple{Network, Network}
Split net
into one Network
for everything above bus
and one Network
for everything below bus
.
split_network(net::Network, bus::String, out_busses::Vector{String})::Tuple{Network, Network}
Split net
into net_above
and net_below
where net_below
has only out_busses
and net_above
has union( [bus], setdiff(busses(net), out_busses) )
. We want to keep bus in both networks because there can be multiple branches out of bus that are not in out_busses.
Note that out_busses
must contain bus
CommonOPF.init_split_networks!
— Functioninit_split_networks!(nets::Vector{Network{SinglePhase}}; init_vs::Dict = Dict())
Set the loads on the upstream leaf nodes equal to the sum of all the loads in the downstream nodes. It is important that the order of nets
is from leaf branches to trunk branches so that the sums of loads take into account all downstream sub-trees.
if init_vs
is provided, the net.v0
is set for the Input
with its net.substation_bus
equal to the key in init_vs
init_vs = Dict(
"sub_bus_1" => 0.98
)
for net in nets
if net.substation_bus in keys(init_vs)
net.v0 = init_vs[net.substation_bus]
end
end
init_split_networks!(mg::MetaGraphsNext.MetaGraph; init_vs::Dict = Dict())
Use the :load_sum_order
in mg
to init_split_networks!
in the correct order, i.e. set the loads at the leaf - substation connections as sums of all the loads (and the voltages at substations)
CommonOPF.splitting_busses
— Functionsplitting_busses(net::Network, source::String; threshold::Int64=10)
Determine the busses to split a tree graph on by searching upward from the deepest leafs first and gathering the nearest busses until threshold is met for each subgraph.
Returns a Vector{String}
for the bus names to split on and Vector{Vector{String}}
for the corresponding busses within each sub-graph.
It is not enough to have only the splitting busses to obey the max_busses
limit because one must also know which sub branches to take from each splitting bus. In other words, we also need all the busses within each subgraph to split properly. For example, if a splitting bus has two sub branches then obeying the max_busses limit can require only including one sub branch out of the splitting bus. To know which branch to take we can use the other busses in the sub graph (which is why this method also returns the bussed in each subgraph).
CommonOPF.split_at_busses
— Functionsplit_at_busses(net::Network, at_busses::Vector{String})
Split net.graph
using the at_busses
returns directed MetaGraph
with vertices containing Network
for the sub-graphs using integer vertex labels. For example mg[2]
is the Network
at the second vertex of the graph created by splitting the network via the at_busses
.
split_at_busses(net::Network, at_busses::Vector{String}, with_busses::Vector{Vector{String}})
Split up p
using the at_busses
as each new substation_bus
and containing the corresponding with_busses
. The at_busses
and with_busses
can be determined using splitting_busses
.
NOTE: this variation of spltatbusses allows for more than two splits at the same bus; whereas the other implementation of splitatbusses only splits the network into two parts for everything above and everything below a splitting bus.
[2]
Sadnan, Rabayet, and Anamika Dubey. "Distributed optimization using reduced network equivalents for radial power distribution systems." IEEE Transactions on Power Systems 36.4 (2021): 3645-3656.