### Resolve AC-PF and see whether a cascade unfolds
ifisempty(solpath)==false# save final network data
calc_cascade!(network_data,method,print_level)
save(solpath,"network_data",network_data)
end
end
returnnothing
returnnothing
...
@@ -209,42 +198,67 @@ end
...
@@ -209,42 +198,67 @@ end
Calculates whether a cascading failure unfolds in a damaged network. If any network contained in network_data misses a slack bus, the largest generator is selected in each connected component. Additionally, the active power balance is restored for each connected component in every step, if it is violated.
Calculates whether a cascading failure unfolds in a damaged network. If any network contained in network_data misses a slack bus, the largest generator is selected in each connected component. Additionally, the active power balance is restored for each connected component in every step, if it is violated.
=#
=#
function calc_cascade!(
function calc_cascade!(
network_data::Dict{String,<:Any},
network_data::Dict{String,<:Any},# network with destroyed lines
method=:JuMP,
method=:JuMP,
print_level=0
print_level=5,# level of detail for Ipopt output
logpath="",# optional path to .log file for saving logs of interest
solpath=""# path for saving results/solutions of interest
Restores active power balance in a connected component identified by the set of buses cc. Depending on whether an overproduction or underproduction exists, generator dispatches may be increased or reduced. If necessary, load can be shed by reducing the demands uniformly until the total demand matches generation. For more details see flow chart.
Restores active power balance in a connected component identified by the set of buses cc. Depending on whether an overproduction or underproduction exists, generator dispatches may be increased or reduced. If necessary, load can be shed by reducing the demands uniformly until the total demand matches generation. For more details see flow chart.
=#
=#
function _restore_p_balance!(network_data::Dict{String,<:Any},cc::Set{Int64})
function _restore_p_balance!(
network_data::Dict{String,<:Any},
cc::Set{Int64},
cc_i::Int64# index/number of connected component cc
)
active_cc_gens=Int64[
active_cc_gens=Int64[
gen["index"]forgeninvalues(network_data["gen"])if
gen["index"]forgeninvalues(network_data["gen"])if
gen["gen_bus"]∈cc&&gen["gen_status"]!=0
gen["gen_bus"]∈cc&&gen["gen_status"]!=0
...
@@ -282,9 +300,14 @@ function _restore_p_balance!(network_data::Dict{String,<:Any}, cc::Set{Int64})
...
@@ -282,9 +300,14 @@ function _restore_p_balance!(network_data::Dict{String,<:Any}, cc::Set{Int64})
network_data,active_cc_gens,active_cc_loads,cc
network_data,active_cc_gens,active_cc_loads,cc
)
)
info(_LOGGER,"Active power mismatch in CC #$cc_i: $cc_Δp")
ifisapprox(cc_Δp,0,atol=1e-10)# "sufficient" power balance
ifisapprox(cc_Δp,0,atol=1e-10)# "sufficient" power balance
nothing# nothing has to be done
nothing# nothing has to be done
elseifcc_Δp>0# overproduction
elseifcc_Δp>0# overproduction
debug(_LOGGER,"Overproduction in CC #$cc_i: $cc_Δp")
ifisapprox(cc_Δp_lim,0,atol=1e-10)# power balance at minimum
ifisapprox(cc_Δp_lim,0,atol=1e-10)# power balance at minimum
### Set all active generators to their minimum
### Set all active generators to their minimum
forginactive_cc_gens
forginactive_cc_gens
...
@@ -412,6 +435,8 @@ function _reduce_p_dispatch!(
...
@@ -412,6 +435,8 @@ function _reduce_p_dispatch!(
)# repeat
)# repeat
end
end
# info(_LOGGER, "2 Active power mismatch in CC #1: $cc_Δp")