From 8ebecd75ec1be000bbf3bdcdf5a90c4bbc25137c Mon Sep 17 00:00:00 2001 From: Carleton Coffrin Date: Mon, 1 Jan 2024 15:49:07 -0700 Subject: [PATCH] drop support for multiconductor, closes #872 --- CHANGELOG.md | 1 + src/core/base.jl | 19 ++----------------- src/core/data.jl | 35 ----------------------------------- src/core/objective.jl | 22 ++++++---------------- src/core/ref.jl | 23 +++++------------------ src/core/solution.jl | 4 ---- src/form/acp.jl | 16 ++++------------ src/form/acr.jl | 15 +++------------ src/form/apo.jl | 8 ++------ src/form/bf.jl | 16 +++------------- src/form/dcp.jl | 4 ++-- src/form/shared.jl | 20 ++++---------------- src/io/common.jl | 1 - src/io/json.jl | 1 - src/prob/tnep.jl | 4 +--- src/util/obbt.jl | 1 - test/data-mc.jl | 13 ------------- test/data.jl | 2 +- test/runtests.jl | 2 -- 19 files changed, 34 insertions(+), 173 deletions(-) delete mode 100644 test/data-mc.jl diff --git a/CHANGELOG.md b/CHANGELOG.md index 447a4336c..09a7feb9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ PowerModels.jl Change Log - Add support for models with mixtures of PWL and polynomial cost functions (#829) - Revised models to use two-sided constraints (#819) (breaking) - Rewrite code for building objective functions (#778) (breaking) +- Drop support for multiple conductors (#872) (breaking) - Drop support for `run_*` functions (#878) (breaking) - Drop support for JuMP v0.22 and v0.23 (breaking) - Drop support for JSON v0.18, v0.19, v0.20 (breaking) diff --git a/src/core/base.jl b/src/core/base.jl index 30bd2590a..ec6a40247 100644 --- a/src/core/base.jl +++ b/src/core/base.jl @@ -12,15 +12,6 @@ _IM.@def pm_fields begin end -"" -ismulticonductor(pm::AbstractPowerModel, nw::Int) = haskey(pm.ref[:it][pm_it_sym][:nw][nw], :conductors) -ismulticonductor(pm::AbstractPowerModel; nw::Int=nw_id_default) = haskey(pm.ref[:it][pm_it_sym][:nw][nw], :conductors) - -"" -conductor_ids(pm::AbstractPowerModel, nw::Int) = pm.ref[:it][pm_it_sym][:nw][nw][:conductor_ids] -conductor_ids(pm::AbstractPowerModel; nw::Int=nw_id_default) = pm.ref[:it][pm_it_sym][:nw][nw][:conductor_ids] - - "" function solve_model(file::String, model_type::Type, optimizer, build_method; kwargs...) data = PowerModels.parse_file(file) @@ -30,7 +21,7 @@ end "" function solve_model(data::Dict{String,<:Any}, model_type::Type, optimizer, build_method; ref_extensions=[], solution_processors=[], relax_integrality=false, - multinetwork=false, multiconductor=false, kwargs...) + multinetwork=false, kwargs...) if multinetwork != _IM.ismultinetwork(data) model_requirement = multinetwork ? "multi-network" : "single-network" @@ -38,12 +29,6 @@ function solve_model(data::Dict{String,<:Any}, model_type::Type, optimizer, buil Memento.error(_LOGGER, "attempted to build a $(model_requirement) model with $(data_type) data") end - if multiconductor != ismulticonductor(data) - model_requirement = multiconductor ? "multi-conductor" : "single-conductor" - data_type = ismulticonductor(data) ? "multi-conductor" : "single-conductor" - Memento.error(_LOGGER, "attempted to build a $(model_requirement) model with $(data_type) data") - end - start_time = time() pm = instantiate_model(data, model_type, build_method; ref_extensions=ref_extensions, kwargs...) Memento.debug(_LOGGER, "pm model build time: $(time() - start_time)") @@ -199,7 +184,7 @@ function ref_add_core!(ref::Dict{Symbol,Any}) ### aggregate info for pairs of connected buses ### if !haskey(nw_ref, :buspairs) - nw_ref[:buspairs] = calc_buspair_parameters(nw_ref[:bus], nw_ref[:branch], nw_ref[:conductor_ids], haskey(nw_ref, :conductors)) + nw_ref[:buspairs] = calc_buspair_parameters(nw_ref[:bus], nw_ref[:branch]) end end end diff --git a/src/core/data.jl b/src/core/data.jl index b76d16f74..0d3798ef8 100644 --- a/src/core/data.jl +++ b/src/core/data.jl @@ -1045,41 +1045,6 @@ function _calc_power_balance(data::Dict{String,<:Any}) end - - - -"" -function ismulticonductor(data::Dict{String,<:Any}) - pm_data = get_pm_data(data) - - if _IM.ismultinetwork(pm_data) - return all(_ismulticonductor(pm_nw_data) for (i, pm_nw_data) in pm_data["nw"]) - else - return _ismulticonductor(pm_data) - end -end - -function _ismulticonductor(data::Dict{String,<:Any}) - return haskey(data, "conductors") -end - - -"" -function check_conductors(data::Dict{String,<:Any}) - apply_pm!(_check_conductors, data) -end - - -"" -function _check_conductors(data::Dict{String,<:Any}) - if haskey(data, "conductors") && data["conductors"] < 1 - Memento.error(_LOGGER, "conductor values must be positive integers, given $(data["conductors"])") - end -end - - - - "checks that voltage angle differences are within 90 deg., if not tightens" function correct_voltage_angle_differences!(data::Dict{String,<:Any}, default_pad = 1.0472) pm_data = get_pm_data(data) diff --git a/src/core/objective.jl b/src/core/objective.jl index ac5c25051..c62c81e5e 100644 --- a/src/core/objective.jl +++ b/src/core/objective.jl @@ -196,19 +196,15 @@ function expression_pg_cost(pm::AbstractPowerModel; report::Bool=true) pg_cost = var(pm, n)[:pg_cost] = Dict{Int,Any}() for (i,gen) in ref(pm, n, :gen) - if isa(var(pm, n, :pg, i), Array) - pg_terms = [var(pm, n, :pg, i)[c] for c in conductor_ids(pm, n)] - else - pg_terms = [var(pm, n, :pg, i)] - end + pg_terms = [var(pm, n, :pg, i)] if gen["model"] == 1 if isa(pg_terms, Array{JuMP.VariableRef}) pmin = sum(JuMP.lower_bound.(pg_terms)) pmax = sum(JuMP.upper_bound.(pg_terms)) else - pmin = sum(gen["pmin"][c] for c in conductor_ids(pm, n)) - pmax = sum(gen["pmax"][c] for c in conductor_ids(pm, n)) + pmin = gen["pmin"] + pmax = gen["pmax"] end points = calc_pwl_points(gen["ncost"], gen["cost"], pmin, pmax) @@ -236,19 +232,15 @@ function expression_p_dc_cost(pm::AbstractPowerModel; report::Bool=true) for (i,dcline) in ref(pm, n, :dcline) arc = (i, dcline["f_bus"], dcline["t_bus"]) - if isa(var(pm, n, :pg, i), Array) - p_dc_terms = [var(pm, n, :p_dc, arc)[c] for c in conductor_ids(pm, n)] - else - p_dc_terms = [var(pm, n, :p_dc, arc)] - end + p_dc_terms = [var(pm, n, :p_dc, arc)] if dcline["model"] == 1 if isa(p_dc_terms, Array{JuMP.VariableRef}) pmin = sum(JuMP.lower_bound.(p_dc_terms)) pmax = sum(JuMP.upper_bound.(p_dc_terms)) else - pmin = sum(dcline["pminf"][c] for c in conductor_ids(pm, n)) - pmax = sum(dcline["pmaxf"][c] for c in conductor_ids(pm, n)) + pmin = dcline["pminf"] + pmax = dcline["pmaxf"] end # note pmin/pmax may be different from dcline["pminf"]/dcline["pmaxf"] in the on/off case @@ -386,8 +378,6 @@ end function objective_max_loadability(pm::AbstractPowerModel) nws = nw_ids(pm) - @assert all(!ismulticonductor(pm, n) for n in nws) - z_demand = Dict(n => var(pm, n, :z_demand) for n in nws) z_shunt = Dict(n => var(pm, n, :z_shunt) for n in nws) time_elapsed = Dict(n => get(ref(pm, n), :time_elapsed, 1) for n in nws) diff --git a/src/core/ref.jl b/src/core/ref.jl index 536d47164..c75513a28 100644 --- a/src/core/ref.jl +++ b/src/core/ref.jl @@ -8,7 +8,7 @@ end "compute bus pair level data, can be run on data or ref data structures" -function calc_buspair_parameters(buses, branches, conductor_ids, ismulticondcutor) +function calc_buspair_parameters(buses, branches) bus_lookup = Dict(bus["index"] => bus for (i,bus) in buses if bus["bus_type"] != 4) branch_lookup = Dict(branch["index"] => branch for (i,branch) in branches if branch["br_status"] == 1 && haskey(bus_lookup, branch["f_bus"]) && haskey(bus_lookup, branch["t_bus"])) @@ -17,28 +17,15 @@ function calc_buspair_parameters(buses, branches, conductor_ids, ismulticondcuto bp_branch = Dict((bp, typemax(Int)) for bp in buspair_indexes) - if ismulticondcutor - bp_angmin = Dict((bp, [-Inf for c in conductor_ids]) for bp in buspair_indexes) - bp_angmax = Dict((bp, [ Inf for c in conductor_ids]) for bp in buspair_indexes) - else - @assert(length(conductor_ids) == 1) - bp_angmin = Dict((bp, -Inf) for bp in buspair_indexes) - bp_angmax = Dict((bp, Inf) for bp in buspair_indexes) - end + bp_angmin = Dict((bp, -Inf) for bp in buspair_indexes) + bp_angmax = Dict((bp, Inf) for bp in buspair_indexes) for (l,branch) in branch_lookup i = branch["f_bus"] j = branch["t_bus"] - if ismulticondcutor - for c in conductor_ids - bp_angmin[(i,j)][c] = max(bp_angmin[(i,j)][c], branch["angmin"][c]) - bp_angmax[(i,j)][c] = min(bp_angmax[(i,j)][c], branch["angmax"][c]) - end - else - bp_angmin[(i,j)] = max(bp_angmin[(i,j)], branch["angmin"]) - bp_angmax[(i,j)] = min(bp_angmax[(i,j)], branch["angmax"]) - end + bp_angmin[(i,j)] = max(bp_angmin[(i,j)], branch["angmin"]) + bp_angmax[(i,j)] = min(bp_angmax[(i,j)], branch["angmax"]) bp_branch[(i,j)] = min(bp_branch[(i,j)], l) end diff --git a/src/core/solution.jl b/src/core/solution.jl index e67add962..3d8064485 100644 --- a/src/core/solution.jl +++ b/src/core/solution.jl @@ -4,10 +4,6 @@ function _IM.solution_preprocessor(pm::AbstractPowerModel, solution::Dict) for (nw_id, nw_ref) in nws(pm) solution["it"][pm_it_name]["nw"]["$(nw_id)"]["baseMVA"] = nw_ref[:baseMVA] - - if ismulticonductor(pm, nw_id) - solution["it"][pm_it_name]["nw"]["$(nw_id)"]["conductors"] = nw_ref[:conductors] - end end end diff --git a/src/form/acp.jl b/src/form/acp.jl index f40843765..3d15f6bfd 100644 --- a/src/form/acp.jl +++ b/src/form/acp.jl @@ -570,7 +570,7 @@ end "" -function constraint_storage_losses(pm::AbstractACPModel, n::Int, i, bus, r, x, p_loss, q_loss; conductors=[1]) +function constraint_storage_losses(pm::AbstractACPModel, n::Int, i, bus, r, x, p_loss, q_loss) vm = var(pm, n, :vm, bus) ps = var(pm, n, :ps, i) qs = var(pm, n, :qs, i) @@ -578,15 +578,7 @@ function constraint_storage_losses(pm::AbstractACPModel, n::Int, i, bus, r, x, p sd = var(pm, n, :sd, i) qsc = var(pm, n, :qsc, i) - JuMP.@NLconstraint(pm.model, - sum(ps[c] for c in conductors) + (sd - sc) - == - p_loss + sum(r[c]*(ps[c]^2 + qs[c]^2)/vm[c]^2 for c in conductors) - ) - - JuMP.@NLconstraint(pm.model, - sum(qs[c] for c in conductors) - == - qsc + q_loss + sum(x[c]*(ps[c]^2 + qs[c]^2)/vm[c]^2 for c in conductors) - ) + JuMP.@NLconstraint(pm.model, ps + (sd - sc) == p_loss + r*(ps^2 + qs^2)/vm^2) + JuMP.@NLconstraint(pm.model, qs == qsc + q_loss + x*(ps^2 + qs^2)/vm^2) end + diff --git a/src/form/acr.jl b/src/form/acr.jl index 6e4910e37..3ef1011e4 100644 --- a/src/form/acr.jl +++ b/src/form/acr.jl @@ -217,7 +217,7 @@ end "" -function constraint_storage_losses(pm::AbstractACRModel, n::Int, i, bus, r, x, p_loss, q_loss; conductors=[1]) +function constraint_storage_losses(pm::AbstractACRModel, n::Int, i, bus, r, x, p_loss, q_loss) vr = var(pm, n, :vr, bus) vi = var(pm, n, :vi, bus) ps = var(pm, n, :ps, i) @@ -226,17 +226,8 @@ function constraint_storage_losses(pm::AbstractACRModel, n::Int, i, bus, r, x, p sd = var(pm, n, :sd, i) qsc = var(pm, n, :qsc, i) - JuMP.@NLconstraint(pm.model, - sum(ps[c] for c in conductors) + (sd - sc) - == - p_loss + sum(r[c]*(ps[c]^2 + qs[c]^2)/(vr[c]^2 + vi[c]^2) for c in conductors) - ) - - JuMP.@NLconstraint(pm.model, - sum(qs[c] for c in conductors) - == - qsc + q_loss + sum(x[c]*(ps[c]^2 + qs[c]^2)/(vr[c]^2 + vi[c]^2) for c in conductors) - ) + JuMP.@NLconstraint(pm.model, ps + (sd - sc) == p_loss + r*(ps^2 + qs^2)/(vr^2 + vi^2)) + JuMP.@NLconstraint(pm.model, qs == qsc + q_loss + x*(ps^2 + qs^2)/(vr^2 + vi^2)) end diff --git a/src/form/apo.jl b/src/form/apo.jl index 821b543aa..646801176 100644 --- a/src/form/apo.jl +++ b/src/form/apo.jl @@ -276,16 +276,12 @@ function constraint_storage_current_limit(pm::AbstractActivePowerModel, n::Int, end "" -function constraint_storage_losses(pm::AbstractActivePowerModel, n::Int, i, bus, r, x, p_loss, q_loss; conductors=[1]) +function constraint_storage_losses(pm::AbstractActivePowerModel, n::Int, i, bus, r, x, p_loss, q_loss) ps = var(pm, n, :ps, i) sc = var(pm, n, :sc, i) sd = var(pm, n, :sd, i) - JuMP.@constraint(pm.model, - sum(ps[c] for c in conductors) + (sd - sc) - == - p_loss + sum(r[c]*ps[c]^2 for c in conductors) - ) + JuMP.@constraint(pm.model, ps + (sd - sc) == p_loss + r*ps^2) end function constraint_storage_on_off(pm::AbstractActivePowerModel, n::Int, i, pmin, pmax, qmin, qmax, charge_ub, discharge_ub) diff --git a/src/form/bf.jl b/src/form/bf.jl index cde93e9af..fbbd9df7f 100644 --- a/src/form/bf.jl +++ b/src/form/bf.jl @@ -192,23 +192,13 @@ end "Neglects the active and reactive loss terms associated with the squared current magnitude." -function constraint_storage_losses(pm::AbstractBFAModel, n::Int, i, bus, r, x, p_loss, q_loss; conductors=[1]) +function constraint_storage_losses(pm::AbstractBFAModel, n::Int, i, bus, r, x, p_loss, q_loss) ps = var(pm, n, :ps, i) qs = var(pm, n, :qs, i) sc = var(pm, n, :sc, i) sd = var(pm, n, :sd, i) qsc = var(pm, n, :qsc, i) - - JuMP.@constraint(pm.model, - sum(ps[c] for c in conductors) + (sd - sc) - == - p_loss - ) - - JuMP.@constraint(pm.model, - sum(qs[c] for c in conductors) - == - qsc + q_loss - ) + JuMP.@constraint(pm.model, ps + (sd - sc) == p_loss) + JuMP.@constraint(pm.model, qs == qsc + q_loss) end diff --git a/src/form/dcp.jl b/src/form/dcp.jl index 6fd1520ce..146237a66 100644 --- a/src/form/dcp.jl +++ b/src/form/dcp.jl @@ -365,12 +365,12 @@ function constraint_storage_on_off(pm::AbstractAPLossLessModels, n::Int, i, pmin end "" -function constraint_storage_losses(pm::AbstractAPLossLessModels, n::Int, i, bus, r, x, p_loss, q_loss; conductors=[1]) +function constraint_storage_losses(pm::AbstractAPLossLessModels, n::Int, i, bus, r, x, p_loss, q_loss) ps = var(pm, n, :ps, i) sc = var(pm, n, :sc, i) sd = var(pm, n, :sd, i) - JuMP.@constraint(pm.model, sum(ps[c] for c in conductors) + (sd - sc) == p_loss) + JuMP.@constraint(pm.model, ps + (sd - sc) == p_loss) end diff --git a/src/form/shared.jl b/src/form/shared.jl index 35dc54192..f252b8c6f 100644 --- a/src/form/shared.jl +++ b/src/form/shared.jl @@ -393,7 +393,7 @@ function constraint_current_limit(pm::AbstractWModels, n::Int, f_idx, c_rating_a end "" -function constraint_storage_losses(pm::AbstractWConvexModels, n::Int, i, bus, r, x, p_loss, q_loss; conductors=[1]) +function constraint_storage_losses(pm::AbstractWConvexModels, n::Int, i, bus, r, x, p_loss, q_loss) w = var(pm, n, :w, bus) ccms = var(pm, n, :ccms, i) ps = var(pm, n, :ps, i) @@ -402,19 +402,7 @@ function constraint_storage_losses(pm::AbstractWConvexModels, n::Int, i, bus, r, sd = var(pm, n, :sd, i) qsc = var(pm, n, :qsc, i) - for c in conductors - JuMP.@constraint(pm.model, ps[c]^2 + qs[c]^2 <= w[c]*ccms[c]) - end - - JuMP.@constraint(pm.model, - sum(ps[c] for c in conductors) + (sd - sc) - == - p_loss + sum(r[c]*ccms[c] for c in conductors) - ) - - JuMP.@constraint(pm.model, - sum(qs[c] for c in conductors) - == - qsc + q_loss + sum(x[c]*ccms[c] for c in conductors) - ) + JuMP.@constraint(pm.model, ps^2 + qs^2 <= w*ccms) + JuMP.@constraint(pm.model, ps + (sd - sc) == p_loss + r*ccms) + JuMP.@constraint(pm.model, qs == qsc + q_loss + x*ccms) end diff --git a/src/io/common.jl b/src/io/common.jl index a2ca21235..58a13130a 100644 --- a/src/io/common.jl +++ b/src/io/common.jl @@ -95,7 +95,6 @@ Runs various data quality checks on a PowerModels data dictionary. Applies modifications in some cases. Reports modified component ids. """ function correct_network_data!(data::Dict{String,<:Any}) - check_conductors(data) check_connectivity(data) check_status(data) check_reference_bus(data) diff --git a/src/io/json.jl b/src/io/json.jl index 432d3236d..06590d2f4 100644 --- a/src/io/json.jl +++ b/src/io/json.jl @@ -1,5 +1,4 @@ # Parse PowerModels data from JSON exports of PowerModels data structures. -# Necessary in order to support MultiConductorValues function _jsonver2juliaver!(pm_data) if haskey(pm_data, "source_version") && isa(pm_data["source_version"], Dict) diff --git a/src/prob/tnep.jl b/src/prob/tnep.jl index 53b4d6097..7036f1983 100644 --- a/src/prob/tnep.jl +++ b/src/prob/tnep.jl @@ -92,8 +92,6 @@ function _ref_add_ne_branch!(ref::Dict{Symbol,<:Any}, data::Dict{String,<:Any}) ref[:ne_bus_arcs] = ne_bus_arcs if !haskey(ref, :ne_buspairs) - ismc = haskey(ref, :conductors) - cid = ref[:conductor_ids] - ref[:ne_buspairs] = calc_buspair_parameters(ref[:bus], ref[:ne_branch], cid, ismc) + ref[:ne_buspairs] = calc_buspair_parameters(ref[:bus], ref[:ne_branch]) end end diff --git a/src/util/obbt.jl b/src/util/obbt.jl index c8c60e86f..a6cfa388e 100644 --- a/src/util/obbt.jl +++ b/src/util/obbt.jl @@ -85,7 +85,6 @@ function solve_obbt_opf!(data::Dict{String,<:Any}, optimizer; model_relaxation = instantiate_model(data, model_type, PowerModels.build_opf) (_IM.ismultinetwork(model_relaxation, pm_it_sym)) && (Memento.error(_LOGGER, "OBBT is not supported for multi-networks")) - (ismulticonductor(model_relaxation)) && (Memento.error(_LOGGER, "OBBT is not supported for multi-conductor networks")) # check for model_type compatability with OBBT _check_variables(model_relaxation) diff --git a/test/data-mc.jl b/test/data-mc.jl deleted file mode 100644 index ec8cf1bfb..000000000 --- a/test/data-mc.jl +++ /dev/null @@ -1,13 +0,0 @@ -@testset "test multiconductor data" begin - - @testset "multiconductor calc_theta_delta_bounds" begin - data = PowerModels.parse_file("../test/data/matpower/case5.m") - data["conductors"] = 1 - - theta_lb, theta_ub = calc_theta_delta_bounds(data) - - @test theta_lb[1] <= -2.0 - @test theta_ub[1] >= 2.0 - end - -end \ No newline at end of file diff --git a/test/data.jl b/test/data.jl index d5af341fb..006f43799 100644 --- a/test/data.jl +++ b/test/data.jl @@ -593,7 +593,7 @@ end @testset "5-bus test" begin data = PowerModels.parse_file("../test/data/matpower/case5.m") data["branch"]["4"]["br_status"] = 0 - data["buspairs"] = PowerModels.calc_buspair_parameters(data["bus"], data["branch"], 1:1, false) + data["buspairs"] = PowerModels.calc_buspair_parameters(data["bus"], data["branch"]) result = solve_opf(data, ACPPowerModel, nlp_solver) @test result["termination_status"] == LOCALLY_SOLVED diff --git a/test/runtests.jl b/test/runtests.jl index 1c7538dd9..f1dc0af1b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -45,8 +45,6 @@ include("common.jl") include("data.jl") - include("data-mc.jl") - include("data-basic.jl") include("model.jl")