From a719b27e21fe1c2e750e04891d21d002cd0f217c Mon Sep 17 00:00:00 2001 From: Juan Ospina Date: Fri, 26 Apr 2024 15:07:56 -0600 Subject: [PATCH] REF: prob. formulations to remove unnecessary loops when creating the KCL constraints. This significantly reduces the time to create the ITD JuMP models. --- CHANGELOG.md | 6 +- Project.toml | 2 +- src/core/base.jl | 4 +- src/core/ref.jl | 13 +- src/form/acp.jl | 7 +- src/form/acr.jl | 6 +- src/form/boundary.jl | 162 +++++++++------------- src/form/fbs.jl | 3 +- src/form/fotp.jl | 5 +- src/form/fotr.jl | 3 +- src/form/ivr.jl | 6 +- src/form/lindist3flow.jl | 3 +- src/form/linear.jl | 6 +- src/form/wmodels.jl | 6 +- src/prob/opfitd.jl | 268 +++++++++++++++++++++++++------------ src/prob/opfitd_dmld.jl | 200 ++++++++++++++++++--------- src/prob/opfitd_oltc.jl | 221 +++++++++++++++++++----------- src/prob/opfitd_storage.jl | 268 +++++++++++++++++++++++++------------ src/prob/pfitd.jl | 169 ++++++++++++++--------- 19 files changed, 845 insertions(+), 513 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d964bb0..1e583ce 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,11 @@ ## staged -- none. +- Refactored code in `ref.jl` function `_ref_filter_transmission_integration_loads!` to allow connecting multiple distro. systems to same trans. system bus. +- Refactored `/prob/` formulations to avoid unnecessary loops when deciding KCL contraints for boundary buses vs. regular buses. +- This refactor significantly reduces loops and should reduce time to build ITD JuMP models. +- This refactor also allows building ITD models where multiple distro. systems can be connected to same trans. system bus and KCL constraints are not duplicated. +- Bumped PMITD compatibility of `PMD` to the latest version (i.e., v0.15.2). ## v0.8.1 diff --git a/Project.toml b/Project.toml index c76a997..6096bcf 100755 --- a/Project.toml +++ b/Project.toml @@ -19,7 +19,7 @@ JSON = "~0.18, ~0.19, ~0.20, ~0.21" JuMP = "~0.22, ~0.23, 1" LinearAlgebra = "1.6" PowerModels = "0.20" -PowerModelsDistribution = "0.15.1" +PowerModelsDistribution = "0.15.2" SCS = "~1.0, ~1.1" julia = "1.6" diff --git a/src/core/base.jl b/src/core/base.jl index 95eef6a..14c14d5 100755 --- a/src/core/base.jl +++ b/src/core/base.jl @@ -363,8 +363,8 @@ function solve_model( result = _IM.optimize_model!( pmitd, optimizer=optimizer, solution_processors=solution_processors) - # Inform about the time for solving the problem (*change to @debug) - @info "pmitd model solution time (instantiate + optimization): $(time() - start_time)" + # Inform about the time for solving the problem (*change to @debug) + @info "pmitd model solution time (instantiate + optimization): $(time() - start_time)" # Transform solution (both T&D) - SI or per unit - MATH or ENG. if (make_si == false) diff --git a/src/core/ref.jl b/src/core/ref.jl index 1acc6d0..ed81581 100644 --- a/src/core/ref.jl +++ b/src/core/ref.jl @@ -50,11 +50,16 @@ function _ref_filter_transmission_integration_loads!(ref::Dict{Symbol,<:Any}) for (nw, nw_ref) in ref[:it][:pm][:nw] # Filters only the ones that have the "transmission_boundary" key for (i, conn) in filter(x -> "transmission_boundary" in keys(x.second), ref[:it][:pmitd][:nw][nw]) + + ## Note: This initialization causes error when solving problems where multiple distro. systems are connected to same transmission system. # Get init (start) values before deleting the boundary load info. - pbound_fr_start = nw_ref[:load][nw_ref[:bus_loads][conn["transmission_boundary"]][1]]["pd"] - qbound_fr_start = nw_ref[:load][nw_ref[:bus_loads][conn["transmission_boundary"]][1]]["qd"] - conn["pbound_fr_start"] = pbound_fr_start - conn["qbound_fr_start"] = qbound_fr_start + # pbound_fr_start = nw_ref[:load][nw_ref[:bus_loads][conn["transmission_boundary"]][1]]["pd"] + # qbound_fr_start = nw_ref[:load][nw_ref[:bus_loads][conn["transmission_boundary"]][1]]["qd"] + # conn["pbound_fr_start"] = pbound_fr_start + # conn["qbound_fr_start"] = qbound_fr_start + + conn["pbound_fr_start"] = 0.0 + conn["qbound_fr_start"] = 0.0 # Remove loads nw_ref[:load] = Dict(x for x in nw_ref[:load] if x.second["load_bus"] != conn["transmission_boundary"] ) diff --git a/src/form/acp.jl b/src/form/acp.jl index 68d90fb..5c4a7b1 100644 --- a/src/form/acp.jl +++ b/src/form/acp.jl @@ -5,7 +5,6 @@ pmitd::AbstractPowerModelITD, pm::_PM.AbstractACPModel, n::Int, - j::Int, i::Int, bus_arcs, bus_arcs_dc, @@ -21,7 +20,7 @@ ACP transmission constraint power balance. """ -function constraint_transmission_power_balance(pmitd::AbstractPowerModelITD, pm::_PM.AbstractACPModel, n::Int, j::Int, i::Int, bus_arcs, bus_arcs_dc, bus_arcs_sw, bus_gens, bus_storage, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) +function constraint_transmission_power_balance(pmitd::AbstractPowerModelITD, pm::_PM.AbstractACPModel, n::Int, i::Int, bus_arcs, bus_arcs_dc, bus_arcs_sw, bus_gens, bus_storage, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) vm = _PM.var(pm, n, :vm, i) @@ -111,7 +110,6 @@ end pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedACPModel, n::Int, - j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, @@ -127,7 +125,8 @@ end ACPU distribution constraint power balance. """ -function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedACPModel, n::Int, j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) +function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedACPModel, n::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) + vm = _PMD.var(pmd, n, :vm, i) va = _PMD.var(pmd, n, :va, i) diff --git a/src/form/acr.jl b/src/form/acr.jl index 22f7e58..03869cf 100644 --- a/src/form/acr.jl +++ b/src/form/acr.jl @@ -5,7 +5,6 @@ pmitd::AbstractPowerModelITD, pm::_PM.AbstractACRModel, n::Int, - j::Int, i::Int, bus_arcs, bus_arcs_dc, @@ -21,7 +20,7 @@ ACR transmission constraint power balance. """ -function constraint_transmission_power_balance(pmitd::AbstractPowerModelITD, pm::_PM.AbstractACRModel, n::Int, j::Int, i::Int, bus_arcs, bus_arcs_dc, bus_arcs_sw, bus_gens, bus_storage, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) +function constraint_transmission_power_balance(pmitd::AbstractPowerModelITD, pm::_PM.AbstractACRModel, n::Int, i::Int, bus_arcs, bus_arcs_dc, bus_arcs_sw, bus_gens, bus_storage, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) vr = _PM.var(pm, n, :vr, i) vi = _PM.var(pm, n, :vi, i) @@ -76,7 +75,6 @@ end pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedACRModel, n::Int, - j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, @@ -92,7 +90,7 @@ end ACRU distribution constraint power balance. """ -function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedACRModel, n::Int, j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) +function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedACRModel, n::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) vr = _PMD.var(pmd, n, :vr, i) vi = _PMD.var(pmd, n, :vi, i) diff --git a/src/form/boundary.jl b/src/form/boundary.jl index a233369..807da60 100644 --- a/src/form/boundary.jl +++ b/src/form/boundary.jl @@ -158,169 +158,139 @@ end """ function constraint_transmission_power_balance_boundary( pmitd::AbstractPowerModelITD, - i::Int, - j::Int, - boundary_buses::Vector; + i::Int; nw_pmitd::Int=nw_id_default ) General power balance contraints for boundary buses in the transmission system-side. """ -function constraint_transmission_power_balance_boundary(pmitd::AbstractPowerModelITD, i::Int, j::Int, boundary_buses::Vector; nw_pmitd::Int=nw_id_default) +function constraint_transmission_power_balance_boundary(pmitd::AbstractPowerModelITD, i::Int; nw_pmitd::Int=nw_id_default) # Extract the transmission model pm_model = _get_powermodel_from_powermodelitd(pmitd) bus = _PM.ref(pm_model, nw_pmitd, :bus, i) - boundary_pmitd = ref(pmitd, nw_pmitd, :boundary, j) - bus_pm = boundary_pmitd["f_bus"] + bus_arcs = _PM.ref(pm_model, nw_pmitd, :bus_arcs, i) + bus_arcs_dc = _PM.ref(pm_model, nw_pmitd, :bus_arcs_dc, i) + bus_arcs_sw = _PM.ref(pm_model, nw_pmitd, :bus_arcs_sw, i) + bus_gens = _PM.ref(pm_model, nw_pmitd, :bus_gens, i) + bus_loads = _PM.ref(pm_model, nw_pmitd, :bus_loads, i) + bus_shunts = _PM.ref(pm_model, nw_pmitd, :bus_shunts, i) + bus_storage = _PM.ref(pm_model, nw_pmitd, :bus_storage, i) - if bus["bus_i"] == bus_pm # consider Power flowing through respective boundary connection - bus_arcs = _PM.ref(pm_model, nw_pmitd, :bus_arcs, i) - bus_arcs_dc = _PM.ref(pm_model, nw_pmitd, :bus_arcs_dc, i) - bus_arcs_sw = _PM.ref(pm_model, nw_pmitd, :bus_arcs_sw, i) - bus_gens = _PM.ref(pm_model, nw_pmitd, :bus_gens, i) - bus_loads = _PM.ref(pm_model, nw_pmitd, :bus_loads, i) - bus_shunts = _PM.ref(pm_model, nw_pmitd, :bus_shunts, i) - bus_storage = _PM.ref(pm_model, nw_pmitd, :bus_storage, i) + bus_pd = Dict(k => _PM.ref(pm_model, nw_pmitd, :load, k, "pd") for k in bus_loads) + bus_qd = Dict(k => _PM.ref(pm_model, nw_pmitd, :load, k, "qd") for k in bus_loads) - bus_pd = Dict(k => _PM.ref(pm_model, nw_pmitd, :load, k, "pd") for k in bus_loads) - bus_qd = Dict(k => _PM.ref(pm_model, nw_pmitd, :load, k, "qd") for k in bus_loads) + bus_gs = Dict(k => _PM.ref(pm_model, nw_pmitd, :shunt, k, "gs") for k in bus_shunts) + bus_bs = Dict(k => _PM.ref(pm_model, nw_pmitd, :shunt, k, "bs") for k in bus_shunts) - bus_gs = Dict(k => _PM.ref(pm_model, nw_pmitd, :shunt, k, "gs") for k in bus_shunts) - bus_bs = Dict(k => _PM.ref(pm_model, nw_pmitd, :shunt, k, "bs") for k in bus_shunts) + bus_arcs_boundary_from = ref(pmitd, nw_pmitd, :bus_arcs_boundary_from, i) + constraint_transmission_power_balance(pmitd, pm_model, nw_pmitd, i, bus_arcs, bus_arcs_dc, bus_arcs_sw, bus_gens, bus_storage, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) - bus_arcs_boundary_from = ref(pmitd, nw_pmitd, :bus_arcs_boundary_from, i) - constraint_transmission_power_balance(pmitd, pm_model, nw_pmitd, j, i, bus_arcs, bus_arcs_dc, bus_arcs_sw, bus_gens, bus_storage, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) - push!(boundary_buses, bus_pm) # add to vector storage - end end """ function constraint_distribution_power_balance_boundary( pmitd::AbstractPowerModelITD, - i::Int, - j::Int, - boundary_buses::Vector; + i::Int; nw_pmitd::Int=nw_id_default ) General power balance contraints for boundary buses in the distribution system-side. """ -function constraint_distribution_power_balance_boundary(pmitd::AbstractPowerModelITD, i::Int, j::Int, boundary_buses::Vector; nw_pmitd::Int=nw_id_default) +function constraint_distribution_power_balance_boundary(pmitd::AbstractPowerModelITD, i::Int; nw_pmitd::Int=nw_id_default) # Extract the distribution model pmd_model = _get_powermodeldistribution_from_powermodelitd(pmitd) bus = _PMD.ref(pmd_model, nw_pmitd, :bus, i) - boundary_pmitd = ref(pmitd, nw_pmitd, :boundary, j) - bus_pmd = boundary_pmitd["t_bus"] - - if bus["bus_i"] == bus_pmd # consider Power flowing through respective boundary connection - bus_arcs = _PMD.ref(pmd_model, nw_pmitd, :bus_arcs_conns_branch, i) - bus_arcs_sw = _PMD.ref(pmd_model, nw_pmitd, :bus_arcs_conns_switch, i) - bus_arcs_trans = _PMD.ref(pmd_model, nw_pmitd, :bus_arcs_conns_transformer, i) - bus_gens = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_gen, i) - bus_storage = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_storage, i) - bus_loads = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_load, i) - bus_shunts = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_shunt, i) - - if !haskey(_PMD.con(pmd_model, nw_pmitd), :lam_kcl_r) - _PMD.con(pmd_model, nw_pmitd)[:lam_kcl_r] = Dict{Int,Array{JuMP.ConstraintRef}}() - end - - if !haskey(_PMD.con(pmd_model, nw_pmitd), :lam_kcl_i) - _PMD.con(pmd_model, nw_pmitd)[:lam_kcl_i] = Dict{Int,Array{JuMP.ConstraintRef}}() - end - - bus_arcs_boundary_to = ref(pmitd, nw_pmitd, :bus_arcs_boundary_to, i) - constraint_distribution_power_balance(pmitd, pmd_model, nw_pmitd, j, i, bus["terminals"], bus["grounded"], bus_arcs, bus_arcs_sw, bus_arcs_trans, bus_gens, bus_storage, bus_loads, bus_shunts, bus_arcs_boundary_to) - push!(boundary_buses, bus_pmd) # add to vector storage + bus_arcs = _PMD.ref(pmd_model, nw_pmitd, :bus_arcs_conns_branch, i) + bus_arcs_sw = _PMD.ref(pmd_model, nw_pmitd, :bus_arcs_conns_switch, i) + bus_arcs_trans = _PMD.ref(pmd_model, nw_pmitd, :bus_arcs_conns_transformer, i) + bus_gens = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_gen, i) + bus_storage = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_storage, i) + bus_loads = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_load, i) + bus_shunts = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_shunt, i) + + if !haskey(_PMD.con(pmd_model, nw_pmitd), :lam_kcl_r) + _PMD.con(pmd_model, nw_pmitd)[:lam_kcl_r] = Dict{Int,Array{JuMP.ConstraintRef}}() end + if !haskey(_PMD.con(pmd_model, nw_pmitd), :lam_kcl_i) + _PMD.con(pmd_model, nw_pmitd)[:lam_kcl_i] = Dict{Int,Array{JuMP.ConstraintRef}}() + end + + bus_arcs_boundary_to = ref(pmitd, nw_pmitd, :bus_arcs_boundary_to, i) + constraint_distribution_power_balance(pmitd, pmd_model, nw_pmitd, i, bus["terminals"], bus["grounded"], bus_arcs, bus_arcs_sw, bus_arcs_trans, bus_gens, bus_storage, bus_loads, bus_shunts, bus_arcs_boundary_to) + end """ function constraint_transmission_current_balance_boundary( pmitd::AbstractIVRPowerModelITD, - i::Int, - j::Int, - boundary_buses::Vector; + i::Int; nw_pmitd::Int=nw_id_default ) General current balance contraints for boundary buses in the transmission system-side. """ -function constraint_transmission_current_balance_boundary(pmitd::AbstractIVRPowerModelITD, i::Int, j::Int, boundary_buses::Vector; nw_pmitd::Int=nw_id_default) +function constraint_transmission_current_balance_boundary(pmitd::AbstractIVRPowerModelITD, i::Int; nw_pmitd::Int=nw_id_default) # Extract the transmission model pm_model = _get_powermodel_from_powermodelitd(pmitd) bus = _PM.ref(pm_model, nw_pmitd, :bus, i) - boundary_pmitd = ref(pmitd, nw_pmitd, :boundary, j) - bus_pm = boundary_pmitd["f_bus"] - - if bus["bus_i"] == bus_pm # consider Current flowing through respective boundary connection + if !haskey(_PM.con(pm_model, nw_pmitd), :kcl_cr) + _PM.con(pm_model, nw_pmitd)[:kcl_cr] = Dict{Int,JuMP.ConstraintRef}() + end + if !haskey(_PM.con(pm_model, nw_pmitd), :kcl_ci) + _PM.con(pm_model, nw_pmitd)[:kcl_ci] = Dict{Int,JuMP.ConstraintRef}() + end - if !haskey(_PM.con(pm_model, nw_pmitd), :kcl_cr) - _PM.con(pm_model, nw_pmitd)[:kcl_cr] = Dict{Int,JuMP.ConstraintRef}() - end - if !haskey(_PM.con(pm_model, nw_pmitd), :kcl_ci) - _PM.con(pm_model, nw_pmitd)[:kcl_ci] = Dict{Int,JuMP.ConstraintRef}() - end + bus_arcs = _PM.ref(pm_model, nw_pmitd, :bus_arcs, i) + bus_arcs_dc = _PM.ref(pm_model, nw_pmitd, :bus_arcs_dc, i) + bus_gens = _PM.ref(pm_model, nw_pmitd, :bus_gens, i) + bus_loads = _PM.ref(pm_model, nw_pmitd, :bus_loads, i) + bus_shunts = _PM.ref(pm_model, nw_pmitd, :bus_shunts, i) - bus_arcs = _PM.ref(pm_model, nw_pmitd, :bus_arcs, i) - bus_arcs_dc = _PM.ref(pm_model, nw_pmitd, :bus_arcs_dc, i) - bus_gens = _PM.ref(pm_model, nw_pmitd, :bus_gens, i) - bus_loads = _PM.ref(pm_model, nw_pmitd, :bus_loads, i) - bus_shunts = _PM.ref(pm_model, nw_pmitd, :bus_shunts, i) + bus_pd = Dict(k => _PM.ref(pm_model, nw_pmitd, :load, k, "pd") for k in bus_loads) + bus_qd = Dict(k => _PM.ref(pm_model, nw_pmitd, :load, k, "qd") for k in bus_loads) - bus_pd = Dict(k => _PM.ref(pm_model, nw_pmitd, :load, k, "pd") for k in bus_loads) - bus_qd = Dict(k => _PM.ref(pm_model, nw_pmitd, :load, k, "qd") for k in bus_loads) + bus_gs = Dict(k => _PM.ref(pm_model, nw_pmitd, :shunt, k, "gs") for k in bus_shunts) + bus_bs = Dict(k => _PM.ref(pm_model, nw_pmitd, :shunt, k, "bs") for k in bus_shunts) - bus_gs = Dict(k => _PM.ref(pm_model, nw_pmitd, :shunt, k, "gs") for k in bus_shunts) - bus_bs = Dict(k => _PM.ref(pm_model, nw_pmitd, :shunt, k, "bs") for k in bus_shunts) + bus_arcs_boundary_from = ref(pmitd, nw_pmitd, :bus_arcs_boundary_from, i) + constraint_transmission_current_balance(pmitd, pm_model, nw_pmitd, i, bus_arcs, bus_arcs_dc, bus_gens, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) - bus_arcs_boundary_from = ref(pmitd, nw_pmitd, :bus_arcs_boundary_from, i) - constraint_transmission_current_balance(pmitd, pm_model, nw_pmitd, j, i, bus_arcs, bus_arcs_dc, bus_gens, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) - push!(boundary_buses, bus_pm) # add to vector storage - end end """ function constraint_distribution_current_balance_boundary( pmitd::AbstractIVRPowerModelITD, - i::Int, - j::Int, - boundary_buses::Vector; + i::Int; nw_pmitd::Int=nw_id_default ) General current balance contraints for boundary buses in the distribution system-side. """ -function constraint_distribution_current_balance_boundary(pmitd::AbstractIVRPowerModelITD, i::Int, j::Int, boundary_buses::Vector; nw_pmitd::Int=nw_id_default) +function constraint_distribution_current_balance_boundary(pmitd::AbstractIVRPowerModelITD, i::Int; nw_pmitd::Int=nw_id_default) # Extract the distribution model pmd_model = _get_powermodeldistribution_from_powermodelitd(pmitd) bus = _PMD.ref(pmd_model, nw_pmitd, :bus, i) - boundary_pmitd = ref(pmitd, nw_pmitd, :boundary, j) - bus_pmd = boundary_pmitd["t_bus"] - - if bus["bus_i"] == bus_pmd # consider Current flowing through respective boundary connection - bus_arcs = _PMD.ref(pmd_model, nw_pmitd, :bus_arcs_conns_branch, i) - bus_arcs_sw = _PMD.ref(pmd_model, nw_pmitd, :bus_arcs_conns_switch, i) - bus_arcs_trans = _PMD.ref(pmd_model, nw_pmitd, :bus_arcs_conns_transformer, i) - bus_gens = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_gen, i) - bus_storage = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_storage, i) - bus_loads = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_load, i) - bus_shunts = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_shunt, i) - - bus_arcs_boundary_to = ref(pmitd, nw_pmitd, :bus_arcs_boundary_to, i) - constraint_distribution_current_balance(pmitd, pmd_model, nw_pmitd, j, i, bus["terminals"], bus["grounded"], bus_arcs, bus_arcs_sw, bus_arcs_trans, bus_gens, bus_storage, bus_loads, bus_shunts, bus_arcs_boundary_to) - push!(boundary_buses, bus_pmd) # add to vector storage - end + bus_arcs = _PMD.ref(pmd_model, nw_pmitd, :bus_arcs_conns_branch, i) + bus_arcs_sw = _PMD.ref(pmd_model, nw_pmitd, :bus_arcs_conns_switch, i) + bus_arcs_trans = _PMD.ref(pmd_model, nw_pmitd, :bus_arcs_conns_transformer, i) + bus_gens = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_gen, i) + bus_storage = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_storage, i) + bus_loads = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_load, i) + bus_shunts = _PMD.ref(pmd_model, nw_pmitd, :bus_conns_shunt, i) + + bus_arcs_boundary_to = ref(pmitd, nw_pmitd, :bus_arcs_boundary_to, i) + constraint_distribution_current_balance(pmitd, pmd_model, nw_pmitd, i, bus["terminals"], bus["grounded"], bus_arcs, bus_arcs_sw, bus_arcs_trans, bus_gens, bus_storage, bus_loads, bus_shunts, bus_arcs_boundary_to) + end diff --git a/src/form/fbs.jl b/src/form/fbs.jl index 0851c61..b41e982 100644 --- a/src/form/fbs.jl +++ b/src/form/fbs.jl @@ -5,7 +5,6 @@ pmitd::AbstractPowerModelITD, pmd::_PMD.FBSUBFPowerModel, n::Int, - j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, @@ -21,7 +20,7 @@ FBSU distribution constraint power balance. """ -function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.FBSUBFPowerModel, n::Int, j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) +function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.FBSUBFPowerModel, n::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) vr = _PMD.var(pmd, n, :vr0, i) vi = _PMD.var(pmd, n, :vi0, i) diff --git a/src/form/fotp.jl b/src/form/fotp.jl index c63d399..94c463b 100644 --- a/src/form/fotp.jl +++ b/src/form/fotp.jl @@ -5,7 +5,6 @@ pmitd::AbstractPowerModelITD, pmd::_PMD.FOTPUPowerModel, n::Int, - j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, @@ -21,7 +20,7 @@ FOTPU distribution constraint power balance. """ -function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.FOTPUPowerModel, n::Int, j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) +function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.FOTPUPowerModel, n::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) vm = _PMD.var(pmd, n, :vm, i) va = _PMD.var(pmd, n, :va, i) @@ -195,4 +194,4 @@ function constraint_boundary_voltage_angle(pm::_PM.ACPPowerModel, pmd::_PMD.FOTP JuMP.@constraint(pm.model, va_to[3] == (va_to[1] + shift_120degs_rad)) -end \ No newline at end of file +end diff --git a/src/form/fotr.jl b/src/form/fotr.jl index 69de10c..345da47 100644 --- a/src/form/fotr.jl +++ b/src/form/fotr.jl @@ -5,7 +5,6 @@ pmitd::AbstractPowerModelITD, pmd::_PMD.FOTRUPowerModel, n::Int, - j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, @@ -21,7 +20,7 @@ FOTRU distribution constraint power balance. """ -function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.FOTRUPowerModel, n::Int, j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) +function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.FOTRUPowerModel, n::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) vr = _PMD.var(pmd, n, :vr, i) vi = _PMD.var(pmd, n, :vi, i) diff --git a/src/form/ivr.jl b/src/form/ivr.jl index d030d48..0f5dc78 100644 --- a/src/form/ivr.jl +++ b/src/form/ivr.jl @@ -5,7 +5,6 @@ pmitd::AbstractPowerModelITD, pm::_PM.AbstractIVRModel, n::Int, - j::Int, i::Int, bus_arcs, bus_arcs_dc, @@ -19,7 +18,7 @@ IVR transmission constraint power balance. """ -function constraint_transmission_current_balance(pmitd::AbstractPowerModelITD, pm::_PM.AbstractIVRModel, n::Int, j::Int, i::Int, bus_arcs, bus_arcs_dc, bus_gens, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) +function constraint_transmission_current_balance(pmitd::AbstractPowerModelITD, pm::_PM.AbstractIVRModel, n::Int, i::Int, bus_arcs, bus_arcs_dc, bus_gens, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) vr = _PM.var(pm, n, :vr, i) vi = _PM.var(pm, n, :vi, i) @@ -59,7 +58,6 @@ end pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedIVRModel, n::Int, - j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, @@ -75,7 +73,7 @@ end IVRU distribution constraint power balance. """ -function constraint_distribution_current_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedIVRModel, n::Int, j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) +function constraint_distribution_current_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedIVRModel, n::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) vr = _PMD.var(pmd, n, :vr, i) vi = _PMD.var(pmd, n, :vi, i) diff --git a/src/form/lindist3flow.jl b/src/form/lindist3flow.jl index badc385..5f292c5 100644 --- a/src/form/lindist3flow.jl +++ b/src/form/lindist3flow.jl @@ -5,7 +5,6 @@ pmitd::AbstractBFPowerModelITD, pmd::_PMD.LPUBFDiagPowerModel, n::Int, - j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, @@ -21,7 +20,7 @@ LinDist3FlowPowerModel distribution constraint power balance. """ -function constraint_distribution_power_balance(pmitd::AbstractBFPowerModelITD, pmd::_PMD.LPUBFDiagPowerModel, n::Int, j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) +function constraint_distribution_power_balance(pmitd::AbstractBFPowerModelITD, pmd::_PMD.LPUBFDiagPowerModel, n::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) w = _PMD.var(pmd, n, :w, i) p = _PMD.get(_PMD.var(pmd, n), :p, Dict()); _PMD._check_var_keys(p, bus_arcs, "active power", "branch") q = _PMD.get(_PMD.var(pmd, n), :q, Dict()); _PMD._check_var_keys(q, bus_arcs, "reactive power", "branch") diff --git a/src/form/linear.jl b/src/form/linear.jl index f281205..9ad5896 100644 --- a/src/form/linear.jl +++ b/src/form/linear.jl @@ -5,7 +5,6 @@ pmitd::AbstractPowerModelITD, pm::_PM.AbstractActivePowerModel, n::Int, - j::Int, i::Int, bus_arcs, bus_arcs_dc, @@ -21,7 +20,7 @@ DCP/NFA transmission constraint power balance. """ -function constraint_transmission_power_balance(pmitd::AbstractPowerModelITD, pm::_PM.AbstractActivePowerModel, n::Int, j::Int, i::Int, bus_arcs, bus_arcs_dc, bus_arcs_sw, bus_gens, bus_storage, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) +function constraint_transmission_power_balance(pmitd::AbstractPowerModelITD, pm::_PM.AbstractActivePowerModel, n::Int, i::Int, bus_arcs, bus_arcs_dc, bus_arcs_sw, bus_gens, bus_storage, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) p = _PM.get(_PM.var(pm, n), :p, Dict()); _PM._check_var_keys(p, bus_arcs, "active power", "branch") pg = _PM.get(_PM.var(pm, n), :pg, Dict()); _PM._check_var_keys(pg, bus_gens, "active power", "generator") @@ -57,7 +56,6 @@ end pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedActivePowerModel, n::Int, - j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, @@ -73,7 +71,7 @@ end DCPU/NFAU distribution constraint power balance. """ -function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedActivePowerModel, n::Int, j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) +function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedActivePowerModel, n::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) p = _PMD.get(_PMD.var(pmd, n), :p, Dict())#; _PMD._check_var_keys(p, bus_arcs, "active power", "branch") pg = _PMD.get(_PMD.var(pmd, n), :pg_bus, Dict())#; _PMD._check_var_keys(pg, bus_gens, "active power", "generator") ps = _PMD.get(_PMD.var(pmd, n), :ps, Dict())#; _PMD._check_var_keys(ps, bus_storage, "active power", "storage") diff --git a/src/form/wmodels.jl b/src/form/wmodels.jl index bbdd4b8..43b8d0e 100644 --- a/src/form/wmodels.jl +++ b/src/form/wmodels.jl @@ -5,7 +5,6 @@ pmitd::AbstractPowerModelITD, pm::_PM.AbstractWModels, n::Int, - j::Int, i::Int, bus_arcs, bus_arcs_dc, @@ -21,7 +20,7 @@ W Models (e.g., SOCBF) transmission constraint power balance. """ -function constraint_transmission_power_balance(pmitd::AbstractPowerModelITD, pm::_PM.AbstractWModels, n::Int, j::Int, i::Int, bus_arcs, bus_arcs_dc, bus_arcs_sw, bus_gens, bus_storage, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) +function constraint_transmission_power_balance(pmitd::AbstractPowerModelITD, pm::_PM.AbstractWModels, n::Int, i::Int, bus_arcs, bus_arcs_dc, bus_arcs_sw, bus_gens, bus_storage, bus_pd, bus_qd, bus_gs, bus_bs, bus_arcs_boundary_from) w = _PM.var(pm, n, :w, i) p = _PM.get(_PM.var(pm, n), :p, Dict()); _PM._check_var_keys(p, bus_arcs, "active power", "branch") q = _PM.get(_PM.var(pm, n), :q, Dict()); _PM._check_var_keys(q, bus_arcs, "reactive power", "branch") @@ -73,7 +72,6 @@ end pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedWModels, n::Int, - j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, @@ -89,7 +87,7 @@ end Unbalanced W models distribution constraint power balance. """ -function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedWModels, n::Int, j::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) +function constraint_distribution_power_balance(pmitd::AbstractPowerModelITD, pmd::_PMD.AbstractUnbalancedWModels, n::Int, i::Int, terminals::Vector{Int}, grounded::Vector{Bool}, bus_arcs::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_sw::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_arcs_trans::Vector{Tuple{Tuple{Int,Int,Int},Vector{Int}}}, bus_gens::Vector{Tuple{Int,Vector{Int}}}, bus_storage::Vector{Tuple{Int,Vector{Int}}}, bus_loads::Vector{Tuple{Int,Vector{Int}}}, bus_shunts::Vector{Tuple{Int,Vector{Int}}}, bus_arcs_boundary_to) Wr = _PMD.var(pmd, n, :Wr, i) Wi = _PMD.var(pmd, n, :Wi, i) P = _PMD.get(_PMD.var(pmd, n), :P, Dict()); _PMD._check_var_keys(P, bus_arcs, "active power", "branch") diff --git a/src/prob/opfitd.jl b/src/prob/opfitd.jl index bfac232..d4abe28 100755 --- a/src/prob/opfitd.jl +++ b/src/prob/opfitd.jl @@ -200,25 +200,36 @@ function build_opfitd(pmitd::AbstractPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance(pmd_model, i) end end @@ -329,25 +340,36 @@ function build_opfitd(pmitd::AbstractIVRPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_current_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_current_balance_boundary(pmitd, i) + else _PM.constraint_current_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_current_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_current_balance_boundary(pmitd, i) + else _PMD.constraint_mc_current_balance(pmd_model, i) end end @@ -477,25 +499,36 @@ function build_opfitd(pmitd::AbstractBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance(pmd_model, i) end end @@ -623,25 +656,36 @@ function build_opfitd(pmitd::AbstractLNLBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance(pmd_model, i) end end @@ -770,30 +814,40 @@ function build_mn_opfitd(pmitd::AbstractPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PM.constraint_power_balance(pm_model, i, nw=n) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PMD.constraint_mc_power_balance(pmd_model, i; nw=n) end end - end # --- PM energy storage state constraint --- @@ -941,28 +995,40 @@ function build_mn_opfitd(pmitd::AbstractIVRPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_current_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_current_balance_boundary(pmitd, i; nw_pmitd=n) + else _PM.constraint_current_balance(pm_model, i, nw=n) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_current_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_current_balance_boundary(pmitd, i; nw_pmitd=n) + else _PMD.constraint_mc_current_balance(pmd_model, i; nw=n) end end + end # --- PM energy storage state constraint --- @@ -1119,28 +1185,40 @@ function build_mn_opfitd(pmitd::AbstractBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PM.constraint_power_balance(pm_model, i, nw=n) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PMD.constraint_mc_power_balance(pmd_model, i; nw=n) end end + end # --- PM energy storage state constraint --- @@ -1296,28 +1374,40 @@ function build_mn_opfitd(pmitd::AbstractLNLBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PM.constraint_power_balance(pm_model, i, nw=n) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PMD.constraint_mc_power_balance(pmd_model, i; nw=n) end end + end # --- PM energy storage state constraint --- diff --git a/src/prob/opfitd_dmld.jl b/src/prob/opfitd_dmld.jl index 794a103..d892ec4 100755 --- a/src/prob/opfitd_dmld.jl +++ b/src/prob/opfitd_dmld.jl @@ -194,25 +194,36 @@ function build_dmld_opfitd(pmitd::AbstractPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance_shed(pmd_model, i) end end @@ -347,25 +358,36 @@ function build_dmld_opfitd(pmitd::AbstractBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance_shed(pmd_model, i) end end @@ -485,25 +507,36 @@ function build_dmld_opfitd(pmitd::AbstractLNLBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance_shed(pmd_model, i) end end @@ -626,25 +659,36 @@ function build_mn_dmld_opfitd_simple(pmitd::AbstractPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PM.constraint_power_balance(pm_model, i, nw=n) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PMD.constraint_mc_power_balance_shed(pmd_model, i; nw=n) end end @@ -812,28 +856,40 @@ function build_mn_dmld_opfitd_simple(pmitd::AbstractBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PM.constraint_power_balance(pm_model, i, nw=n) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PMD.constraint_mc_power_balance_shed(pmd_model, i; nw=n) end end + end # --- PM energy storage state constraint --- @@ -983,28 +1039,40 @@ function build_mn_dmld_opfitd_simple(pmitd::AbstractLNLBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PM.constraint_power_balance(pm_model, i, nw=n) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PMD.constraint_mc_power_balance_shed(pmd_model, i; nw=n) end end + end # --- PM energy storage state constraint --- diff --git a/src/prob/opfitd_oltc.jl b/src/prob/opfitd_oltc.jl index 2999560..a27237c 100644 --- a/src/prob/opfitd_oltc.jl +++ b/src/prob/opfitd_oltc.jl @@ -201,25 +201,36 @@ function build_opfitd_oltc(pmitd::AbstractPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance(pmd_model, i) end end @@ -349,25 +360,36 @@ function build_opfitd_oltc(pmitd::AbstractBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance(pmd_model, i) end end @@ -495,25 +517,36 @@ function build_opfitd_oltc(pmitd::AbstractLNLBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance(pmd_model, i) end end @@ -640,28 +673,40 @@ function build_mn_opfitd_oltc(pmitd::AbstractPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PM.constraint_power_balance(pm_model, i, nw=n) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PMD.constraint_mc_power_balance(pmd_model, i; nw=n) end end + end # --- PM energy storage state constraint --- @@ -818,28 +863,40 @@ function build_mn_opfitd_oltc(pmitd::AbstractBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end - # Note: Both of these need to consider flow on boundaries if bus is connected to boundary - # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint - for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) - _PM.constraint_power_balance(pm_model, i, nw=n) - end - end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- + # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + + # # ---- Transmission Power Balance --- + for i in _PM.ids(pm_model, :bus, nw=n) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i; nw_pmitd=n) + else + _PM.constraint_power_balance(pm_model, i, nw=n) + end + end + + # ---- Distribution Power Balance --- + for i in _PMD.ids(pmd_model, n, :bus) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i; nw_pmitd=n) + else + _PMD.constraint_mc_power_balance(pmd_model, i; nw=n) + end + end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint - for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) - _PMD.constraint_mc_power_balance(pmd_model, i; nw=n) - end - end end # --- PM energy storage state constraint --- @@ -995,28 +1052,40 @@ function build_mn_opfitd_oltc(pmitd::AbstractLNLBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PM.constraint_power_balance(pm_model, i, nw=n) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PMD.constraint_mc_power_balance(pmd_model, i; nw=n) end end + end # --- PM energy storage state constraint --- diff --git a/src/prob/opfitd_storage.jl b/src/prob/opfitd_storage.jl index 703d7d3..6c12a72 100755 --- a/src/prob/opfitd_storage.jl +++ b/src/prob/opfitd_storage.jl @@ -232,25 +232,36 @@ function build_opfitd_storage(pmitd::AbstractPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance(pmd_model, i) end end @@ -364,25 +375,36 @@ function build_opfitd_storage(pmitd::AbstractIVRPowerModelITD) # constraint_boundary_voltage_angle(pmitd, i) # end + # # ------------------------------------------------- + # # --- PMITD(T&D) KCL Constraints ---------- # # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + # boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + # boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + # for j in ids(pmitd, :boundary) + # boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + # bus_pm = boundary_pmitd["f_bus"] + # bus_pmd = boundary_pmitd["t_bus"] + # push!(boundary_buses_transmission, bus_pm) + # push!(boundary_buses_distribution, bus_pmd) + # end + # # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + # boundary_buses_transmission_set = Set(boundary_buses_transmission) + # boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # # ---- Transmission Power Balance --- - # boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint # for i in _PM.ids(pm_model, :bus) - # for j in ids(pmitd, :boundary) - # constraint_transmission_current_balance_boundary(pmitd, i, j, boundary_buses) - # end - # if !(i in boundary_buses) + # if i in boundary_buses_transmission_set + # constraint_transmission_current_balance_boundary(pmitd, i) + # else # _PM.constraint_current_balance(pm_model, i) # end # end - # # # ---- Distribution Power Balance --- - # boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # # ---- Distribution Power Balance --- # for i in _PMD.ids(pmd_model, :bus) - # for j in ids(pmitd, :boundary) - # constraint_distribution_current_balance_boundary(pmitd, i, j, boundary_buses) - # end - # if !(i in boundary_buses) + # if i in boundary_buses_distribution_set + # constraint_distribution_current_balance_boundary(pmitd, i) + # else # _PMD.constraint_mc_current_balance(pmd_model, i) # end # end @@ -513,25 +535,36 @@ function build_opfitd_storage(pmitd::AbstractBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance(pmd_model, i) end end @@ -660,25 +693,36 @@ function build_opfitd_storage(pmitd::AbstractLNLBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance(pmd_model, i) end end @@ -807,30 +851,40 @@ function build_mn_opfitd_storage(pmitd::AbstractPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PM.constraint_power_balance(pm_model, i, nw=n) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PMD.constraint_mc_power_balance(pmd_model, i; nw=n) end end - end # --- PM energy storage state constraint --- @@ -981,28 +1035,40 @@ function build_mn_opfitd_storage(pmitd::AbstractIVRPowerModelITD) # constraint_boundary_voltage_angle(pmitd, i; nw=n) # end + # # ------------------------------------------------- + # # --- PMITD(T&D) KCL Constraints ---------- # # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + # boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + # boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + # for j in ids(pmitd, :boundary; nw=n) + # boundary_pmitd = ref(pmitd, n, :boundary, j) + # bus_pm = boundary_pmitd["f_bus"] + # bus_pmd = boundary_pmitd["t_bus"] + # push!(boundary_buses_transmission, bus_pm) + # push!(boundary_buses_distribution, bus_pmd) + # end + # # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + # boundary_buses_transmission_set = Set(boundary_buses_transmission) + # boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # # ---- Transmission Power Balance --- - # boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint # for i in _PM.ids(pm_model, :bus, nw=n) - # for j in ids(pmitd, :boundary; nw=n) - # constraint_transmission_current_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - # end - # if !(i in boundary_buses) + # if i in boundary_buses_transmission_set + # constraint_transmission_current_balance_boundary(pmitd, i; nw_pmitd=n) + # else # _PM.constraint_current_balance(pm_model, i, nw=n) # end # end - # # # ---- Distribution Power Balance --- - # boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # # ---- Distribution Power Balance --- # for i in _PMD.ids(pmd_model, n, :bus) - # for j in ids(pmitd, :boundary; nw=n) - # constraint_distribution_current_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - # end - # if !(i in boundary_buses) + # if i in boundary_buses_distribution_set + # constraint_distribution_current_balance_boundary(pmitd, i; nw_pmitd=n) + # else # _PMD.constraint_mc_current_balance(pmd_model, i; nw=n) # end # end + # end # # --- PM energy storage state constraint --- @@ -1159,28 +1225,40 @@ function build_mn_opfitd_storage(pmitd::AbstractBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PM.constraint_power_balance(pm_model, i, nw=n) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PMD.constraint_mc_power_balance(pmd_model, i; nw=n) end end + end # --- PM energy storage state constraint --- @@ -1336,28 +1414,40 @@ function build_mn_opfitd_storage(pmitd::AbstractLNLBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i; nw=n) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary; nw=n) + boundary_pmitd = ref(pmitd, n, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint for i in _PM.ids(pm_model, :bus, nw=n) - for j in ids(pmitd, :boundary; nw=n) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PM.constraint_power_balance(pm_model, i, nw=n) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint + # ---- Distribution Power Balance --- for i in _PMD.ids(pmd_model, n, :bus) - for j in ids(pmitd, :boundary; nw=n) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses; nw_pmitd=n) - end - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i; nw_pmitd=n) + else _PMD.constraint_mc_power_balance(pmd_model, i; nw=n) end end + end # --- PM energy storage state constraint --- diff --git a/src/prob/pfitd.jl b/src/prob/pfitd.jl index 4c4b8fb..4976476 100755 --- a/src/prob/pfitd.jl +++ b/src/prob/pfitd.jl @@ -146,15 +146,28 @@ function build_pfitd(pmitd::AbstractPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary - # # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint - for (i,bus) in _PM.ref(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - - if !(i in boundary_buses) + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + + # # ---- Transmission Power Balance --- + for (i, bus) in _PM.ref(pm_model, :bus) + + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end @@ -169,14 +182,12 @@ function build_pfitd(pmitd::AbstractPowerModelITD) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint - for (i,bus) in _PMD.ref(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end + # ---- Distribution Power Balance --- + for (i, bus) in _PMD.ref(pmd_model, :bus) - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance(pmd_model, i) end @@ -190,6 +201,7 @@ function build_pfitd(pmitd::AbstractPowerModelITD) end end end + end @@ -286,14 +298,28 @@ function build_pfitd(pmitd::AbstractIVRPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end - # # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint - for (i,bus) in _PM.ref(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_current_balance_boundary(pmitd, i, j, boundary_buses) - end - - if !(i in boundary_buses) + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- + # Note: Both of these need to consider flow on boundaries if bus is connected to boundary + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + + # # ---- Transmission Power Balance --- + for (i, bus) in _PM.ref(pm_model, :bus) + + if i in boundary_buses_transmission_set + constraint_transmission_current_balance_boundary(pmitd, i) + else _PM.constraint_current_balance(pm_model, i) end @@ -308,14 +334,12 @@ function build_pfitd(pmitd::AbstractIVRPowerModelITD) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint - for (i,bus) in _PMD.ref(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_current_balance_boundary(pmitd, i, j, boundary_buses) - end + # ---- Distribution Power Balance --- + for (i, bus) in _PMD.ref(pmd_model, :bus) - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_current_balance_boundary(pmitd, i) + else _PMD.constraint_mc_current_balance(pmd_model, i) end @@ -329,6 +353,7 @@ function build_pfitd(pmitd::AbstractIVRPowerModelITD) end end end + end @@ -442,15 +467,28 @@ function build_pfitd(pmitd::AbstractBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary - # # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint - for (i,bus) in _PM.ref(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - - if !(i in boundary_buses) + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + + # # ---- Transmission Power Balance --- + for (i, bus) in _PM.ref(pm_model, :bus) + + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end @@ -465,14 +503,12 @@ function build_pfitd(pmitd::AbstractBFPowerModelITD) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint - for (i,bus) in _PMD.ref(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end + # ---- Distribution Power Balance --- + for (i, bus) in _PMD.ref(pmd_model, :bus) - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance(pmd_model, i) end @@ -486,6 +522,7 @@ function build_pfitd(pmitd::AbstractBFPowerModelITD) end end end + end @@ -600,15 +637,28 @@ function build_pfitd(pmitd::AbstractLNLBFPowerModelITD) constraint_boundary_voltage_angle(pmitd, i) end + # ------------------------------------------------- + # --- PMITD(T&D) KCL Constraints ---------- # Note: Both of these need to consider flow on boundaries if bus is connected to boundary - # # # ---- Transmission Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint - for (i,bus) in _PM.ref(pm_model, :bus) - for j in ids(pmitd, :boundary) - constraint_transmission_power_balance_boundary(pmitd, i, j, boundary_buses) - end - - if !(i in boundary_buses) + boundary_buses_transmission = Vector{Int}() # vector to store the boundary buses transmission + boundary_buses_distribution = Vector{Int}() # vector to store the boundary buses distribution + for j in ids(pmitd, :boundary) + boundary_pmitd = ref(pmitd, nw_id_default, :boundary, j) + bus_pm = boundary_pmitd["f_bus"] + bus_pmd = boundary_pmitd["t_bus"] + push!(boundary_buses_transmission, bus_pm) + push!(boundary_buses_distribution, bus_pmd) + end + # Convert to Julia Set - Note: membership checks are faster in sets (vs. vectors) in Julia + boundary_buses_transmission_set = Set(boundary_buses_transmission) + boundary_buses_distribution_set = Set(boundary_buses_distribution) + + # # ---- Transmission Power Balance --- + for (i, bus) in _PM.ref(pm_model, :bus) + + if i in boundary_buses_transmission_set + constraint_transmission_power_balance_boundary(pmitd, i) + else _PM.constraint_power_balance(pm_model, i) end @@ -623,14 +673,12 @@ function build_pfitd(pmitd::AbstractLNLBFPowerModelITD) end end - # # ---- Distribution Power Balance --- - boundary_buses = Vector{Int}() # empty vector that stores the boundary buses, so they are not repeated by the other constraint - for (i,bus) in _PMD.ref(pmd_model, :bus) - for j in ids(pmitd, :boundary) - constraint_distribution_power_balance_boundary(pmitd, i, j, boundary_buses) - end + # ---- Distribution Power Balance --- + for (i, bus) in _PMD.ref(pmd_model, :bus) - if !(i in boundary_buses) + if i in boundary_buses_distribution_set + constraint_distribution_power_balance_boundary(pmitd, i) + else _PMD.constraint_mc_power_balance(pmd_model, i) end @@ -644,4 +692,5 @@ function build_pfitd(pmitd::AbstractLNLBFPowerModelITD) end end end + end