diff --git a/Project.toml b/Project.toml index 122a7c1727..2186c0dbb8 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "PowerSimulations" uuid = "e690365d-45e2-57bb-ac84-44ba829e73c4" authors = ["Jose Daniel Lara", "Clayton Barrows", "Daniel Thom", "Dheepak Krishnamurthy", "Sourabh Dalvi"] -version = "0.22.0" +version = "0.23.0" [deps] CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" @@ -35,15 +35,15 @@ CSV = "~0.10" DataFrames = "1" DataStructures = "~0.18" DocStringExtensions = "~v0.9" -HDF5 = "~0.16" +HDF5 = "~0.17" InfrastructureSystems = "^1.21" JSON = "0.21" JSON3 = "1" JuMP = "1" MathOptInterface = "1" PowerModels = "~0.19" -PowerNetworkMatrices = "^0.8" -PowerSystems = "^2.6" +PowerNetworkMatrices = "^0.9" +PowerSystems = "^3" PrettyTables = "^1.3, 2" ProgressMeter = "^1.5" TimeSeries = "~0.23" diff --git a/docs/src/formulation_library/Branch.md b/docs/src/formulation_library/Branch.md index cb41d19e72..f55d6c37e7 100644 --- a/docs/src/formulation_library/Branch.md +++ b/docs/src/formulation_library/Branch.md @@ -44,24 +44,24 @@ StaticBranchUnbounded --- -## `HVDCP2PLossless` +## `HVDCTwoTerminalLossless` ```@docs -HVDCP2PLossless +HVDCTwoTerminalLossless ``` --- -## `HVDCP2PDispatch` +## `HVDCTwoTerminalDispatch` ```@docs -HVDCP2PDispatch +HVDCTwoTerminalDispatch ``` --- -## `HVDCP2PUnbounded` +## `HVDCTwoTerminalUnbounded` ```@docs -HVDCP2PUnbounded +HVDCTwoTerminalUnbounded ``` diff --git a/src/PowerSimulations.jl b/src/PowerSimulations.jl index cb6e30dc00..8afece5303 100644 --- a/src/PowerSimulations.jl +++ b/src/PowerSimulations.jl @@ -41,11 +41,15 @@ export ConstantMaxInterfaceFlow export StaticBranch export StaticBranchBounds export StaticBranchUnbounded -export HVDCP2PLossless -export HVDCP2PDispatch -export HVDCP2PUnbounded +export HVDCTwoTerminalLossless +export HVDCTwoTerminalDispatch +export HVDCTwoTerminalUnbounded export PhaseAngleControl # export VoltageSourceDC + +######## HVDC models ######## +export LossLessConverter +export LossLessLine ######## Load Models ######## export StaticPowerLoad export PowerLoadInterruption @@ -511,7 +515,8 @@ include("devices_models/devices/renewable_generation.jl") include("devices_models/devices/thermal_generation.jl") include("devices_models/devices/electric_loads.jl") include("devices_models/devices/AC_branches.jl") -include("devices_models/devices/DC_branches.jl") +include("devices_models/devices/TwoTerminalDC_branches.jl") +include("devices_models/devices/HVDCsystems.jl") include("devices_models/devices/regulation_device.jl") # Services Models @@ -528,12 +533,14 @@ include("network_models/powermodels_interface.jl") include("network_models/pm_translator.jl") include("network_models/network_slack_variables.jl") include("network_models/area_balance_model.jl") +include("network_models/hvdc_networks.jl") include("initial_conditions/initialization.jl") # Device constructors include("devices_models/device_constructors/constructor_validations.jl") include("devices_models/device_constructors/thermalgeneration_constructor.jl") +include("devices_models/device_constructors/hvdcsystems_constructor.jl") include("devices_models/device_constructors/branch_constructor.jl") include("devices_models/device_constructors/renewablegeneration_constructor.jl") include("devices_models/device_constructors/load_constructor.jl") diff --git a/src/core/definitions.jl b/src/core/definitions.jl index 8d726d7ba7..1900cf773f 100644 --- a/src/core/definitions.jl +++ b/src/core/definitions.jl @@ -27,6 +27,7 @@ const JuMPVariableMatrix = DenseAxisArray{ const JuMPFloatArray = DenseAxisArray{Float64} const JuMPVariableArray = DenseAxisArray{JuMP.VariableRef} +const TwoTerminalHVDCTypes = Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCDCLine} # Settings constants const UNSET_HORIZON = 0 const UNSET_INI_TIME = Dates.DateTime(0) diff --git a/src/core/formulations.jl b/src/core/formulations.jl index 73e801cdf6..6070734baf 100644 --- a/src/core/formulations.jl +++ b/src/core/formulations.jl @@ -102,7 +102,7 @@ struct MyCustomBranchFormulation <: PSI.AbstractDeviceFormulation # Generic Branch Models abstract type AbstractBranchFormulation <: AbstractDeviceFormulation end -############################### AC Branch Formulations ##################################### +############################### AC/DC Branch Formulations ##################################### """ Branch type to add unbounded flow variables and use flow constraints """ @@ -121,21 +121,32 @@ Branch formulation for PhaseShiftingTransformer flow control struct PhaseAngleControl <: AbstractBranchFormulation end ############################### DC Branch Formulations ##################################### -abstract type AbstractDCLineFormulation <: AbstractBranchFormulation end +abstract type AbstractTwoTerminalDCLineFormulation <: AbstractBranchFormulation end """ Branch type to avoid flow constraints """ -struct HVDCP2PUnbounded <: AbstractDCLineFormulation end +struct HVDCTwoTerminalUnbounded <: AbstractTwoTerminalDCLineFormulation end """ Branch type to represent lossless power flow on DC lines """ -struct HVDCP2PLossless <: AbstractDCLineFormulation end +struct HVDCTwoTerminalLossless <: AbstractTwoTerminalDCLineFormulation end """ Branch type to represent lossy power flow on DC lines """ -struct HVDCP2PDispatch <: AbstractDCLineFormulation end +struct HVDCTwoTerminalDispatch <: AbstractTwoTerminalDCLineFormulation end # Not Implemented -# struct VoltageSourceDC <: AbstractDCLineFormulation end +# struct VoltageSourceDC <: AbstractTwoTerminalDCLineFormulation end + +############################### AC/DC Converter Formulations ##################################### +abstract type AbstractConverterFormulation <: AbstractDeviceFormulation end + +""" +LossLess InterconnectingConverter Model +""" +struct LossLessConverter <: AbstractConverterFormulation end + +# TODO: Think if this an ok abstraction for future use cases +struct LossLessLine <: AbstractBranchFormulation end ############################## Network Model Formulations ################################## # These formulations are taken directly from PowerModels diff --git a/src/core/network_model.jl b/src/core/network_model.jl index 4cce44d90e..058d512f77 100644 --- a/src/core/network_model.jl +++ b/src/core/network_model.jl @@ -30,7 +30,7 @@ mutable struct NetworkModel{T <: PM.AbstractPowerModel} use_slacks::Bool PTDF_matrix::Union{Nothing, PNM.PowerNetworkMatrix} subnetworks::Dict{Int, Set{Int}} - bus_area_map::Dict{PSY.Bus, Int} + bus_area_map::Dict{PSY.ACBus, Int} duals::Vector{DataType} function NetworkModel( @@ -41,7 +41,7 @@ mutable struct NetworkModel{T <: PM.AbstractPowerModel} duals = Vector{DataType}(), ) where {T <: PM.AbstractPowerModel} _check_pm_formulation(T) - new{T}(use_slacks, PTDF_matrix, subnetworks, Dict{PSY.Bus, Int}(), duals) + new{T}(use_slacks, PTDF_matrix, subnetworks, Dict{PSY.ACBus, Int}(), duals) end end @@ -107,7 +107,7 @@ function _assign_subnetworks_to_buses( ) where {T <: Union{CopperPlatePowerModel, StandardPTDFModel}} subnetworks = model.subnetworks temp_bus_map = Dict{Int, Int}() - for bus in get_available_components(PSY.Bus, sys) + for bus in get_available_components(PSY.ACBus, sys) bus_no = PSY.get_number(bus) if haskey(temp_bus_map, bus_no) model.bus_area_map[bus] = temp_bus_map[bus_no] @@ -131,7 +131,7 @@ _assign_subnetworks_to_buses( function get_reference_bus( model::NetworkModel{T}, - b::PSY.Bus, + b::PSY.ACBus, )::Int where {T <: PM.AbstractPowerModel} if isempty(model.bus_area_map) return first(keys(model.subnetworks)) diff --git a/src/core/optimization_container.jl b/src/core/optimization_container.jl index 769d78a1ea..7f62169581 100644 --- a/src/core/optimization_container.jl +++ b/src/core/optimization_container.jl @@ -267,7 +267,11 @@ end function is_milp(container::OptimizationContainer)::Bool !supports_milp(container) && return false if !isempty( - JuMP.all_constraints(container.JuMPmodel, JuMP.VariableRef, JuMP.MOI.ZeroOne), + JuMP.all_constraints( + PSI.get_jump_model(container), + JuMP.VariableRef, + JuMP.MOI.ZeroOne, + ), ) return true end @@ -307,10 +311,10 @@ function _finalize_jump_model!(container::OptimizationContainer, settings::Setti @debug "The optimization model has no optimizer attached" _group = LOG_GROUP_OPTIMIZATION_CONTAINER else - JuMP.set_optimizer(container.JuMPmodel, get_optimizer(settings)) + JuMP.set_optimizer(PSI.get_jump_model(container), get_optimizer(settings)) end - JuMPmodel = container.JuMPmodel + JuMPmodel = PSI.get_jump_model(container) warm_start_enabled = get_warm_start(settings) solver_supports_warm_start = _validate_warm_start_support(JuMPmodel, warm_start_enabled) set_warm_start!(settings, solver_supports_warm_start) @@ -386,7 +390,7 @@ function reset_optimization_model!(container::OptimizationContainer) container.initial_conditions_data = InitialConditionsData() container.objective_function = ObjectiveFunction() container.primal_values_cache = PrimalValuesCache() - JuMP.empty!(container.JuMPmodel) + JuMP.empty!(PSI.get_jump_model(container)) return end @@ -425,15 +429,18 @@ end function _make_system_expressions!( container::OptimizationContainer, subnetworks::Dict{Int, Set{Int}}, + dc_bus_numbers::Vector{Int}, ::Type{<:PM.AbstractPowerModel}, ) time_steps = get_time_steps(container) - bus_numbers = collect(Iterators.flatten(values(subnetworks))) + ac_bus_numbers = collect(Iterators.flatten(values(subnetworks))) container.expressions = Dict( - ExpressionKey(ActivePowerBalance, PSY.Bus) => - _make_container_array(bus_numbers, time_steps), - ExpressionKey(ReactivePowerBalance, PSY.Bus) => - _make_container_array(bus_numbers, time_steps), + ExpressionKey(ActivePowerBalance, PSY.ACBus) => + _make_container_array(ac_bus_numbers, time_steps), + ExpressionKey(ActivePowerBalance, PSY.DCBus) => + _make_container_array(dc_bus_numbers, time_steps), + ExpressionKey(ReactivePowerBalance, PSY.ACBus) => + _make_container_array(ac_bus_numbers, time_steps), ) return end @@ -441,13 +448,16 @@ end function _make_system_expressions!( container::OptimizationContainer, subnetworks::Dict{Int, Set{Int}}, + dc_bus_numbers::Vector{Int}, ::Type{<:PM.AbstractActivePowerModel}, ) time_steps = get_time_steps(container) - bus_numbers = collect(Iterators.flatten(values(subnetworks))) + ac_bus_numbers = collect(Iterators.flatten(values(subnetworks))) container.expressions = Dict( - ExpressionKey(ActivePowerBalance, PSY.Bus) => - _make_container_array(bus_numbers, time_steps), + ExpressionKey(ActivePowerBalance, PSY.ACBus) => + _make_container_array(ac_bus_numbers, time_steps), + ExpressionKey(ActivePowerBalance, PSY.DCBus) => + _make_container_array(dc_bus_numbers, time_steps), ) return end @@ -455,6 +465,7 @@ end function _make_system_expressions!( container::OptimizationContainer, subnetworks::Dict{Int, Set{Int}}, + ::Vector{Int}, ::Type{CopperPlatePowerModel}, ) time_steps = get_time_steps(container) @@ -469,16 +480,19 @@ end function _make_system_expressions!( container::OptimizationContainer, subnetworks::Dict{Int, Set{Int}}, + dc_bus_numbers::Vector{Int}, ::Type{T}, ) where {T <: Union{PTDFPowerModel, StandardPTDFModel}} time_steps = get_time_steps(container) - bus_numbers = sort!(collect(Iterators.flatten(values(subnetworks)))) + ac_bus_numbers = sort!(collect(Iterators.flatten(values(subnetworks)))) subnetworks = collect(keys(subnetworks)) container.expressions = Dict( ExpressionKey(ActivePowerBalance, PSY.System) => _make_container_array(subnetworks, time_steps), - ExpressionKey(ActivePowerBalance, PSY.Bus) => - _make_container_array(bus_numbers, time_steps), + ExpressionKey(ActivePowerBalance, PSY.DCBus) => + _make_container_array(dc_bus_numbers, time_steps), + ExpressionKey(ActivePowerBalance, PSY.ACBus) => + _make_container_array(ac_bus_numbers, time_steps), ) return end @@ -487,8 +501,10 @@ function initialize_system_expressions!( container::OptimizationContainer, ::Type{T}, subnetworks::Dict{Int, Set{Int}}, + system::PSY.System, ) where {T <: PM.AbstractPowerModel} - _make_system_expressions!(container, subnetworks, T) + dc_bus_numbers = [PSY.get_number(b) for b in PSY.get_components(PSY.DCBus, system)] + _make_system_expressions!(container, subnetworks, dc_bus_numbers, T) return end @@ -499,7 +515,12 @@ function build_impl!( ) transmission = get_network_formulation(template) transmission_model = get_network_model(template) - initialize_system_expressions!(container, transmission, transmission_model.subnetworks) + initialize_system_expressions!( + container, + transmission, + transmission_model.subnetworks, + sys, + ) # Order is required for device_model in values(template.devices) @@ -607,7 +628,7 @@ function build_impl!( @debug "Building Objective" _group = LOG_GROUP_OPTIMIZATION_CONTAINER update_objective_function!(container) end - @debug "Total operation count $(container.JuMPmodel.operator_counter)" _group = + @debug "Total operation count $(PSI.get_jump_model(container).operator_counter)" _group = LOG_GROUP_OPTIMIZATION_CONTAINER check_optimization_container(container) @@ -1325,7 +1346,7 @@ function get_expression( ::Type{U}, meta = CONTAINER_KEY_EMPTY_META, ) where {T <: SystemBalanceExpressions, U <: PM.AbstractPowerModel} - return get_expression(container, ExpressionKey(T, PSY.Bus, meta)) + return get_expression(container, ExpressionKey(T, PSY.ACBus, meta)) end function get_expression( diff --git a/src/core/variables.jl b/src/core/variables.jl index 083fa93f84..a4f228bdd4 100644 --- a/src/core/variables.jl +++ b/src/core/variables.jl @@ -172,7 +172,7 @@ struct FlowReactivePowerToFromVariable <: VariableType end struct PhaseShifterAngle <: VariableType end -# Necessary as a work around for HVDCP2P models with losses +# Necessary as a work around for HVDCTwoTerminal models with losses struct HVDCLosses <: VariableType end struct HVDCFlowDirectionVariable <: VariableType end diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index e5cd948924..6566bb9a1a 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -152,57 +152,6 @@ function construct_device!( return end -function construct_device!( - container::OptimizationContainer, - sys::PSY.System, - ::ArgumentConstructStage, - device_model::DeviceModel{T, HVDCP2PLossless}, - network_model::NetworkModel{CopperPlatePowerModel}, -) where {T <: PSY.DCBranch} - if has_subnetworks(network_model) - devices = - get_available_components(T, sys, get_attribute(device_model, "filter_function")) - add_variables!( - container, - FlowActivePowerVariable, - network_model, - devices, - HVDCP2PLossless(), - ) - add_to_expression!( - container, - ActivePowerBalance, - FlowActivePowerVariable, - devices, - device_model, - network_model, - ) - end - return -end - -function construct_device!( - container::OptimizationContainer, - sys::PSY.System, - ::ModelConstructStage, - device_model::DeviceModel{T, HVDCP2PLossless}, - network_model::NetworkModel{CopperPlatePowerModel}, -) where {T <: PSY.DCBranch} - if has_subnetworks(network_model) - devices = - get_available_components(T, sys, get_attribute(device_model, "filter_function")) - add_constraints!( - container, - FlowRateConstraint, - devices, - device_model, - network_model, - ) - add_constraint_dual!(container, sys, device_model) - end - return -end - construct_device!( ::OptimizationContainer, ::PSY.System, @@ -396,14 +345,71 @@ function construct_device!( return end -################################### P2P HVDC Line Models ################################### +################################### TwoTerminal HVDC Line Models ################################### +function construct_device!( + container::OptimizationContainer, + sys::PSY.System, + ::ArgumentConstructStage, + device_model::DeviceModel{T, HVDCTwoTerminalLossless}, + network_model::NetworkModel{CopperPlatePowerModel}, +) where {T <: TwoTerminalHVDCTypes} + if has_subnetworks(network_model) + devices = + get_available_components(T, sys, get_attribute(device_model, "filter_function")) + add_variables!( + container, + FlowActivePowerVariable, + network_model, + devices, + HVDCTwoTerminalLossless(), + ) + add_to_expression!( + container, + ActivePowerBalance, + FlowActivePowerVariable, + devices, + device_model, + network_model, + ) + end + return +end + +function construct_device!( + container::OptimizationContainer, + sys::PSY.System, + ::ModelConstructStage, + device_model::DeviceModel{T, HVDCTwoTerminalLossless}, + network_model::NetworkModel{CopperPlatePowerModel}, +) where {T <: TwoTerminalHVDCTypes} + if has_subnetworks(network_model) + devices = + get_available_components(T, sys, get_attribute(device_model, "filter_function")) + add_constraints!( + container, + FlowRateConstraint, + devices, + device_model, + network_model, + ) + add_constraint_dual!(container, sys, device_model) + end + return +end + function construct_device!( ::OptimizationContainer, ::PSY.System, ::ArgumentConstructStage, ::DeviceModel{T, F}, ::NetworkModel{S}, -) where {T <: PSY.DCBranch, F <: HVDCP2PUnbounded, S <: PM.AbstractPowerModel} end +) where { + T <: TwoTerminalHVDCTypes, + F <: HVDCTwoTerminalUnbounded, + S <: PM.AbstractPowerModel, +} + return +end function construct_device!( container::OptimizationContainer, @@ -411,11 +417,15 @@ function construct_device!( ::ModelConstructStage, model::DeviceModel{T, U}, ::NetworkModel{S}, -) where {T <: PSY.DCBranch, U <: HVDCP2PUnbounded, S <: PM.AbstractPowerModel} +) where { + T <: TwoTerminalHVDCTypes, + U <: HVDCTwoTerminalUnbounded, + S <: PM.AbstractPowerModel, +} add_constraint_dual!(container, sys, model) end -# Repeated method to avoid ambiguity between HVDCP2PUnbounded and HVDCP2PLossless +# Repeated method to avoid ambiguity between HVDCTwoTerminalUnbounded and HVDCTwoTerminalLossless function construct_device!( container::OptimizationContainer, sys::PSY.System, @@ -423,8 +433,8 @@ function construct_device!( model::DeviceModel{T, U}, network_model::NetworkModel{S}, ) where { - T <: PSY.DCBranch, - U <: HVDCP2PUnbounded, + T <: TwoTerminalHVDCTypes, + U <: HVDCTwoTerminalUnbounded, S <: Union{StandardPTDFModel, PTDFPowerModel}, } devices = @@ -441,7 +451,7 @@ function construct_device!( return end -# Repeated method to avoid ambiguity between HVDCP2PUnbounded and HVDCP2PLossless +# Repeated method to avoid ambiguity between HVDCTwoTerminalUnbounded and HVDCTwoTerminalLossless function construct_device!( container::OptimizationContainer, sys::PSY.System, @@ -449,8 +459,8 @@ function construct_device!( model::DeviceModel{T, U}, network_model::NetworkModel{S}, ) where { - T <: PSY.DCBranch, - U <: HVDCP2PUnbounded, + T <: TwoTerminalHVDCTypes, + U <: HVDCTwoTerminalUnbounded, S <: Union{StandardPTDFModel, PTDFPowerModel}, } add_constraint_dual!(container, sys, model) @@ -463,7 +473,13 @@ function construct_device!( ::ArgumentConstructStage, ::DeviceModel{T, F}, ::NetworkModel{S}, -) where {T <: PSY.DCBranch, F <: HVDCP2PLossless, S <: PM.AbstractPowerModel} end +) where { + T <: TwoTerminalHVDCTypes, + F <: HVDCTwoTerminalLossless, + S <: PM.AbstractPowerModel, +} + return +end function construct_device!( container::OptimizationContainer, @@ -471,7 +487,11 @@ function construct_device!( ::ModelConstructStage, model::DeviceModel{T, U}, network_model::NetworkModel{S}, -) where {T <: PSY.DCBranch, U <: HVDCP2PLossless, S <: PM.AbstractPowerModel} +) where { + T <: TwoTerminalHVDCTypes, + U <: HVDCTwoTerminalLossless, + S <: PM.AbstractPowerModel, +} devices = get_available_components(T, sys, get_attribute(model, "filter_function")) add_constraints!(container, FlowRateConstraint, devices, model, network_model) @@ -479,14 +499,14 @@ function construct_device!( return end -# Repeated method to avoid ambiguity between HVDCP2PUnbounded and HVDCP2PLossless +# Repeated method to avoid ambiguity between HVDCTwoTerminalUnbounded and HVDCTwoTerminalLossless function construct_device!( container::OptimizationContainer, sys::PSY.System, ::ArgumentConstructStage, model::DeviceModel{T, U}, network_model::NetworkModel{<:Union{StandardPTDFModel, PTDFPowerModel}}, -) where {T <: PSY.DCBranch, U <: HVDCP2PLossless} +) where {T <: TwoTerminalHVDCTypes, U <: HVDCTwoTerminalLossless} devices = get_available_components(T, sys, get_attribute(model, "filter_function")) add_variables!(container, FlowActivePowerVariable, devices, U()) @@ -501,14 +521,17 @@ function construct_device!( return end -# Repeated method to avoid ambiguity between HVDCP2PUnbounded and HVDCP2PLossless +# Repeated method to avoid ambiguity between HVDCTwoTerminalUnbounded and HVDCTwoTerminalLossless function construct_device!( container::OptimizationContainer, sys::PSY.System, ::ModelConstructStage, - model::DeviceModel{T, U}, - network_model::NetworkModel{<:Union{StandardPTDFModel, PTDFPowerModel}}, -) where {T <: PSY.HVDCLine, U <: HVDCP2PLossless} + model::DeviceModel{T, HVDCTwoTerminalLossless}, + network_model::NetworkModel{U}, +) where { + T <: TwoTerminalHVDCTypes, + U <: Union{StandardPTDFModel, PTDFPowerModel}, +} devices = get_available_components(T, sys, get_attribute(model, "filter_function")) add_constraints!(container, FlowRateConstraint, devices, model, network_model) @@ -520,15 +543,25 @@ function construct_device!( container::OptimizationContainer, sys::PSY.System, ::ArgumentConstructStage, - model::DeviceModel{PSY.HVDCLine, HVDCP2PDispatch}, + model::DeviceModel{T, HVDCTwoTerminalDispatch}, network_model::NetworkModel{StandardPTDFModel}, -) +) where {T <: TwoTerminalHVDCTypes} devices = - get_available_components(PSY.HVDCLine, sys, get_attribute(model, "filter_function")) - add_variables!(container, FlowActivePowerToFromVariable, devices, HVDCP2PDispatch()) - add_variables!(container, FlowActivePowerFromToVariable, devices, HVDCP2PDispatch()) - add_variables!(container, HVDCLosses, devices, HVDCP2PDispatch()) - add_variables!(container, HVDCFlowDirectionVariable, devices, HVDCP2PDispatch()) + get_available_components(T, sys, get_attribute(model, "filter_function")) + add_variables!( + container, + FlowActivePowerToFromVariable, + devices, + HVDCTwoTerminalDispatch(), + ) + add_variables!( + container, + FlowActivePowerFromToVariable, + devices, + HVDCTwoTerminalDispatch(), + ) + add_variables!(container, HVDCLosses, devices, HVDCTwoTerminalDispatch()) + add_variables!(container, HVDCFlowDirectionVariable, devices, HVDCTwoTerminalDispatch()) add_to_expression!( container, ActivePowerBalance, @@ -560,16 +593,15 @@ function construct_device!( container::OptimizationContainer, sys::PSY.System, ::ModelConstructStage, - model::DeviceModel{PSY.HVDCLine, HVDCP2PDispatch}, + model::DeviceModel{T, HVDCTwoTerminalDispatch}, network_model::NetworkModel{StandardPTDFModel}, -) +) where {T <: TwoTerminalHVDCTypes} devices = - get_available_components(PSY.HVDCLine, sys, get_attribute(model, "filter_function")) + get_available_components(T, sys, get_attribute(model, "filter_function")) add_constraints!(container, FlowRateConstraintFromTo, devices, model, network_model) add_constraints!(container, FlowRateConstraintToFrom, devices, model, network_model) add_constraints!(container, HVDCPowerBalance, devices, model, network_model) add_constraints!(container, HVDCLossesAbsoluteValue, devices, model, network_model) - add_constraint_dual!(container, sys, model) return end @@ -577,14 +609,24 @@ function construct_device!( container::OptimizationContainer, sys::PSY.System, ::ArgumentConstructStage, - model::DeviceModel{PSY.HVDCLine, HVDCP2PDispatch}, - network_model::NetworkModel{T}, -) where {T <: PM.AbstractActivePowerModel} + model::DeviceModel{T, HVDCTwoTerminalDispatch}, + network_model::NetworkModel{U}, +) where {T <: TwoTerminalHVDCTypes, U <: PM.AbstractActivePowerModel} devices = - get_available_components(PSY.HVDCLine, sys, get_attribute(model, "filter_function")) - add_variables!(container, FlowActivePowerToFromVariable, devices, HVDCP2PDispatch()) - add_variables!(container, FlowActivePowerFromToVariable, devices, HVDCP2PDispatch()) - add_variables!(container, HVDCFlowDirectionVariable, devices, HVDCP2PDispatch()) + get_available_components(T, sys, get_attribute(model, "filter_function")) + add_variables!( + container, + FlowActivePowerToFromVariable, + devices, + HVDCTwoTerminalDispatch(), + ) + add_variables!( + container, + FlowActivePowerFromToVariable, + devices, + HVDCTwoTerminalDispatch(), + ) + add_variables!(container, HVDCFlowDirectionVariable, devices, HVDCTwoTerminalDispatch()) add_to_expression!( container, ActivePowerBalance, @@ -608,11 +650,11 @@ function construct_device!( container::OptimizationContainer, sys::PSY.System, ::ModelConstructStage, - model::DeviceModel{PSY.HVDCLine, HVDCP2PDispatch}, - network_model::NetworkModel{T}, -) where {T <: PM.AbstractActivePowerModel} + model::DeviceModel{T, HVDCTwoTerminalDispatch}, + network_model::NetworkModel{U}, +) where {T <: TwoTerminalHVDCTypes, U <: PM.AbstractActivePowerModel} devices = - get_available_components(PSY.HVDCLine, sys, get_attribute(model, "filter_function")) + get_available_components(T, sys, get_attribute(model, "filter_function")) add_constraints!(container, FlowRateConstraintFromTo, devices, model, network_model) add_constraints!(container, FlowRateConstraintToFrom, devices, model, network_model) add_constraints!(container, HVDCPowerBalance, devices, model, network_model) @@ -621,26 +663,6 @@ function construct_device!( return end -function construct_device!( - ::OptimizationContainer, - ::PSY.System, - ::ArgumentConstructStage, - ::DeviceModel{PSY.HVDCLine, HVDCP2PDispatch}, - ::NetworkModel{T}, -) where {T <: PM.AbstractPowerModel} - return -end - -function construct_device!( - ::OptimizationContainer, - ::PSY.System, - ::ModelConstructStage, - ::DeviceModel{PSY.HVDCLine, HVDCP2PDispatch}, - ::NetworkModel{T}, -) where {T <: PM.AbstractPowerModel} - return -end - ############################# Phase Shifter Transformer Models ############################# function construct_device!( diff --git a/src/devices_models/device_constructors/hvdcsystems_constructor.jl b/src/devices_models/device_constructors/hvdcsystems_constructor.jl new file mode 100644 index 0000000000..cd176bb292 --- /dev/null +++ b/src/devices_models/device_constructors/hvdcsystems_constructor.jl @@ -0,0 +1,66 @@ +function construct_device!( + container::OptimizationContainer, + sys::PSY.System, + ::ArgumentConstructStage, + model::DeviceModel{PSY.InterconnectingConverter, LossLessConverter}, + network_model::NetworkModel{S}, +) where {S <: PM.AbstractActivePowerModel} + devices = get_available_components(PSY.InterconnectingConverter, sys) + add_variables!(container, ActivePowerVariable, devices, LossLessConverter()) + add_to_expression!( + container, + ActivePowerBalance, + ActivePowerVariable, + devices, + model, + network_model, + ) + add_feedforward_arguments!(container, model, devices) + return +end + +function construct_device!( + container::OptimizationContainer, + sys::PSY.System, + ::ModelConstructStage, + model::DeviceModel{PSY.InterconnectingConverter, LossLessConverter}, + ::NetworkModel{S}, +) where {S <: PM.AbstractActivePowerModel} + devices = get_available_components(PSY.InterconnectingConverter, sys) + add_feedforward_constraints!(container, model, devices) + objective_function!(container, devices, model, S) + add_constraint_dual!(container, sys, model) + return +end + +function construct_device!( + container::OptimizationContainer, + sys::PSY.System, + ::ArgumentConstructStage, + model::DeviceModel{PSY.TModelHVDCLine, LossLessLine}, + network_model::NetworkModel{S}, +) where {S <: PM.AbstractActivePowerModel} + devices = get_available_components(PSY.TModelHVDCLine, sys) + add_variables!(container, FlowActivePowerVariable, devices, LossLessLine()) + add_to_expression!( + container, + ActivePowerBalance, + FlowActivePowerVariable, + devices, + model, + network_model, + ) + add_feedforward_arguments!(container, model, devices) + return +end + +function construct_device!( + ::OptimizationContainer, + sys::PSY.System, + ::ModelConstructStage, + model::DeviceModel{PSY.TModelHVDCLine, LossLessLine}, + ::NetworkModel{S}, +) where {S <: PM.AbstractActivePowerModel} + devices = get_available_components(PSY.TModelHVDCLine, sys) + return +end diff --git a/src/devices_models/device_constructors/thermalgeneration_constructor.jl b/src/devices_models/device_constructors/thermalgeneration_constructor.jl index 59f1c6083d..721d21b619 100644 --- a/src/devices_models/device_constructors/thermalgeneration_constructor.jl +++ b/src/devices_models/device_constructors/thermalgeneration_constructor.jl @@ -885,6 +885,7 @@ function construct_device!( model, network_model, ) + add_to_expression!( container, ReactivePowerBalance, @@ -1012,6 +1013,7 @@ function construct_device!( model, network_model, ) + add_to_expression!( container, ActivePowerBalance, @@ -1597,6 +1599,7 @@ function construct_device!( model, network_model, ) + add_to_expression!( container, ActivePowerRangeExpressionLB, diff --git a/src/devices_models/devices/AC_branches.jl b/src/devices_models/devices/AC_branches.jl index 191c7d1727..a5f5cd4252 100644 --- a/src/devices_models/devices/AC_branches.jl +++ b/src/devices_models/devices/AC_branches.jl @@ -339,7 +339,7 @@ function add_constraints!( branches, time_steps, ) - nodal_balance_expressions = get_expression(container, ActivePowerBalance(), PSY.Bus) + nodal_balance_expressions = get_expression(container, ActivePowerBalance(), PSY.ACBus) flow_variables = get_variable(container, FlowActivePowerVariable(), T) angle_variables = get_variable(container, PhaseShifterAngle(), T) jump_model = get_jump_model(container) @@ -546,7 +546,7 @@ function add_constraints!( time_steps = get_time_steps(container) flow_variables = get_variable(container, FlowActivePowerVariable(), T) ps_angle_variables = get_variable(container, PhaseShifterAngle(), T) - bus_angle_variables = get_variable(container, VoltageAngle(), PSY.Bus) + bus_angle_variables = get_variable(container, VoltageAngle(), PSY.ACBus) jump_model = get_jump_model(container) branch_flow = add_constraints_container!( container, diff --git a/src/devices_models/devices/HVDCsystems.jl b/src/devices_models/devices/HVDCsystems.jl new file mode 100644 index 0000000000..ee20e478f6 --- /dev/null +++ b/src/devices_models/devices/HVDCsystems.jl @@ -0,0 +1,259 @@ +#! format: off +get_variable_binary(::ActivePowerVariable, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = false +get_variable_warm_start_value(::ActivePowerVariable, d::PSY.InterconnectingConverter, ::AbstractConverterFormulation) = PSY.get_active_power(d) +get_variable_lower_bound(::ActivePowerVariable, d::PSY.InterconnectingConverter, ::AbstractConverterFormulation) = PSY.get_active_power_limits(d).min +get_variable_upper_bound(::ActivePowerVariable, d::PSY.InterconnectingConverter, ::AbstractConverterFormulation) = PSY.get_active_power_limits(d).max +get_variable_multiplier(_, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = 1.0 + + +function _get_flow_bounds(d::PSY.TModelHVDCLine) + check_hvdc_line_limits_consistency(d) + from_min = PSY.get_active_power_limits_from(d).min + to_min = PSY.get_active_power_limits_to(d).min + from_max = PSY.get_active_power_limits_from(d).max + to_max = PSY.get_active_power_limits_to(d).max + + if from_min >= 0.0 && to_min >= 0.0 + min_rate = min(from_min, to_min) + elseif from_min <= 0.0 && to_min <= 0.0 + min_rate = max(from_min, to_min) + elseif from_min <= 0.0 && to_min >= 0.0 + min_rate = from_min + elseif to_min <= 0.0 && from_min >= 0.0 + min_rate = to_min + else + @assert false + end + + if from_max >= 0.0 && to_max >= 0.0 + max_rate = min(from_max, to_max) + elseif from_max <= 0.0 && to_max <= 0.0 + max_rate = max(from_max, to_max) + elseif from_max <= 0.0 && to_max >= 0.0 + max_rate = from_max + elseif from_max >= 0.0 && to_max <= 0.0 + max_rate = to_max + else + @assert false + end + + return min_rate, max_rate +end + + +get_variable_binary(::FlowActivePowerVariable, ::Type{PSY.TModelHVDCLine}, ::AbstractBranchFormulation) = false +get_variable_warm_start_value(::FlowActivePowerVariable, d::PSY.TModelHVDCLine, ::AbstractBranchFormulation) = PSY.get_active_power_flow(d) +get_variable_lower_bound(::FlowActivePowerVariable, d::PSY.TModelHVDCLine, ::AbstractBranchFormulation) = _get_flow_bounds(d)[1] +get_variable_upper_bound(::FlowActivePowerVariable, d::PSY.TModelHVDCLine, ::AbstractBranchFormulation) = _get_flow_bounds(d)[2] +get_variable_multiplier(_, ::Type{PSY.TModelHVDCLine}, ::AbstractBranchFormulation) = 1.0 + +requires_initialization(::AbstractConverterFormulation) = false +requires_initialization(::LossLessLine) = false + +function get_initial_conditions_device_model( + ::OperationModel, + model::DeviceModel{PSY.InterconnectingConverter, <:AbstractConverterFormulation}, +) + return model +end + +function get_initial_conditions_device_model( + ::OperationModel, + model::DeviceModel{PSY.TModelHVDCLine, LossLessLine}, +) + return model +end + + +function get_default_time_series_names( + ::Type{PSY.InterconnectingConverter}, + ::Type{<:AbstractConverterFormulation}, +) + return Dict{Type{<:TimeSeriesParameter}, String}() +end + +function get_default_time_series_names( + ::Type{PSY.TModelHVDCLine}, + ::Type{<:AbstractBranchFormulation}, +) + return Dict{Type{<:TimeSeriesParameter}, String}() +end + +function get_default_attributes( + ::Type{PSY.InterconnectingConverter}, + ::Type{<:AbstractConverterFormulation}, +) + return Dict{String, Any}() +end + +function get_default_attributes( + ::Type{PSY.TModelHVDCLine}, + ::Type{<:AbstractBranchFormulation}, +) + return Dict{String, Any}() +end + +function add_to_expression!( + container::OptimizationContainer, + ::Type{T}, + ::Type{U}, + devices::IS.FlattenIteratorWrapper{V}, + ::DeviceModel{V, W}, + network_model::NetworkModel{X}, +) where { + T <: ActivePowerBalance, + U <: FlowActivePowerVariable, + V <: PSY.TModelHVDCLine, + W <: LossLessLine, + X <: PM.AbstractPowerModel, +} + variable = get_variable(container, U(), V) + expression = get_expression(container, T(), PSY.DCBus) + for d in devices + arc = PSY.get_arc(d) + to_bus_number = PSY.get_number(PSY.get_to(arc)) + from_bus_number = PSY.get_number(PSY.get_from(arc)) + for t in get_time_steps(container) + name = PSY.get_name(d) + _add_to_jump_expression!( + expression[to_bus_number, t], + variable[name, t], + 1.0, + ) + _add_to_jump_expression!( + expression[from_bus_number, t], + variable[name, t], + -1.0, + ) + end + end + return +end + +function add_to_expression!( + container::OptimizationContainer, + ::Type{T}, + ::Type{U}, + devices::IS.FlattenIteratorWrapper{V}, + ::DeviceModel{V, W}, + network_model::NetworkModel{X}, +) where { + T <: ActivePowerBalance, + U <: ActivePowerVariable, + V <: PSY.InterconnectingConverter, + W <: AbstractConverterFormulation, + X <: PM.AbstractPowerModel, +} + variable = get_variable(container, U(), V) + expression_dc = get_expression(container, T(), PSY.DCBus) + expression_ac = get_expression(container, T(), PSY.ACBus) + for d in devices, t in get_time_steps(container) + name = PSY.get_name(d) + bus_number_dc = PSY.get_number(PSY.get_dc_bus(d)) + bus_number_ac = PSY.get_number(PSY.get_bus(d)) + _add_to_jump_expression!( + expression_ac[bus_number_ac, t], + variable[name, t], + 1.0, + ) + _add_to_jump_expression!( + expression_dc[bus_number_dc, t], + variable[name, t], + -1.0, + ) + end + return +end + +function add_to_expression!( + ::OptimizationContainer, + ::Type{T}, + ::Type{U}, + ::IS.FlattenIteratorWrapper{V}, + devices::DeviceModel{V, W}, + network_model::NetworkModel{CopperPlatePowerModel}, +) where { + T <: ActivePowerBalance, + U <: ActivePowerVariable, + V <: PSY.InterconnectingConverter, + W <: AbstractConverterFormulation, +} + + variable = get_variable(container, U(), V) + expression_dc = get_expression(container, T(), PSY.DCBus) + sys_expr = get_expression(container, T(), PSY.System) + for d in devices, t in get_time_steps(container) + name = PSY.get_name(d) + device_bus = PSY.get_bus(d) + ref_bus = get_reference_bus(network_model, device_bus) + bus_number_dc = PSY.get_number(PSY.get_dc_bus(d)) + for t in get_time_steps(container) + _add_to_jump_expression!( + sys_expr[ref_bus, t], + variable[name, t], + get_variable_multiplier(U(), V, W()), + ) + _add_to_jump_expression!( + expression_dc[bus_number_dc, t], + variable[name, t], + -1.0, + ) + end + end + return +end + +function add_to_expression!( + container::OptimizationContainer, + ::Type{T}, + ::Type{U}, + devices::IS.FlattenIteratorWrapper{V}, + ::DeviceModel{V, W}, + network_model::NetworkModel{X}, +) where { + T <: ActivePowerBalance, + U <: ActivePowerVariable, + V <: PSY.InterconnectingConverter, + W <: AbstractConverterFormulation, + X <: Union{PTDFPowerModel, StandardPTDFModel}, +} + variable = get_variable(container, U(), V) + expression_dc = get_expression(container, T(), PSY.DCBus) + expression_ac = get_expression(container, T(), PSY.ACBus) + sys_expr = get_expression(container, T(), PSY.System) + for d in devices + name = PSY.get_name(d) + device_bus = PSY.get_bus(d) + bus_number_ac = PSY.get_number(device_bus) + ref_bus = get_reference_bus(network_model, device_bus) + bus_number_dc = PSY.get_number(PSY.get_dc_bus(d)) + for t in get_time_steps(container) + _add_to_jump_expression!( + sys_expr[ref_bus, t], + variable[name, t], + get_variable_multiplier(U(), V, W()), + ) + _add_to_jump_expression!( + expression_ac[bus_number_ac, t], + variable[name, t], + get_variable_multiplier(U(), V, W()), + ) + _add_to_jump_expression!( + expression_dc[bus_number_dc, t], + variable[name, t], + -1.0, + ) + end + end + + return +end + +function objective_function!( + ::OptimizationContainer, + ::IS.FlattenIteratorWrapper{PSY.InterconnectingConverter}, + ::DeviceModel{PSY.InterconnectingConverter, LossLessConverter}, + ::Type{<:PM.AbstractPowerModel}, +) + return +end diff --git a/src/devices_models/devices/DC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl similarity index 82% rename from src/devices_models/devices/DC_branches.jl rename to src/devices_models/devices/TwoTerminalDC_branches.jl index 23cbba14f9..5483ac226f 100644 --- a/src/devices_models/devices/DC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -1,32 +1,42 @@ #################################### Branch Variables ################################################## -get_variable_binary(_, ::Type{<:PSY.DCBranch}, ::AbstractDCLineFormulation) = false +get_variable_binary( + _, + ::Type{<:PSY.TwoTerminalHVDCLine}, + ::AbstractTwoTerminalDCLineFormulation, +) = + false get_variable_binary( ::FlowActivePowerVariable, - ::Type{<:PSY.DCBranch}, - ::AbstractDCLineFormulation, + ::Type{<:PSY.TwoTerminalHVDCLine}, + ::AbstractTwoTerminalDCLineFormulation, ) = false get_variable_binary( ::HVDCFlowDirectionVariable, - ::Type{<:PSY.DCBranch}, - ::AbstractDCLineFormulation, + ::Type{<:PSY.TwoTerminalHVDCLine}, + ::AbstractTwoTerminalDCLineFormulation, ) = true -get_variable_multiplier(::FlowActivePowerVariable, ::Type{<:PSY.DCBranch}, _) = NaN +get_variable_multiplier(::FlowActivePowerVariable, ::Type{<:PSY.TwoTerminalHVDCLine}, _) = + NaN get_variable_multiplier( ::FlowActivePowerFromToVariable, - ::Type{<:PSY.DCBranch}, - ::AbstractDCLineFormulation, + ::Type{<:PSY.TwoTerminalHVDCLine}, + ::AbstractTwoTerminalDCLineFormulation, ) = -1.0 get_variable_multiplier( ::FlowActivePowerToFromVariable, - ::Type{<:PSY.DCBranch}, - ::AbstractDCLineFormulation, + ::Type{<:PSY.TwoTerminalHVDCLine}, + ::AbstractTwoTerminalDCLineFormulation, ) = 1.0 -function get_variable_multiplier(::HVDCLosses, d::PSY.DCBranch, ::HVDCP2PDispatch) +function get_variable_multiplier( + ::HVDCLosses, + d::PSY.TwoTerminalHVDCLine, + ::HVDCTwoTerminalDispatch, +) l1 = PSY.get_loss(d).l1 l0 = PSY.get_loss(d).l0 if l1 == 0.0 && l0 == 0.0 @@ -36,27 +46,41 @@ function get_variable_multiplier(::HVDCLosses, d::PSY.DCBranch, ::HVDCP2PDispatc end end -get_variable_lower_bound(::FlowActivePowerVariable, d::PSY.DCBranch, ::HVDCP2PUnbounded) = - nothing +get_variable_lower_bound( + ::FlowActivePowerVariable, + d::PSY.TwoTerminalHVDCLine, + ::HVDCTwoTerminalUnbounded, +) = nothing -get_variable_upper_bound(::FlowActivePowerVariable, d::PSY.DCBranch, ::HVDCP2PUnbounded) = - nothing +get_variable_upper_bound( + ::FlowActivePowerVariable, + d::PSY.TwoTerminalHVDCLine, + ::HVDCTwoTerminalUnbounded, +) = nothing get_variable_lower_bound( ::FlowActivePowerVariable, - d::PSY.DCBranch, - ::AbstractDCLineFormulation, + d::PSY.TwoTerminalHVDCLine, + ::AbstractTwoTerminalDCLineFormulation, ) = nothing get_variable_upper_bound( ::FlowActivePowerVariable, - d::PSY.DCBranch, - ::AbstractDCLineFormulation, + d::PSY.TwoTerminalHVDCLine, + ::AbstractTwoTerminalDCLineFormulation, ) = nothing -get_variable_lower_bound(::HVDCLosses, d::PSY.DCBranch, ::HVDCP2PDispatch) = 0.0 - -function get_variable_upper_bound(::HVDCLosses, d::PSY.DCBranch, ::HVDCP2PDispatch) +get_variable_lower_bound( + ::HVDCLosses, + d::PSY.TwoTerminalHVDCLine, + ::HVDCTwoTerminalDispatch, +) = 0.0 + +function get_variable_upper_bound( + ::HVDCLosses, + d::PSY.TwoTerminalHVDCLine, + ::HVDCTwoTerminalDispatch, +) l1 = PSY.get_loss(d).l1 l0 = PSY.get_loss(d).l0 if l1 == 0.0 && l0 == 0.0 @@ -69,24 +93,25 @@ end function get_default_time_series_names( ::Type{U}, ::Type{V}, -) where {U <: PSY.DCBranch, V <: AbstractDCLineFormulation} +) where {U <: PSY.TwoTerminalHVDCLine, V <: AbstractTwoTerminalDCLineFormulation} return Dict{Type{<:TimeSeriesParameter}, String}() end function get_default_attributes( ::Type{U}, ::Type{V}, -) where {U <: PSY.DCBranch, V <: AbstractDCLineFormulation} +) where {U <: PSY.TwoTerminalHVDCLine, V <: AbstractTwoTerminalDCLineFormulation} return Dict{String, Any}() end get_initial_conditions_device_model( ::OperationModel, ::DeviceModel{T, U}, -) where {T <: PSY.HVDCLine, U <: AbstractDCLineFormulation} = DeviceModel(T, U) +) where {T <: PSY.TwoTerminalHVDCLine, U <: AbstractTwoTerminalDCLineFormulation} = + DeviceModel(T, U) #################################### Rate Limits Constraints ################################################## -function _get_flow_bounds(d::PSY.HVDCLine) +function _get_flow_bounds(d::PSY.TwoTerminalHVDCLine) check_hvdc_line_limits_consistency(d) from_min = PSY.get_active_power_limits_from(d).min to_min = PSY.get_active_power_limits_to(d).min @@ -119,16 +144,16 @@ end add_constraints!( ::OptimizationContainer, ::Type{<:Union{FlowRateConstraintFromTo, FlowRateConstraintToFrom}}, - ::IS.FlattenIteratorWrapper{<:PSY.DCBranch}, - ::DeviceModel{<:PSY.DCBranch, HVDCP2PUnbounded}, + ::IS.FlattenIteratorWrapper{<:PSY.TwoTerminalHVDCLine}, + ::DeviceModel{<:PSY.TwoTerminalHVDCLine, HVDCTwoTerminalUnbounded}, ::NetworkModel{<:PM.AbstractPowerModel}, ) = nothing add_constraints!( ::OptimizationContainer, ::Type{FlowRateConstraint}, - ::IS.FlattenIteratorWrapper{<:PSY.DCBranch}, - ::DeviceModel{<:PSY.DCBranch, HVDCP2PUnbounded}, + ::IS.FlattenIteratorWrapper{<:PSY.TwoTerminalHVDCLine}, + ::DeviceModel{<:PSY.TwoTerminalHVDCLine, HVDCTwoTerminalUnbounded}, ::NetworkModel{<:PM.AbstractPowerModel}, ) = nothing @@ -136,9 +161,9 @@ function add_constraints!( container::OptimizationContainer, ::Type{T}, devices::Union{Vector{U}, IS.FlattenIteratorWrapper{U}}, - ::DeviceModel{U, HVDCP2PLossless}, + ::DeviceModel{U, HVDCTwoTerminalLossless}, ::NetworkModel{<:PM.AbstractPowerModel}, -) where {T <: FlowRateConstraint, U <: PSY.DCBranch} +) where {T <: FlowRateConstraint, U <: PSY.TwoTerminalHVDCLine} time_steps = get_time_steps(container) names = [PSY.get_name(d) for d in devices] @@ -167,9 +192,9 @@ function add_constraints!( container::OptimizationContainer, ::Type{FlowRateConstraint}, devices::IS.FlattenIteratorWrapper{T}, - model::DeviceModel{T, HVDCP2PLossless}, + model::DeviceModel{T, HVDCTwoTerminalLossless}, network_model::NetworkModel{CopperPlatePowerModel}, -) where {T <: PSY.DCBranch} +) where {T <: PSY.TwoTerminalHVDCLine} inter_network_branches = T[] for d in devices ref_bus_from = get_reference_bus(network_model, PSY.get_arc(d).from) @@ -194,9 +219,9 @@ function add_constraints!( container::OptimizationContainer, ::Type{T}, devices::IS.FlattenIteratorWrapper{U}, - ::DeviceModel{U, HVDCP2PDispatch}, + ::DeviceModel{U, HVDCTwoTerminalDispatch}, ::NetworkModel{<:PM.AbstractDCPModel}, -) where {T <: FlowRateConstraintFromTo, U <: PSY.DCBranch} +) where {T <: FlowRateConstraintFromTo, U <: PSY.TwoTerminalHVDCLine} time_steps = get_time_steps(container) names = [PSY.get_name(d) for d in devices] @@ -225,9 +250,9 @@ function add_constraints!( container::OptimizationContainer, ::Type{T}, devices::IS.FlattenIteratorWrapper{U}, - ::DeviceModel{U, HVDCP2PDispatch}, + ::DeviceModel{U, HVDCTwoTerminalDispatch}, ::NetworkModel{<:PM.AbstractDCPModel}, -) where {T <: FlowRateConstraintToFrom, U <: PSY.DCBranch} +) where {T <: FlowRateConstraintToFrom, U <: PSY.TwoTerminalHVDCLine} time_steps = get_time_steps(container) names = [PSY.get_name(d) for d in devices] @@ -256,9 +281,9 @@ function add_constraints!( container::OptimizationContainer, ::Type{T}, devices::IS.FlattenIteratorWrapper{U}, - ::DeviceModel{U, HVDCP2PDispatch}, + ::DeviceModel{U, HVDCTwoTerminalDispatch}, ::NetworkModel{<:PM.AbstractDCPModel}, -) where {T <: HVDCDirection, U <: PSY.DCBranch} +) where {T <: HVDCDirection, U <: PSY.TwoTerminalHVDCLine} time_steps = get_time_steps(container) names = [PSY.get_name(d) for d in devices] @@ -304,9 +329,9 @@ function add_constraints!( container::OptimizationContainer, ::Type{HVDCPowerBalance}, devices::IS.FlattenIteratorWrapper{T}, - ::DeviceModel{T, <:AbstractDCLineFormulation}, + ::DeviceModel{T, <:AbstractTwoTerminalDCLineFormulation}, ::NetworkModel{<:PM.AbstractDCPModel}, -) where {T <: PSY.DCBranch} +) where {T <: PSY.TwoTerminalHVDCLine} time_steps = get_time_steps(container) names = [PSY.get_name(d) for d in devices] tf_var = get_variable(container, FlowActivePowerToFromVariable(), T) @@ -387,9 +412,9 @@ function add_constraints!( container::OptimizationContainer, ::Type{HVDCLossesAbsoluteValue}, devices::IS.FlattenIteratorWrapper{T}, - ::DeviceModel{T, <:AbstractDCLineFormulation}, + ::DeviceModel{T, <:AbstractTwoTerminalDCLineFormulation}, ::NetworkModel{<:PM.AbstractDCPModel}, -) where {T <: PSY.DCBranch} +) where {T <: PSY.TwoTerminalHVDCLine} time_steps = get_time_steps(container) names = [PSY.get_name(d) for d in devices] losses = get_variable(container, HVDCLosses(), T) diff --git a/src/devices_models/devices/common/add_constraint_dual.jl b/src/devices_models/devices/common/add_constraint_dual.jl index 5527c48315..1d5e9111bd 100644 --- a/src/devices_models/devices/common/add_constraint_dual.jl +++ b/src/devices_models/devices/common/add_constraint_dual.jl @@ -19,7 +19,7 @@ function add_constraint_dual!( model::NetworkModel{T}, ) where {T <: PM.AbstractPowerModel} if !isempty(get_duals(model)) - devices = get_available_components(PSY.Bus, sys) + devices = PSY.get_components(PSY.ACBus, sys) for constraint_type in get_duals(model) assign_dual_variable!(container, constraint_type, devices, model) end @@ -96,7 +96,7 @@ function assign_dual_variable!( constraint_type::Type{<:ConstraintType}, devices::U, ::NetworkModel{<:PM.AbstractPowerModel}, -) where {U <: Union{Vector{D}, IS.FlattenIteratorWrapper{D}}} where {D <: PSY.Bus} +) where {U <: Union{Vector{D}, IS.FlattenIteratorWrapper{D}}} where {D <: PSY.ACBus} @assert !isempty(devices) time_steps = get_time_steps(container) add_dual_container!( diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index 10b70dc188..5146cf131c 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -171,7 +171,12 @@ function add_to_expression!( devices::IS.FlattenIteratorWrapper{V}, ::DeviceModel{V, W}, network_model::NetworkModel{StandardPTDFModel}, -) where {T <: ActivePowerBalance, U <: HVDCLosses, V <: PSY.HVDCLine, W <: HVDCP2PDispatch} +) where { + T <: ActivePowerBalance, + U <: HVDCLosses, + V <: TwoTerminalHVDCTypes, + W <: HVDCTwoTerminalDispatch, +} variable = get_variable(container, U(), V) expression = get_expression(container, T(), PSY.System) for d in devices @@ -363,7 +368,7 @@ function add_to_expression!( W <: AbstractDeviceFormulation, } variable = get_variable(container, U(), V) - expression = get_expression(container, T(), CopperPlatePowerModel) + expression = get_expression(container, T(), PSY.System) for d in devices device_bus = PSY.get_bus(d) ref_bus = get_reference_bus(network_model, device_bus) @@ -393,7 +398,7 @@ function add_to_expression!( W <: Union{AbstractCompactUnitCommitment, ThermalCompactDispatch}, } variable = get_variable(container, U(), V) - expression = get_expression(container, T(), CopperPlatePowerModel) + expression = get_expression(container, T(), PSY.System) for d in devices name = PSY.get_name(d) device_bus = PSY.get_bus(d) @@ -429,7 +434,7 @@ function add_to_expression!( param_container = get_parameter(container, U(), V) multiplier = get_multiplier_array(param_container) sys_expr = get_expression(container, T(), PSY.System) - nodal_expr = get_expression(container, T(), PSY.Bus) + nodal_expr = get_expression(container, T(), PSY.ACBus) for d in devices name = PSY.get_name(d) device_bus = PSY.get_bus(d) @@ -460,7 +465,7 @@ function add_to_expression!( } parameter = get_parameter_array(container, U(), V) sys_expr = get_expression(container, T(), PSY.System) - nodal_expr = get_expression(container, T(), PSY.Bus) + nodal_expr = get_expression(container, T(), PSY.ACBus) for d in devices, t in get_time_steps(container) name = PSY.get_name(d) bus_no = PSY.get_number(PSY.get_bus(d)) @@ -492,7 +497,7 @@ function add_to_expression!( } variable = get_variable(container, U(), V) sys_expr = get_expression(container, T(), PSY.System) - nodal_expr = get_expression(container, T(), PSY.Bus) + nodal_expr = get_expression(container, T(), PSY.ACBus) for d in devices name = PSY.get_name(d) device_bus = PSY.get_bus(d) @@ -530,7 +535,7 @@ function add_to_expression!( } variable = get_variable(container, U(), V) sys_expr = get_expression(container, T(), PSY.System) - nodal_expr = get_expression(container, T(), PSY.Bus) + nodal_expr = get_expression(container, T(), PSY.ACBus) for d in devices name = PSY.get_name(d) device_bus = PSY.get_bus(d) @@ -565,7 +570,7 @@ function add_to_expression!( ) where { T <: ActivePowerBalance, U <: FlowActivePowerVariable, - V <: PSY.Branch, + V <: PSY.ACBranch, W <: AbstractBranchFormulation, X <: PM.AbstractActivePowerModel, } @@ -602,12 +607,11 @@ function add_to_expression!( ) where { T <: ActivePowerBalance, U <: FlowActivePowerVariable, - V <: PSY.Branch, + V <: PSY.ACBranch, W <: AbstractBranchFormulation, } var = get_variable(container, U(), V) - nodal_expr = get_expression(container, T(), StandardPTDFModel) - var = get_variable(container, U(), V) + nodal_expr = get_expression(container, T(), PSY.ACBus) sys_expr = get_expression(container, T(), PSY.System) for d in devices bus_no_from = PSY.get_number(PSY.get_arc(d).from) @@ -640,7 +644,7 @@ function add_to_expression!( ) where { T <: ActivePowerBalance, U <: FlowActivePowerVariable, - V <: PSY.Branch, + V <: PSY.ACBranch, W <: AbstractBranchFormulation, } inter_network_branches = V[] @@ -682,7 +686,7 @@ function add_to_expression!( network_model::NetworkModel{StandardPTDFModel}, ) where {T <: ActivePowerBalance, U <: PhaseShifterAngle, V <: PhaseAngleControl} var = get_variable(container, U(), PSY.PhaseShiftingTransformer) - expression = get_expression(container, T(), PSY.Bus) + expression = get_expression(container, T(), PSY.ACBus) for d in devices for t in get_time_steps(container) flow_variable = var[PSY.get_name(d), t] @@ -933,14 +937,14 @@ function add_to_expression!( U <: Union{SystemBalanceSlackUp, SystemBalanceSlackDown}, W <: PM.AbstractActivePowerModel, } - variable = get_variable(container, U(), PSY.Bus) - expression = get_expression(container, T(), PSY.Bus) + variable = get_variable(container, U(), PSY.ACBus) + expression = get_expression(container, T(), PSY.ACBus) @assert_op length(axes(variable, 1)) == length(axes(expression, 1)) for t in get_time_steps(container), n in axes(variable, 1) _add_to_jump_expression!( expression[n, t], variable[n, t], - get_variable_multiplier(U(), PSY.Bus, W), + get_variable_multiplier(U(), PSY.ACBus, W), ) end return @@ -957,14 +961,14 @@ function add_to_expression!( U <: Union{SystemBalanceSlackUp, SystemBalanceSlackDown}, W <: PM.AbstractPowerModel, } - variable = get_variable(container, U(), PSY.Bus, "P") - expression = get_expression(container, T(), PSY.Bus) - bus_numbers = PSY.get_number.(get_available_components(PSY.Bus, sys)) + variable = get_variable(container, U(), PSY.ACBus, "P") + expression = get_expression(container, T(), PSY.ACBus) + bus_numbers = PSY.get_number.(get_available_components(PSY.ACBus, sys)) for t in get_time_steps(container), n in bus_numbers _add_to_jump_expression!( expression[n, t], variable[n, t], - get_variable_multiplier(U(), PSY.Bus, W), + get_variable_multiplier(U(), PSY.ACBus, W), ) end return @@ -981,14 +985,14 @@ function add_to_expression!( U <: Union{SystemBalanceSlackUp, SystemBalanceSlackDown}, W <: PM.AbstractPowerModel, } - variable = get_variable(container, U(), PSY.Bus, "Q") - expression = get_expression(container, T(), PSY.Bus) - bus_numbers = PSY.get_number.(get_available_components(PSY.Bus, sys)) + variable = get_variable(container, U(), PSY.ACBus, "Q") + expression = get_expression(container, T(), PSY.ACBus) + bus_numbers = PSY.get_number.(get_available_components(PSY.ACBus, sys)) for t in get_time_steps(container), n in bus_numbers _add_to_jump_expression!( expression[n, t], variable[n, t], - get_variable_multiplier(U(), PSY.Bus, W), + get_variable_multiplier(U(), PSY.ACBus, W), ) end return diff --git a/src/devices_models/devices/common/add_variable.jl b/src/devices_models/devices/common/add_variable.jl index c9bb403fe3..a0053104b5 100644 --- a/src/devices_models/devices/common/add_variable.jl +++ b/src/devices_models/devices/common/add_variable.jl @@ -135,13 +135,13 @@ function add_service_variable!( binary = binary ) - ub = get_variable_upper_bound(variable_type, service, d, container.settings) + ub = get_variable_upper_bound(variable_type, service, d, formulation) ub !== nothing && JuMP.set_upper_bound(variable[name, t], ub) - lb = get_variable_lower_bound(variable_type, service, d, container.settings) + lb = get_variable_lower_bound(variable_type, service, d, formulation) lb !== nothing && !binary && JuMP.set_lower_bound(variable[name, t], lb) - init = get_variable_warm_start_value(variable_type, d, container.settings) + init = get_variable_warm_start_value(variable_type, d, formulation) init !== nothing && JuMP.set_start_value(variable[name, t], init) end diff --git a/src/feedforward/feedforward_arguments.jl b/src/feedforward/feedforward_arguments.jl index abfadf8214..20fdd57767 100644 --- a/src/feedforward/feedforward_arguments.jl +++ b/src/feedforward/feedforward_arguments.jl @@ -40,7 +40,7 @@ function _add_feedforward_arguments!( contributing_devices::Vector, ff::AbstractAffectFeedforward, ) where {T <: PSY.AbstractReserve, U <: AbstractServiceFormulation} - parameter_type = get_default_parameter_type(ff, SR) + parameter_type = get_default_parameter_type(ff, U) add_parameters!(container, parameter_type, ff, model, contributing_devices) return end diff --git a/src/feedforward/feedforwards.jl b/src/feedforward/feedforwards.jl index a5f3bb4729..82f4220b25 100644 --- a/src/feedforward/feedforwards.jl +++ b/src/feedforward/feedforwards.jl @@ -26,7 +26,8 @@ function attach_feedforward!( ff_ = T(; component_type = get_component_type(ff), source = get_entry_type(get_optimization_container_key(ff)), - affected_values = [get_entry_type(get_optimization_container_key(ff))], + affected_values = affected_values = + get_entry_type.(get_affected_values(ff)), meta = model.service_name, ) end @@ -132,7 +133,7 @@ function attach_feedforward!( ff_ = T(; component_type = get_component_type(ff), source = get_entry_type(get_optimization_container_key(ff)), - affected_values = [get_entry_type(get_optimization_container_key(ff))], + affected_values = get_entry_type.(get_affected_values(ff)), meta = model.service_name, add_slacks = ff.add_slacks, ) diff --git a/src/network_models/area_balance_model.jl b/src/network_models/area_balance_model.jl index 612bb7bee1..04d6ffa3e0 100644 --- a/src/network_models/area_balance_model.jl +++ b/src/network_models/area_balance_model.jl @@ -1,7 +1,7 @@ function area_balance( container::OptimizationContainer, expression::ExpressionKey, - area_mapping::Dict{String, Array{PSY.Bus, 1}}, + area_mapping::Dict{String, Array{PSY.ACBus, 1}}, branches, ) time_steps = get_time_steps(container) diff --git a/src/network_models/hvdc_networks.jl b/src/network_models/hvdc_networks.jl new file mode 100644 index 0000000000..555c6b5858 --- /dev/null +++ b/src/network_models/hvdc_networks.jl @@ -0,0 +1,29 @@ +function add_constraints!( + container::OptimizationContainer, + ::Type{NodalBalanceActiveConstraint}, + sys::PSY.System, + model::NetworkModel{V}, +) where {V <: PM.AbstractPowerModel} + dc_buses = PSY.get_components(PSY.DCBus, sys) + if isempty(dc_buses) + return + end + + time_steps = get_time_steps(container) + dc_expr = get_expression(container, ActivePowerBalance(), PSY.DCBus) + balance_constraint = add_constraints_container!( + container, + NodalBalanceActiveConstraint(), + PSY.DCBus, + axes(dc_expr)[1], + time_steps, + ) + for d in dc_buses + dc_bus_no = PSY.get_number(d) + for t in time_steps + balance_constraint[dc_bus_no, t] = + JuMP.@constraint(get_jump_model(container), dc_expr[dc_bus_no, t] == 0) + end + end + return +end diff --git a/src/network_models/network_constructor.jl b/src/network_models/network_constructor.jl index 547ddc5af2..e2d4a5d850 100644 --- a/src/network_models/network_constructor.jl +++ b/src/network_models/network_constructor.jl @@ -42,7 +42,7 @@ function construct_network!( area_balance( container, - ExpressionKey(ActivePowerBalance, PSY.Bus), + ExpressionKey(ActivePowerBalance, PSY.ACBus), area_mapping, branches, ) @@ -69,9 +69,8 @@ function construct_network!( ) objective_function!(container, PSY.System, model) end - add_constraints!(container, CopperPlateBalanceConstraint, sys, model) - + add_constraints!(container, NodalBalanceActiveConstraint, sys, model) add_constraint_dual!(container, sys, model) return end @@ -93,8 +92,8 @@ function construct_network!( add_pm_expr_refs!(container, T, sys) add_constraints!(container, CopperPlateBalanceConstraint, sys, model) + add_constraints!(container, NodalBalanceActiveConstraint, sys, model) add_constraint_dual!(container, sys, model) - return end @@ -124,12 +123,14 @@ function construct_network!( sys, model, ) - objective_function!(container, PSY.Bus, model) + objective_function!(container, PSY.ACBus, model) end @debug "Building the $T network with $instantiate_model method" _group = LOG_GROUP_NETWORK_CONSTRUCTION powermodels_network!(container, T, sys, template, instantiate_model) + #Constraints in case the model has DC Buses + add_constraints!(container, NodalBalanceActiveConstraint, sys, model) add_pm_variable_refs!(container, T, sys) add_pm_constraint_refs!(container, T, sys) @@ -170,18 +171,13 @@ function construct_network!( sys, model, ) - add_to_expression!( - container, - ReactivePowerBalance, - SystemBalanceSlackDown, - sys, - model, - ) - objective_function!(container, PSY.Bus, model) + objective_function!(container, PSY.ACBus, model) end @debug "Building the $T network with $instantiate_model method" _group = LOG_GROUP_NETWORK_CONSTRUCTION + #Constraints in case the model has DC Buses + add_constraints!(container, NodalBalanceActiveConstraint, sys, model) powermodels_network!(container, T, sys, template, instantiate_model) add_pm_variable_refs!(container, T, sys) add_pm_constraint_refs!(container, T, sys) @@ -240,11 +236,13 @@ function construct_network!( model, T, ) - objective_function!(container, PSY.Bus, model) + objective_function!(container, PSY.ACBus, model) end @debug "Building the $T network with $instantiate_model method" _group = LOG_GROUP_NETWORK_CONSTRUCTION + #Constraints in case the model has DC Buses + add_constraints!(container, NodalBalanceActiveConstraint, sys, model) powermodels_network!(container, T, sys, template, instantiate_model) add_pm_variable_refs!(container, T, sys) add_pm_constraint_refs!(container, T, sys) @@ -302,11 +300,13 @@ function construct_network!( model, T, ) - objective_function!(container, PSY.Bus, model) + objective_function!(container, PSY.ACBus, model) end @debug "Building the $T network with $instantiate_model method" _group = LOG_GROUP_NETWORK_CONSTRUCTION + #Constraints in case the model has DC Buses + add_constraints!(container, NodalBalanceActiveConstraint, sys, model) powermodels_network!(container, T, sys, template, instantiate_model) add_pm_variable_refs!(container, T, sys) add_pm_constraint_refs!(container, T, sys) diff --git a/src/network_models/network_slack_variables.jl b/src/network_models/network_slack_variables.jl index a40a16a25d..619aeab047 100644 --- a/src/network_models/network_slack_variables.jl +++ b/src/network_models/network_slack_variables.jl @@ -1,6 +1,6 @@ #! format: off -get_variable_multiplier(::SystemBalanceSlackUp, ::Type{<: Union{PSY.Bus, PSY.System}}, _) = 1.0 -get_variable_multiplier(::SystemBalanceSlackDown, ::Type{<: Union{PSY.Bus, PSY.System}}, _) = -1.0 +get_variable_multiplier(::SystemBalanceSlackUp, ::Type{<: Union{PSY.ACBus, PSY.System}}, _) = 1.0 +get_variable_multiplier(::SystemBalanceSlackDown, ::Type{<: Union{PSY.ACBus, PSY.System}}, _) = -1.0 #! format: on function add_variables!( @@ -37,9 +37,8 @@ function add_variables!( U <: PM.AbstractActivePowerModel, } time_steps = get_time_steps(container) - bus_numbers = PSY.get_number.(get_available_components(PSY.Bus, sys)) - variable = add_variable_container!(container, T(), PSY.Bus, bus_numbers, time_steps) - + bus_numbers = PSY.get_number.(get_available_components(PSY.ACBus, sys)) + variable = add_variable_container!(container, T(), PSY.ACBus, bus_numbers, time_steps) for t in time_steps, n in bus_numbers variable[n, t] = JuMP.@variable( get_jump_model(container), @@ -60,11 +59,11 @@ function add_variables!( U <: PM.AbstractPowerModel, } time_steps = get_time_steps(container) - bus_numbers = PSY.get_number.(get_available_components(PSY.Bus, sys)) + bus_numbers = PSY.get_number.(get_available_components(PSY.ACBus, sys)) variable_active = - add_variable_container!(container, T(), PSY.Bus, "P", bus_numbers, time_steps) + add_variable_container!(container, T(), PSY.ACBus, "P", bus_numbers, time_steps) variable_reactive = - add_variable_container!(container, T(), PSY.Bus, "Q", bus_numbers, time_steps) + add_variable_container!(container, T(), PSY.ACBus, "Q", bus_numbers, time_steps) for t in time_steps, n in bus_numbers variable_active[n, t] = JuMP.@variable( @@ -101,11 +100,11 @@ end function objective_function!( container::OptimizationContainer, - ::Type{PSY.Bus}, + ::Type{PSY.ACBus}, network_model::NetworkModel{T}, ) where {T <: PM.AbstractActivePowerModel} - variable_up = get_variable(container, SystemBalanceSlackUp(), PSY.Bus) - variable_dn = get_variable(container, SystemBalanceSlackDown(), PSY.Bus) + variable_up = get_variable(container, SystemBalanceSlackUp(), PSY.ACBus) + variable_dn = get_variable(container, SystemBalanceSlackDown(), PSY.ACBus) bus_numbers = axes(variable_up)[1] @assert_op bus_numbers == axes(variable_dn)[1] for t in get_time_steps(container), n in bus_numbers @@ -119,13 +118,13 @@ end function objective_function!( container::OptimizationContainer, - ::Type{PSY.Bus}, + ::Type{PSY.ACBus}, network_model::NetworkModel{T}, ) where {T <: PM.AbstractPowerModel} - variable_p_up = get_variable(container, SystemBalanceSlackUp(), PSY.Bus, "P") - variable_p_dn = get_variable(container, SystemBalanceSlackDown(), PSY.Bus, "P") - variable_q_up = get_variable(container, SystemBalanceSlackUp(), PSY.Bus, "Q") - variable_q_dn = get_variable(container, SystemBalanceSlackDown(), PSY.Bus, "Q") + variable_p_up = get_variable(container, SystemBalanceSlackUp(), PSY.ACBus, "P") + variable_p_dn = get_variable(container, SystemBalanceSlackDown(), PSY.ACBus, "P") + variable_q_up = get_variable(container, SystemBalanceSlackUp(), PSY.ACBus, "Q") + variable_q_dn = get_variable(container, SystemBalanceSlackDown(), PSY.ACBus, "Q") bus_numbers = axes(variable_p_up)[1] @assert_op bus_numbers == axes(variable_q_dn)[1] for t in get_time_steps(container), n in bus_numbers diff --git a/src/network_models/pm_translator.jl b/src/network_models/pm_translator.jl index b311268033..627a5b7cf0 100644 --- a/src/network_models/pm_translator.jl +++ b/src/network_models/pm_translator.jl @@ -1,18 +1,18 @@ const PM_MAP_TUPLE = NamedTuple{(:from_to, :to_from), Tuple{Tuple{Int, Int, Int}, Tuple{Int, Int, Int}}} -const PM_BUSTYPES = Dict{PSY.BusTypes, Int}( - PSY.BusTypes.ISOLATED => 4, - PSY.BusTypes.PQ => 1, - PSY.BusTypes.PV => 2, - PSY.BusTypes.REF => 3, - PSY.BusTypes.SLACK => 3, +const PM_BUSTYPES = Dict{PSY.ACBusTypes, Int}( + PSY.ACBusTypes.ISOLATED => 4, + PSY.ACBusTypes.PQ => 1, + PSY.ACBusTypes.PV => 2, + PSY.ACBusTypes.REF => 3, + PSY.ACBusTypes.SLACK => 3, ) struct PMmap - bus::Dict{Int, PSY.Bus} + bus::Dict{Int, PSY.ACBus} arcs::Dict{PM_MAP_TUPLE, <:PSY.ACBranch} - arcs_dc::Dict{PM_MAP_TUPLE, <:PSY.DCBranch} + arcs_dc::Dict{PM_MAP_TUPLE, PSY.TwoTerminalHVDCLine} end function get_branch_to_pm( @@ -266,8 +266,8 @@ end function get_branch_to_pm( ix::Int, - branch::PSY.HVDCLine, - ::Type{HVDCP2PDispatch}, + branch::PSY.TwoTerminalHVDCLine, + ::Type{HVDCTwoTerminalDispatch}, ::Type{<:PM.AbstractDCPModel}, ) PM_branch = Dict{String, Any}( @@ -304,8 +304,8 @@ end function get_branch_to_pm( ix::Int, - branch::PSY.HVDCLine, - ::Type{HVDCP2PDispatch}, + branch::PSY.TwoTerminalHVDCLine, + ::Type{HVDCTwoTerminalDispatch}, ::Type{<:PM.AbstractPowerModel}, ) check_hvdc_line_limits_unidirectional(branch) @@ -343,8 +343,8 @@ end function get_branch_to_pm( ix::Int, - branch::PSY.HVDCLine, - ::Type{<:AbstractBranchFormulation}, + branch::PSY.TwoTerminalHVDCLine, + ::Type{<:AbstractTwoTerminalDCLineFormulation}, ::Type{<:PM.AbstractPowerModel}, ) PM_branch = Dict{String, Any}( @@ -385,7 +385,39 @@ function get_branches_to_pm( ::Type{T}, branch_template::BranchModelContainer, start_idx = 0, -) where {T <: PSY.Branch, S <: PM.AbstractPowerModel} +) where {T <: PSY.ACBranch, S <: PM.AbstractPowerModel} + PM_branches = Dict{String, Any}() + PMmap_br = Dict{PM_MAP_TUPLE, T}() + + for (d, device_model) in branch_template + comp_type = get_component_type(device_model) + if comp_type <: TwoTerminalHVDCTypes + continue + end + !(comp_type <: T) && continue + start_idx += length(PM_branches) + filter_func = get_attribute(device_model, "filter_function") + for (i, branch) in enumerate(get_available_components(comp_type, sys, filter_func)) + ix = i + start_idx + PM_branches["$(ix)"] = + get_branch_to_pm(ix, branch, get_formulation(device_model), S) + if PM_branches["$(ix)"]["br_status"] == true + f = PM_branches["$(ix)"]["f_bus"] + t = PM_branches["$(ix)"]["t_bus"] + PMmap_br[(from_to = (ix, f, t), to_from = (ix, t, f))] = branch + end + end + end + return PM_branches, PMmap_br +end + +function get_branches_to_pm( + sys::PSY.System, + ::Type{S}, + ::Type{T}, + branch_template::BranchModelContainer, + start_idx = 0, +) where {T <: TwoTerminalHVDCTypes, S <: PM.AbstractPowerModel} PM_branches = Dict{String, Any}() PMmap_br = Dict{PM_MAP_TUPLE, T}() @@ -414,18 +446,18 @@ function get_branches_to_pm( ::Type{T}, branch_template::BranchModelContainer, start_idx = 0, -) where {T <: PSY.DCBranch} +) where {T <: TwoTerminalHVDCTypes} PM_branches = Dict{String, Any}() PMmap_br = Dict{PM_MAP_TUPLE, T}() return PM_branches, PMmap_br end -function get_buses_to_pm(buses::IS.FlattenIteratorWrapper{PSY.Bus}) +function get_buses_to_pm(buses::IS.FlattenIteratorWrapper{PSY.ACBus}) PM_buses = Dict{String, Any}() - PMmap_buses = Dict{Int, PSY.Bus}() + PMmap_buses = Dict{Int, PSY.ACBus}() for bus in buses - if PSY.get_bustype(bus) == PSY.BusTypes.ISOLATED + if PSY.get_bustype(bus) == PSY.ACBusTypes.ISOLATED continue end number = PSY.get_number(bus) @@ -457,14 +489,14 @@ function pass_to_pm(sys::PSY.System, template::ProblemTemplate, time_periods::In PSY.ACBranch, template.branches, ) - dc_lines, PMmap_dc = get_branches_to_pm( + two_terminal_dc_lines, PMmap_dc = get_branches_to_pm( sys, get_network_formulation(template), - PSY.DCBranch, + TwoTerminalHVDCTypes, template.branches, length(ac_lines), ) - buses = get_available_components(PSY.Bus, sys) + buses = get_available_components(PSY.ACBus, sys) pm_buses, PMmap_buses = get_buses_to_pm(buses) PM_translation = Dict{String, Any}( "bus" => pm_buses, @@ -472,7 +504,7 @@ function pass_to_pm(sys::PSY.System, template::ProblemTemplate, time_periods::In "baseMVA" => PSY.get_base_power(sys), "per_unit" => true, "storage" => Dict{String, Any}(), - "dcline" => dc_lines, + "dcline" => two_terminal_dc_lines, "gen" => Dict{String, Any}(), "switch" => Dict{String, Any}(), "shunt" => Dict{String, Any}(), diff --git a/src/network_models/powermodels_interface.jl b/src/network_models/powermodels_interface.jl index 263844772e..009c4369d2 100644 --- a/src/network_models/powermodels_interface.jl +++ b/src/network_models/powermodels_interface.jl @@ -291,13 +291,16 @@ function powermodels_network!( ) where {S <: PM.AbstractPowerModel} time_steps = get_time_steps(container) pm_data, PM_map = pass_to_pm(sys, template, time_steps[end]) - buses = get_available_components(PSY.Bus, sys) + buses = get_available_components(PSY.ACBus, sys) for t in time_steps, bus in buses pm_data["nw"]["$(t)"]["bus"]["$(bus.number)"]["inj_p"] = - container.expressions[ExpressionKey(ActivePowerBalance, PSY.Bus)][bus.number, t] + container.expressions[ExpressionKey(ActivePowerBalance, PSY.ACBus)][ + bus.number, + t, + ] pm_data["nw"]["$(t)"]["bus"]["$(bus.number)"]["inj_q"] = - container.expressions[ExpressionKey(ReactivePowerBalance, PSY.Bus)][ + container.expressions[ExpressionKey(ReactivePowerBalance, PSY.ACBus)][ bus.number, t, ] @@ -319,11 +322,11 @@ function powermodels_network!( ) where {S <: PM.AbstractActivePowerModel} time_steps = get_time_steps(container) pm_data, PM_map = pass_to_pm(sys, template, time_steps[end]) - buses = get_available_components(PSY.Bus, sys) + buses = get_available_components(PSY.ACBus, sys) for t in time_steps, bus in buses pm_data["nw"]["$(t)"]["bus"]["$(PSY.get_number(bus))"]["inj_p"] = - container.expressions[ExpressionKey(ActivePowerBalance, PSY.Bus)][ + container.expressions[ExpressionKey(ActivePowerBalance, PSY.ACBus)][ PSY.get_number(bus), t, ] @@ -331,7 +334,11 @@ function powermodels_network!( end container.pm = - instantiate_model(pm_data, system_formulation; jump_model = container.JuMPmodel) + instantiate_model( + pm_data, + system_formulation; + jump_model = get_jump_model(container), + ) container.pm.ext[:PMmap] = PM_map return @@ -342,10 +349,10 @@ end function PMvarmap(::Type{S}) where {S <: PM.AbstractDCPModel} pm_variable_map = Dict{Type, Dict{Symbol, Union{VariableType, NamedTuple}}}() - pm_variable_map[PSY.Bus] = Dict(:va => VoltageAngle()) + pm_variable_map[PSY.ACBus] = Dict(:va => VoltageAngle()) pm_variable_map[PSY.ACBranch] = Dict(:p => (from_to = FlowActivePowerVariable(), to_from = nothing)) - pm_variable_map[PSY.DCBranch] = + pm_variable_map[TwoTerminalHVDCTypes] = Dict(:p_dc => (from_to = FlowActivePowerVariable(), to_from = nothing)) return pm_variable_map @@ -354,9 +361,9 @@ end function PMvarmap(::Type{S}) where {S <: PM.AbstractActivePowerModel} pm_variable_map = Dict{Type, Dict{Symbol, Union{VariableType, NamedTuple}}}() - pm_variable_map[PSY.Bus] = Dict(:va => VoltageAngle()) + pm_variable_map[PSY.ACBus] = Dict(:va => VoltageAngle()) pm_variable_map[PSY.ACBranch] = Dict(:p => FlowActivePowerFromToVariable()) - pm_variable_map[PSY.DCBranch] = Dict( + pm_variable_map[TwoTerminalHVDCTypes] = Dict( :p_dc => ( from_to = FlowActivePowerFromToVariable(), to_from = FlowActivePowerToFromVariable(), @@ -369,9 +376,9 @@ end function PMvarmap(::Type{PTDFPowerModel}) pm_variable_map = Dict{Type, Dict{Symbol, Union{String, NamedTuple}}}() - pm_variable_map[PSY.Bus] = Dict() + pm_variable_map[PSY.ACBus] = Dict() pm_variable_map[PSY.ACBranch] = Dict() - pm_variable_map[PSY.DCBranch] = Dict() + pm_variable_map[TwoTerminalHVDCTypes] = Dict() return pm_variable_map end @@ -379,7 +386,7 @@ end function PMvarmap(::Type{S}) where {S <: PM.AbstractPowerModel} pm_variable_map = Dict{Type, Dict{Symbol, Union{VariableType, NamedTuple}}}() - pm_variable_map[PSY.Bus] = Dict(:va => VoltageAngle(), :vm => VoltageMagnitude()) + pm_variable_map[PSY.ACBus] = Dict(:va => VoltageAngle(), :vm => VoltageMagnitude()) pm_variable_map[PSY.ACBranch] = Dict( :p => ( from_to = FlowActivePowerFromToVariable(), @@ -390,7 +397,7 @@ function PMvarmap(::Type{S}) where {S <: PM.AbstractPowerModel} to_from = FlowReactivePowerToFromVariable(), ), ) - pm_variable_map[PSY.DCBranch] = Dict( + pm_variable_map[TwoTerminalHVDCTypes] = Dict( :p_dc => (from_to = FlowActivePowerVariable(), to_from = nothing), :q_dc => ( from_to = FlowReactivePowerFromToVariable(), @@ -404,14 +411,14 @@ end function PMconmap(::Type{S}) where {S <: PM.AbstractActivePowerModel} pm_constraint_map = Dict{Type, Dict{Symbol, <:ConstraintType}}() - pm_constraint_map[PSY.Bus] = Dict(:power_balance_p => NodalBalanceActiveConstraint()) + pm_constraint_map[PSY.ACBus] = Dict(:power_balance_p => NodalBalanceActiveConstraint()) return pm_constraint_map end function PMconmap(::Type{S}) where {S <: PM.AbstractPowerModel} pm_constraint_map = Dict{Type, Dict{Symbol, ConstraintType}}() - pm_constraint_map[PSY.Bus] = Dict( + pm_constraint_map[PSY.ACBus] = Dict( :power_balance_p => NodalBalanceActiveConstraint(), :power_balance_q => NodalBalanceReactiveConstraint(), ) @@ -463,10 +470,10 @@ function add_pm_variable_refs!( pm_variable_map = PMvarmap(system_formulation) bus_names = [PSY.get_name(b) for b in values(bus_dict)] - for (pm_v, ps_v) in pm_variable_map[PSY.Bus] + for (pm_v, ps_v) in pm_variable_map[PSY.ACBus] if pm_v in pm_variable_types var_container = - add_variable_container!(container, ps_v, PSY.Bus, bus_names, time_steps) + add_variable_container!(container, ps_v, PSY.ACBus, bus_names, time_steps) for t in time_steps, (pm_bus, bus) in bus_dict name = PSY.get_name(bus) var_container[name, t] = PM.var(container.pm, t, pm_v)[pm_bus] # pm_vars[pm_v][pm_bus] @@ -485,7 +492,7 @@ function add_pm_variable_refs!( ) add_pm_variable_refs!( container, - PSY.DCBranch, + TwoTerminalHVDCTypes, DCbranch_types, DCbranch_dict, pm_variable_map, @@ -526,6 +533,7 @@ function add_pm_variable_refs!( end end end + return end function add_pm_constraint_refs!( @@ -540,12 +548,12 @@ function add_pm_constraint_refs!( [k for k in keys(PM.con(container.pm, 1)) if !isempty(PM.con(container.pm, 1, k))] pm_constraint_map = PMconmap(system_formulation) - for (pm_v, ps_v) in pm_constraint_map[PSY.Bus] + for (pm_v, ps_v) in pm_constraint_map[PSY.ACBus] if pm_v in pm_constraint_names cons_container = add_constraints_container!( container, ps_v, - PSY.Bus, + PSY.ACBus, [PSY.get_name(b) for b in values(bus_dict)], time_steps, ) diff --git a/src/operation/operation_model_interface.jl b/src/operation/operation_model_interface.jl index 75ccd2bd56..e3511a754c 100644 --- a/src/operation/operation_model_interface.jl +++ b/src/operation/operation_model_interface.jl @@ -224,7 +224,7 @@ function validate_template(model::OperationModel) modeled_types = get_component_types(template) system = get_system(model) system_component_types = PSY.get_existing_component_types(system) - exclusions = [PSY.Arc, PSY.Area, PSY.Bus, PSY.LoadZone] + exclusions = [PSY.Arc, PSY.Area, PSY.ACBus, PSY.LoadZone] for m in setdiff(modeled_types, system_component_types) @warn "The system data doesn't include components of type $(m), consider changing the models in the template" _group = LOG_GROUP_MODELS_VALIDATION diff --git a/src/operation/operation_problem_templates.jl b/src/operation/operation_problem_templates.jl index 800c0cdb1d..1eb7e928f4 100644 --- a/src/operation/operation_problem_templates.jl +++ b/src/operation/operation_problem_templates.jl @@ -13,7 +13,7 @@ function _default_devices_uc() DeviceModel(PSY.Line, StaticBranch), DeviceModel(PSY.Transformer2W, StaticBranch), DeviceModel(PSY.TapTransformer, StaticBranch), - DeviceModel(PSY.HVDCLine, HVDCP2PDispatch), + DeviceModel(PSY.TwoTerminalHVDCLine, HVDCTwoTerminalDispatch), ] end diff --git a/src/parameters/update_parameters.jl b/src/parameters/update_parameters.jl index a9c738087b..671c1b59d7 100644 --- a/src/parameters/update_parameters.jl +++ b/src/parameters/update_parameters.jl @@ -594,7 +594,9 @@ function update_parameter_values!( # if the keys have strings in the meta fields parameter_array = get_parameter_array(optimization_container, key) parameter_attributes = get_parameter_attributes(optimization_container, key) - _update_parameter_values!(parameter_array, parameter_attributes, T, model, input) + service = PSY.get_component(T, get_system(model), key.meta) + @assert service !== nothing + _update_parameter_values!(parameter_array, parameter_attributes, service, model, input) _fix_parameter_value!(optimization_container, parameter_array, parameter_attributes) IS.@record :execution ParameterUpdateEvent( FixValueParameter, diff --git a/src/services_models/reserves.jl b/src/services_models/reserves.jl index 8f84022c0d..cee5ef7f5b 100644 --- a/src/services_models/reserves.jl +++ b/src/services_models/reserves.jl @@ -4,15 +4,15 @@ get_variable_multiplier(_, ::Type{<:PSY.Reserve}, ::AbstractReservesFormulation) = NaN ############################### ActivePowerReserveVariable, Reserve ######################################### get_variable_binary(::ActivePowerReserveVariable, ::Type{<:PSY.Reserve}, ::AbstractReservesFormulation) = false -function get_variable_upper_bound(::ActivePowerReserveVariable, r::PSY.Reserve, d::PSY.Device, _) +function get_variable_upper_bound(::ActivePowerReserveVariable, r::PSY.Reserve, d::PSY.Device, ::AbstractReservesFormulation) return PSY.get_max_output_fraction(r) * PSY.get_max_active_power(d) end -get_variable_upper_bound(::ActivePowerReserveVariable, r::PSY.ReserveDemandCurve, d::PSY.Device, _) = PSY.get_max_active_power(d) +get_variable_upper_bound(::ActivePowerReserveVariable, r::PSY.ReserveDemandCurve, d::PSY.Device, ::AbstractReservesFormulation) = PSY.get_max_active_power(d) get_variable_lower_bound(::ActivePowerReserveVariable, ::PSY.Reserve, ::PSY.Device, _) = 0.0 ############################### ActivePowerReserveVariable, ReserveNonSpinning ######################################### get_variable_binary(::ActivePowerReserveVariable, ::Type{<:PSY.ReserveNonSpinning}, ::AbstractReservesFormulation) = false -function get_variable_upper_bound(::ActivePowerReserveVariable, r::PSY.ReserveNonSpinning, d::PSY.Device, _) +function get_variable_upper_bound(::ActivePowerReserveVariable, r::PSY.ReserveNonSpinning, d::PSY.Device, ::AbstractReservesFormulation) return PSY.get_max_output_fraction(r) * PSY.get_max_active_power(d) end get_variable_lower_bound(::ActivePowerReserveVariable, ::PSY.ReserveNonSpinning, ::PSY.Device, _) = 0.0 diff --git a/src/utils/powersystems_utils.jl b/src/utils/powersystems_utils.jl index 2af80e6319..b50f676fbe 100644 --- a/src/utils/powersystems_utils.jl +++ b/src/utils/powersystems_utils.jl @@ -15,13 +15,13 @@ function get_available_components( end function get_available_components( - ::Type{PSY.Bus}, + ::Type{PSY.ACBus}, sys::PSY.System, ::Nothing = nothing, ) return PSY.get_components( - x -> PSY.get_bustype(x) != PSY.BusTypes.ISOLATED, - PSY.Bus, + x -> PSY.get_bustype(x) != PSY.ACBusTypes.ISOLATED, + PSY.ACBus, sys, ) end @@ -41,7 +41,9 @@ end make_system_filename(sys::PSY.System) = "system-$(IS.get_uuid(sys)).json" make_system_filename(sys_uuid::Union{Base.UUID, AbstractString}) = "system-$(sys_uuid).json" -function check_hvdc_line_limits_consistency(d::PSY.HVDCLine) +function check_hvdc_line_limits_consistency( + d::Union{PSY.TwoTerminalHVDCLine, PSY.TModelHVDCLine}, +) from_min = PSY.get_active_power_limits_from(d).min to_min = PSY.get_active_power_limits_to(d).min from_max = PSY.get_active_power_limits_from(d).max @@ -63,7 +65,7 @@ function check_hvdc_line_limits_consistency(d::PSY.HVDCLine) return end -function check_hvdc_line_limits_unidirectional(d::PSY.HVDCLine) +function check_hvdc_line_limits_unidirectional(d::PSY.TwoTerminalHVDCLine) from_min = PSY.get_active_power_limits_from(d).min to_min = PSY.get_active_power_limits_to(d).min from_max = PSY.get_active_power_limits_from(d).max diff --git a/test/Project.toml b/test/Project.toml index 2b72548673..5e338be182 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -32,5 +32,5 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [compat] HiGHS = "=1.1.2" Ipopt = "=1.4.0" -PowerSystemCaseBuilder = "~1.0.2" +PowerSystemCaseBuilder = "^1.2.0" julia = "^1.6" diff --git a/test/test_device_branch_constructors.jl b/test/test_device_branch_constructors.jl index 3a6f7eebf6..af47085b41 100644 --- a/test/test_device_branch_constructors.jl +++ b/test/test_device_branch_constructors.jl @@ -85,7 +85,7 @@ end end end -@testset "DC Power Flow Models for HVDCLine with with Line Flow Constraints, TapTransformer & Transformer2W Unbounded" begin +@testset "DC Power Flow Models for TwoTerminalHVDCLine with with Line Flow Constraints, TapTransformer & Transformer2W Unbounded" begin ratelimit_constraint_keys = [ PSI.ConstraintKey(RateLimitConstraint, Transformer2W, "ub"), PSI.ConstraintKey(RateLimitConstraint, Transformer2W, "lb"), @@ -94,7 +94,7 @@ end ] system = PSB.build_system(PSITestSystems, "c_sys14_dc") - hvdc_line = PSY.get_component(HVDCLine, system, "DCLine3") + hvdc_line = PSY.get_component(TwoTerminalHVDCLine, system, "DCLine3") limits_from = PSY.get_active_power_limits_from(hvdc_line) limits_to = PSY.get_active_power_limits_to(hvdc_line) limits_min = min(limits_from.min, limits_to.min) @@ -110,7 +110,7 @@ end template = get_template_dispatch_with_network( NetworkModel(model; PTDF_matrix = PTDF(system)), ) - set_device_model!(template, HVDCLine, HVDCP2PLossless) + set_device_model!(template, TwoTerminalHVDCLine, HVDCTwoTerminalLossless) model_m = DecisionModel(template, system; optimizer = ipopt_optimizer) @test build!(model_m; output_dir = mktempdir(; cleanup = true)) == PSI.BuildStatus.BUILT @@ -125,7 +125,7 @@ end @test check_flow_variable_values( model_m, FlowActivePowerVariable, - HVDCLine, + TwoTerminalHVDCLine, "DCLine3", limits_min, limits_max, @@ -149,9 +149,9 @@ end end end -@testset "DC Power Flow Models for Unbounded HVDCLine, and StaticBranchBounds for TapTransformer & Transformer2W" begin +@testset "DC Power Flow Models for Unbounded TwoTerminalHVDCLine , and StaticBranchBounds for TapTransformer & Transformer2W" begin system = PSB.build_system(PSITestSystems, "c_sys14_dc") - hvdc_line = PSY.get_component(HVDCLine, system, "DCLine3") + hvdc_line = PSY.get_component(TwoTerminalHVDCLine, system, "DCLine3") limits_from = PSY.get_active_power_limits_from(hvdc_line) limits_to = PSY.get_active_power_limits_to(hvdc_line) limits_min = min(limits_from.min, limits_to.min) @@ -167,14 +167,21 @@ end template = get_template_dispatch_with_network( NetworkModel(model; PTDF_matrix = PTDF(system)), ) - set_device_model!(template, DeviceModel(HVDCLine, HVDCP2PUnbounded)) + set_device_model!( + template, + DeviceModel(TwoTerminalHVDCLine, HVDCTwoTerminalUnbounded), + ) set_device_model!(template, DeviceModel(TapTransformer, StaticBranchBounds)) set_device_model!(template, DeviceModel(Transformer2W, StaticBranchBounds)) model_m = DecisionModel(template, system; optimizer = ipopt_optimizer) @test build!(model_m; output_dir = mktempdir(; cleanup = true)) == PSI.BuildStatus.BUILT - @test check_variable_unbounded(model_m, FlowActivePowerVariable, HVDCLine) + @test check_variable_unbounded( + model_m, + FlowActivePowerVariable, + TwoTerminalHVDCLine, + ) @test check_variable_bounded(model_m, FlowActivePowerVariable, TapTransformer) @test check_variable_bounded(model_m, FlowActivePowerVariable, TapTransformer) @@ -183,7 +190,7 @@ end @test check_flow_variable_values( model_m, FlowActivePowerVariable, - HVDCLine, + TwoTerminalHVDCLine, "DCLine3", limits_min, limits_max, @@ -207,14 +214,14 @@ end end end -@testset "HVDCP2PLossless values check between network models" begin +@testset "HVDCTwoTerminalLossless values check between network models" begin # Test to compare lossless models with lossless formulation sys_5 = build_system(PSITestSystems, "c_sys5_uc") line = get_component(Line, sys_5, "1") remove_component!(sys_5, line) - hvdc = HVDCLine(; + hvdc = TwoTerminalHVDCLine(; name = get_name(line), available = true, active_power_flow = 0.0, @@ -237,7 +244,10 @@ end set_device_model!(template_uc, RenewableDispatch, FixedOutput) set_device_model!(template_uc, PowerLoad, StaticPowerLoad) set_device_model!(template_uc, DeviceModel(Line, StaticBranch)) - set_device_model!(template_uc, DeviceModel(HVDCLine, HVDCP2PLossless)) + set_device_model!( + template_uc, + DeviceModel(TwoTerminalHVDCLine, HVDCTwoTerminalLossless), + ) model = DecisionModel( template_uc, @@ -252,7 +262,9 @@ end ptdf_vars = get_variable_values(ProblemResults(model)) ptdf_values = - ptdf_vars[PowerSimulations.VariableKey{FlowActivePowerVariable, HVDCLine}("")] + ptdf_vars[PowerSimulations.VariableKey{FlowActivePowerVariable, TwoTerminalHVDCLine}( + "", + )] ptdf_objective = model.internal.container.optimizer_stats.objective_value set_network_model!(template_uc, NetworkModel(DCPPowerModel)) @@ -268,7 +280,9 @@ end solve!(model; output_dir = mktempdir()) dcp_vars = get_variable_values(ProblemResults(model)) dcp_values = - dcp_vars[PowerSimulations.VariableKey{FlowActivePowerVariable, HVDCLine}("")] + dcp_vars[PowerSimulations.VariableKey{FlowActivePowerVariable, TwoTerminalHVDCLine}( + "", + )] dcp_objective = model.internal.container.optimizer_stats.objective_value @test isapprox(dcp_objective, ptdf_objective; atol = 0.1) @@ -282,7 +296,7 @@ end line = get_component(Line, sys_5, "1") remove_component!(sys_5, line) - hvdc = HVDCLine(; + hvdc = TwoTerminalHVDCLine(; name = get_name(line), available = true, active_power_flow = 0.0, @@ -307,7 +321,10 @@ end set_device_model!(template_uc, RenewableDispatch, FixedOutput) set_device_model!(template_uc, PowerLoad, StaticPowerLoad) set_device_model!(template_uc, DeviceModel(Line, StaticBranchUnbounded)) - set_device_model!(template_uc, DeviceModel(HVDCLine, HVDCP2PLossless)) + set_device_model!( + template_uc, + DeviceModel(TwoTerminalHVDCLine, HVDCTwoTerminalLossless), + ) model_ref = DecisionModel( template_uc, @@ -321,10 +338,12 @@ end ref_vars = get_variable_values(ProblemResults(model_ref)) ref_values = ref_vars[PowerSimulations.VariableKey{FlowActivePowerVariable, Line}("")] - hvdc_ref_values = - ref_vars[PowerSimulations.VariableKey{FlowActivePowerVariable, HVDCLine}( - "", - )] + hvdc_ref_values = ref_vars[PowerSimulations.VariableKey{ + FlowActivePowerVariable, + TwoTerminalHVDCLine, + }( + "", + )] ref_objective = model_ref.internal.container.optimizer_stats.objective_value ref_total_gen = sum( sum.( @@ -338,7 +357,10 @@ end ), ), ) - set_device_model!(template_uc, DeviceModel(HVDCLine, HVDCP2PDispatch)) + set_device_model!( + template_uc, + DeviceModel(TwoTerminalHVDCLine, HVDCTwoTerminalDispatch), + ) model = DecisionModel( template_uc, @@ -356,13 +378,13 @@ end )] hvdc_ft_no_loss_values = no_loss_vars[PowerSimulations.VariableKey{ FlowActivePowerFromToVariable, - HVDCLine, + TwoTerminalHVDCLine, }( "", )] hvdc_tf_no_loss_values = no_loss_vars[PowerSimulations.VariableKey{ FlowActivePowerToFromVariable, - HVDCLine, + TwoTerminalHVDCLine, }( "", )] @@ -410,13 +432,13 @@ end dispatch_vars = get_variable_values(ProblemResults(model_wl)) dispatch_values_ft = dispatch_vars[PowerSimulations.VariableKey{ FlowActivePowerFromToVariable, - HVDCLine, + TwoTerminalHVDCLine, }( "", )] dispatch_values_tf = dispatch_vars[PowerSimulations.VariableKey{ FlowActivePowerToFromVariable, - HVDCLine, + TwoTerminalHVDCLine, }( "", )] @@ -445,7 +467,7 @@ end end end -@testset "DC Power Flow Models for HVDCLine Dispatch and TapTransformer & Transformer2W Unbounded" begin +@testset "DC Power Flow Models for TwoTerminalHVDCLine Dispatch and TapTransformer & Transformer2W Unbounded" begin ratelimit_constraint_keys = [ PSI.ConstraintKey(RateLimitConstraint, Transformer2W, "ub"), PSI.ConstraintKey(RateLimitConstraint, Line, "ub"), @@ -453,13 +475,13 @@ end PSI.ConstraintKey(RateLimitConstraint, TapTransformer, "ub"), PSI.ConstraintKey(RateLimitConstraint, Transformer2W, "lb"), PSI.ConstraintKey(RateLimitConstraint, TapTransformer, "lb"), - PSI.ConstraintKey(FlowRateConstraint, HVDCLine, "ub"), - PSI.ConstraintKey(FlowRateConstraint, HVDCLine, "lb"), + PSI.ConstraintKey(FlowRateConstraint, TwoTerminalHVDCLine, "ub"), + PSI.ConstraintKey(FlowRateConstraint, TwoTerminalHVDCLine, "lb"), ] system = PSB.build_system(PSITestSystems, "c_sys14_dc") - hvdc_line = PSY.get_component(HVDCLine, system, "DCLine3") + hvdc_line = PSY.get_component(TwoTerminalHVDCLine, system, "DCLine3") limits_from = PSY.get_active_power_limits_from(hvdc_line) limits_to = PSY.get_active_power_limits_to(hvdc_line) limits_min = min(limits_from.min, limits_to.min) @@ -474,7 +496,7 @@ end template = get_template_dispatch_with_network( NetworkModel(StandardPTDFModel; PTDF_matrix = PTDF(system)), ) - set_device_model!(template, DeviceModel(HVDCLine, HVDCP2PLossless)) + set_device_model!(template, DeviceModel(TwoTerminalHVDCLine, HVDCTwoTerminalLossless)) model_m = DecisionModel(template, system; optimizer = HiGHS_optimizer) @test build!(model_m; output_dir = mktempdir(; cleanup = true)) == PSI.BuildStatus.BUILT @@ -489,7 +511,7 @@ end @test check_flow_variable_values( model_m, FlowActivePowerVariable, - HVDCLine, + TwoTerminalHVDCLine, "DCLine3", limits_max, ) @@ -565,19 +587,19 @@ end ) end -@testset "AC Power Flow Models for HVDCLine Flow Constraints and TapTransformer & Transformer2W Unbounded" begin +@testset "AC Power Flow Models for TwoTerminalHVDCLine Flow Constraints and TapTransformer & Transformer2W Unbounded" begin ratelimit_constraint_keys = [ PSI.ConstraintKey(RateLimitConstraintFromTo, Transformer2W), PSI.ConstraintKey(RateLimitConstraintToFrom, Transformer2W), PSI.ConstraintKey(RateLimitConstraintFromTo, TapTransformer), PSI.ConstraintKey(RateLimitConstraintToFrom, TapTransformer), - PSI.ConstraintKey(FlowRateConstraint, HVDCLine, "ub"), - PSI.ConstraintKey(FlowRateConstraint, HVDCLine, "lb"), + PSI.ConstraintKey(FlowRateConstraint, TwoTerminalHVDCLine, "ub"), + PSI.ConstraintKey(FlowRateConstraint, TwoTerminalHVDCLine, "lb"), ] system = PSB.build_system(PSITestSystems, "c_sys14_dc") - hvdc_line = PSY.get_component(HVDCLine, system, "DCLine3") + hvdc_line = PSY.get_component(TwoTerminalHVDCLine, system, "DCLine3") limits_from = PSY.get_active_power_limits_from(hvdc_line) limits_to = PSY.get_active_power_limits_to(hvdc_line) limits_min = min(limits_from.min, limits_to.min) @@ -590,7 +612,7 @@ end rate_limit2w = PSY.get_rate(tap_transformer) template = get_template_dispatch_with_network(ACPPowerModel) - set_device_model!(template, DeviceModel(HVDCLine, HVDCP2PLossless)) + set_device_model!(template, DeviceModel(TwoTerminalHVDCLine, HVDCTwoTerminalLossless)) model_m = DecisionModel(template, system; optimizer = ipopt_optimizer) @test build!(model_m; output_dir = mktempdir(; cleanup = true)) == PSI.BuildStatus.BUILT @@ -607,7 +629,7 @@ end model_m, FlowActivePowerVariable, FlowReactivePowerToFromVariable, - HVDCLine, + TwoTerminalHVDCLine, "DCLine3", limits_max, ) diff --git a/test/test_device_hvdc.jl b/test/test_device_hvdc.jl new file mode 100644 index 0000000000..42ce383876 --- /dev/null +++ b/test/test_device_hvdc.jl @@ -0,0 +1,38 @@ +@testset "HVDC System Tests" begin + sys_5 = build_system(PSISystems, "sys10_pjm_ac_dc") + template_uc = ProblemTemplate(NetworkModel( + DCPPowerModel, + #use_slacks=true, + #PTDF_matrix=PTDF(sys_5), + #duals=[CopperPlateBalanceConstraint], + )) + + set_device_model!(template_uc, ThermalStandard, ThermalCompactUnitCommitment) + set_device_model!(template_uc, RenewableDispatch, RenewableFullDispatch) + set_device_model!(template_uc, PowerLoad, StaticPowerLoad) + set_device_model!(template_uc, DeviceModel(Line, StaticBranch)) + set_device_model!(template_uc, DeviceModel(InterconnectingConverter, LossLessConverter)) + set_device_model!(template_uc, DeviceModel(TModelHVDCLine, LossLessLine)) + model = DecisionModel(template_uc, sys_5; name = "UC", optimizer = HiGHS_optimizer) + @test build!(model; output_dir = mktempdir()) == PSI.BuildStatus.BUILT + moi_tests(model, 1656, 0, 1536, 816, 888, true) + @test solve!(model) == RunStatus.SUCCESSFUL + + template_uc = ProblemTemplate(NetworkModel( + StandardPTDFModel; + #use_slacks=true, + PTDF_matrix = PTDF(sys_5), + #duals=[CopperPlateBalanceConstraint], + )) + + set_device_model!(template_uc, ThermalStandard, ThermalCompactUnitCommitment) + set_device_model!(template_uc, RenewableDispatch, RenewableFullDispatch) + set_device_model!(template_uc, PowerLoad, StaticPowerLoad) + set_device_model!(template_uc, DeviceModel(Line, StaticBranch)) + set_device_model!(template_uc, DeviceModel(InterconnectingConverter, LossLessConverter)) + set_device_model!(template_uc, DeviceModel(TModelHVDCLine, LossLessLine)) + model = DecisionModel(template_uc, sys_5; name = "UC", optimizer = HiGHS_optimizer) + @test build!(model; output_dir = mktempdir()) == PSI.BuildStatus.BUILT + moi_tests(model, 1416, 0, 1248, 528, 672, true) + @test solve!(model) == RunStatus.SUCCESSFUL +end diff --git a/test/test_model_decision.jl b/test/test_model_decision.jl index 3af76fc801..4137c9fe23 100644 --- a/test/test_model_decision.jl +++ b/test/test_model_decision.jl @@ -181,7 +181,7 @@ end if network == StandardPTDFModel push!(LMPs, abs.(psi_ptdf_lmps(res, ptdf))) else - duals = read_dual(res, NodalBalanceActiveConstraint, Bus) + duals = read_dual(res, NodalBalanceActiveConstraint, ACBus) duals = abs.(duals[:, propertynames(duals) .!== :DateTime]) push!(LMPs, duals[!, sort(propertynames(duals))]) end @@ -622,7 +622,7 @@ end @testset "Test for isolated buses" begin c_sys5 = PSB.build_system(PSITestSystems, "c_sys5") add_component!(c_sys5, - Bus( + ACBus( 10, "node_none", "ISOLATED", diff --git a/test/test_network_constructors.jl b/test/test_network_constructors.jl index 7e362df29c..4de655700b 100644 --- a/test/test_network_constructors.jl +++ b/test/test_network_constructors.jl @@ -262,7 +262,7 @@ end constraint_keys = [ PSI.ConstraintKey(PSI.RateLimitConstraint, PSY.Line, "ub"), PSI.ConstraintKey(PSI.RateLimitConstraint, PSY.Line, "lb"), - PSI.ConstraintKey(PSI.NodalBalanceActiveConstraint, PSY.Bus), + PSI.ConstraintKey(PSI.NodalBalanceActiveConstraint, PSY.ACBus), ] test_results = IdDict{System, Vector{Int}}( c_sys5 => [384, 0, 408, 408, 288], @@ -309,8 +309,8 @@ end constraint_keys = [ PSI.ConstraintKey(RateLimitConstraintFromTo, PSY.Line), PSI.ConstraintKey(RateLimitConstraintToFrom, PSY.Line), - PSI.ConstraintKey(PSI.NodalBalanceActiveConstraint, PSY.Bus), - PSI.ConstraintKey(PSI.NodalBalanceReactiveConstraint, PSY.Bus), + PSI.ConstraintKey(PSI.NodalBalanceActiveConstraint, PSY.ACBus), + PSI.ConstraintKey(PSI.NodalBalanceReactiveConstraint, PSY.ACBus), ] test_results = IdDict{System, Vector{Int}}( c_sys5 => [1056, 0, 384, 384, 264], @@ -353,7 +353,7 @@ end c_sys14_dc = PSB.build_system(PSITestSystems, "c_sys14_dc") systems = [c_sys5, c_sys14, c_sys14_dc] objfuncs = [GAEVF, GQEVF, GQEVF] - constraint_keys = [PSI.ConstraintKey(PSI.NodalBalanceActiveConstraint, PSY.Bus)] + constraint_keys = [PSI.ConstraintKey(PSI.NodalBalanceActiveConstraint, PSY.ACBus)] test_results = Dict{System, Vector{Int}}( c_sys5 => [264, 0, 264, 264, 120], c_sys14 => [600, 0, 600, 600, 336], @@ -400,8 +400,8 @@ end systems = [c_sys5, c_sys14, c_sys14_dc] # TODO: add model specific constraints to this list. Voltages, etc. constraint_keys = [ - PSI.ConstraintKey(PSI.NodalBalanceActiveConstraint, PSY.Bus), - PSI.ConstraintKey(PSI.NodalBalanceReactiveConstraint, PSY.Bus), + PSI.ConstraintKey(PSI.NodalBalanceActiveConstraint, PSY.ACBus), + PSI.ConstraintKey(PSI.NodalBalanceReactiveConstraint, PSY.ACBus), ] ACR_test_results = Dict{System, Vector{Int}}( c_sys5 => [1056, 0, 240, 240, 264], @@ -441,7 +441,7 @@ end c_sys14_dc = PSB.build_system(PSITestSystems, "c_sys14_dc") systems = [c_sys5, c_sys14, c_sys14_dc] # TODO: add model specific constraints to this list. Bi-directional flows etc - constraint_keys = [PSI.ConstraintKey(PSI.NodalBalanceActiveConstraint, PSY.Bus)] + constraint_keys = [PSI.ConstraintKey(PSI.NodalBalanceActiveConstraint, PSY.ACBus)] test_obj_values = IdDict{System, Float64}( c_sys5 => 340000.0, c_sys14 => 142000.0, @@ -519,7 +519,7 @@ end psi_checksolve_test(ps_model, [MOI.OPTIMAL], 480288, 100) results = ProblemResults(ps_model) - hvdc_flow = read_variable(results, "FlowActivePowerVariable__HVDCLine") + hvdc_flow = read_variable(results, "FlowActivePowerVariable__TwoTerminalHVDCLine") @test all(hvdc_flow[!, "nodeC-nodeC2"] .<= 200) @test all(hvdc_flow[!, "nodeC-nodeC2"] .>= -200) @@ -556,7 +556,7 @@ end ) # Test forcing flows to 0.0 - hvdc_link = get_component(PSY.HVDCLine, c_sys5, "nodeC-nodeC2") + hvdc_link = get_component(TwoTerminalHVDCLine, c_sys5, "nodeC-nodeC2") set_active_power_limits_from!(hvdc_link, (min = 0.0, max = 0.0)) set_active_power_limits_to!(hvdc_link, (min = 0.0, max = 0.0)) @@ -572,7 +572,7 @@ end PSI.get_constraint(opt_container, CopperPlateBalanceConstraint(), PSY.System) results = ProblemResults(ps_model) - hvdc_flow = read_variable(results, "FlowActivePowerVariable__HVDCLine") + hvdc_flow = read_variable(results, "FlowActivePowerVariable__TwoTerminalHVDCLine") @test all(hvdc_flow[!, "nodeC-nodeC2"] .== 0.0) @test all(hvdc_flow[!, "nodeC-nodeC2"] .== 0.0) @@ -619,7 +619,7 @@ end psi_checksolve_test(ps_model, [MOI.OPTIMAL], 684763, 100) results = ProblemResults(ps_model) - hvdc_flow = read_variable(results, "FlowActivePowerVariable__HVDCLine") + hvdc_flow = read_variable(results, "FlowActivePowerVariable__TwoTerminalHVDCLine") @test all(hvdc_flow[!, "nodeC-nodeC2"] .<= 200) @test all(hvdc_flow[!, "nodeC-nodeC2"] .>= -200) @@ -656,7 +656,7 @@ end ) # Test forcing flows to 0.0 - hvdc_link = get_component(PSY.HVDCLine, c_sys5, "nodeC-nodeC2") + hvdc_link = get_component(PSY.TwoTerminalHVDCLine, c_sys5, "nodeC-nodeC2") set_active_power_limits_from!(hvdc_link, (min = 0.0, max = 0.0)) set_active_power_limits_to!(hvdc_link, (min = 0.0, max = 0.0)) @@ -672,7 +672,7 @@ end PSI.get_constraint(opt_container, CopperPlateBalanceConstraint(), PSY.System) results = ProblemResults(ps_model) - hvdc_flow = read_variable(results, "FlowActivePowerVariable__HVDCLine") + hvdc_flow = read_variable(results, "FlowActivePowerVariable__TwoTerminalHVDCLine") @test all(hvdc_flow[!, "nodeC-nodeC2"] .== 0.0) @test all(hvdc_flow[!, "nodeC-nodeC2"] .== 0.0) diff --git a/test/test_utils/mock_operation_models.jl b/test/test_utils/mock_operation_models.jl index f1166c01cb..a41128efb5 100644 --- a/test/test_utils/mock_operation_models.jl +++ b/test/test_utils/mock_operation_models.jl @@ -44,7 +44,7 @@ end function PSI.DecisionModel(::Type{MockOperationProblem}; name = nothing, kwargs...) sys = System(100.0) - add_component!(sys, Bus(nothing)) + add_component!(sys, ACBus(nothing)) l = PowerLoad(nothing) gen = ThermalStandard(nothing) set_bus!(l, get_component(Bus, sys, "init")) @@ -71,7 +71,7 @@ end function PSI.EmulationModel(::Type{MockEmulationProblem}; name = nothing, kwargs...) sys = System(100.0) - add_component!(sys, Bus(nothing)) + add_component!(sys, ACBus(nothing)) l = PowerLoad(nothing) gen = ThermalStandard(nothing) set_bus!(l, get_component(Bus, sys, "init")) @@ -116,6 +116,7 @@ function mock_construct_device!( PSI.get_optimization_container(problem), PSI.get_network_formulation(template), PSI.get_network_model(template).subnetworks, + PSI.get_system(problem), ) if PSI.validate_available_devices(model, PSI.get_system(problem)) PSI.construct_device!( diff --git a/test/test_utils/operations_problem_templates.jl b/test/test_utils/operations_problem_templates.jl index c08eabc94b..43c1e5bd1a 100644 --- a/test/test_utils/operations_problem_templates.jl +++ b/test/test_utils/operations_problem_templates.jl @@ -13,7 +13,7 @@ function get_thermal_dispatch_template_network(network = CopperPlatePowerModel) set_device_model!(template, Line, StaticBranch) set_device_model!(template, Transformer2W, StaticBranch) set_device_model!(template, TapTransformer, StaticBranch) - set_device_model!(template, HVDCLine, HVDCP2PLossless) + set_device_model!(template, TwoTerminalHVDCLine, HVDCTwoTerminalLossless) return template end @@ -70,6 +70,6 @@ function get_template_dispatch_with_network(network = StandardPTDFModel) set_device_model!(template, Line, StaticBranch) set_device_model!(template, Transformer2W, StaticBranch) set_device_model!(template, TapTransformer, StaticBranch) - set_device_model!(template, HVDCLine, HVDCP2PLossless) + set_device_model!(template, TwoTerminalHVDCLine, HVDCTwoTerminalLossless) return template end