From ee17425d8871c08ddbaf8df191453edb95dbd726 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 26 Jul 2024 14:51:40 -0700 Subject: [PATCH 01/10] add formulations --- src/core/formulations.jl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/core/formulations.jl b/src/core/formulations.jl index 1b6ddb109a..019b7f5b0f 100644 --- a/src/core/formulations.jl +++ b/src/core/formulations.jl @@ -145,11 +145,26 @@ LossLess InterconnectingConverter Model """ struct LossLessConverter <: AbstractConverterFormulation end +""" +Linear Loss InterconnectingConverter Model +""" +struct LinearLossConverter <: AbstractConverterFormulation end + +""" +Quadratic Loss InterconnectingConverter Model +""" +struct QuadraticLossConverter <: AbstractConverterFormulation end + """ LossLess Line Abstract Model """ struct LossLessLine <: AbstractBranchFormulation end +""" +DC Loss Line Abstract Model +""" +struct DCLossLine <: AbstractBranchFormulation end + ############################## Network Model Formulations ################################## # These formulations are taken directly from PowerModels From bfb5a1d4a7c3d97a4458cb3c1e71f7dae6571a13 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 26 Jul 2024 20:50:06 -0700 Subject: [PATCH 02/10] add variables to HVDC models --- src/core/auxiliary_variables.jl | 14 ++ src/core/formulations.jl | 2 +- src/core/variables.jl | 112 ++++++++++++++ .../hvdcsystems_constructor.jl | 138 ++++++++++++++++++ 4 files changed, 265 insertions(+), 1 deletion(-) diff --git a/src/core/auxiliary_variables.jl b/src/core/auxiliary_variables.jl index c2baca4288..c4fc29faad 100644 --- a/src/core/auxiliary_variables.jl +++ b/src/core/auxiliary_variables.jl @@ -13,4 +13,18 @@ Auxiliary Variable for Thermal Generation Models that solve for power above min """ struct PowerOutput <: AuxVariableType end +""" +Auxiliary Variable of DC Current Variables for DC Lines formulations + +Docs abbreviation: ``i_l^{dc}`` +""" +struct DCLineCurrent <: AuxVariableType end + +""" +Auxiliary Variable of DC Current Variables for DC Lines formulations + +Docs abbreviation: ``p_l^{loss}`` +""" +struct DCLineLosses <: AuxVariableType end + convert_result_to_natural_units(::Type{PowerOutput}) = true diff --git a/src/core/formulations.jl b/src/core/formulations.jl index 019b7f5b0f..2764fa0dc6 100644 --- a/src/core/formulations.jl +++ b/src/core/formulations.jl @@ -163,7 +163,7 @@ struct LossLessLine <: AbstractBranchFormulation end """ DC Loss Line Abstract Model """ -struct DCLossLine <: AbstractBranchFormulation end +struct DCLossyLine <: AbstractBranchFormulation end ############################## Network Model Formulations ################################## # These formulations are taken directly from PowerModels diff --git a/src/core/variables.jl b/src/core/variables.jl index 42d5bc0560..3ef58aa05b 100644 --- a/src/core/variables.jl +++ b/src/core/variables.jl @@ -168,6 +168,118 @@ Docs abbreviation: ``\\theta`` """ struct VoltageAngle <: VariableType end +""" +Struct to dispatch the creation of Voltage Variables for DC formulations + +Docs abbreviation: ``v^{dc}`` +""" +struct DCVoltage <: VariableType end + +""" +Struct to dispatch the creation of Squared Voltage Variables for DC formulations + +Docs abbreviation: ``v^{sq,dc}`` +""" +struct SquaredDCVoltage <: VariableType end + +""" +Struct to dispatch the creation of DC Converter Current Variables for DC formulations + +Docs abbreviation: ``i_c^{dc}`` +""" +struct ConverterCurrent <: VariableType end + +""" +Struct to dispatch the creation of Squared DC Converter Current Variables for DC formulations + +Docs abbreviation: ``i_c^{sq,dc}`` +""" +struct SquaredConverterCurrent <: VariableType end + +""" +Struct to dispatch the creation of DC Converter Positive Term Current Variables for DC formulations + +Docs abbreviation: ``i_c^{+,dc}`` +""" +struct ConverterPositiveCurrent <: VariableType end + +""" +Struct to dispatch the creation of DC Converter Negative Term Current Variables for DC formulations + +Docs abbreviation: ``i_c^{-,dc}`` +""" +struct ConverterNegativeCurrent <: VariableType end + +""" +Struct to dispatch the creation of DC Converter Binary for Absolute Value Current Variables for DC formulations + +Docs abbreviation: `\\nu_c`` +""" +struct ConverterBinaryAbsoluteValueCurrent <: VariableType end + +""" +Struct to dispatch the creation of Binary Variable for Converter Power Direction + +Docs abbreviation: ``\\kappa_c^{dc}`` +""" +struct ConverterPowerDirection <: VariableType end + +""" +Struct to dispatch the creation of Auxiliary Variable for Converter Bilinear term: v * i + +Docs abbreviation: ``\\gamma_c^{dc}`` +""" +struct AuxBilinearConverterVariable <: VariableType end + +""" +Struct to dispatch the creation of Auxiliary Variable for Squared Converter Bilinear term: v * i + +Docs abbreviation: ``\\gamma_c^{sq,dc}`` +""" +struct AuxBilinearSquaredConverterVariable <: VariableType end + +""" +Struct to dispatch the creation of Continuous Interpolation Variable for Squared Converter Voltage + +Docs abbreviation: ``\\delta_c^{v}`` +""" +struct InterpolationSquaredVoltageVariable <: VariableType end + +""" +Struct to dispatch the creation of Binary Interpolation Variable for Squared Converter Voltage + +Docs abbreviation: ``z_c^{v}`` +""" +struct InterpolationBinarySquaredVoltageVariable <: VariableType end + +""" +Struct to dispatch the creation of Continuous Interpolation Variable for Squared Converter Current + +Docs abbreviation: ``\\delta_c^{i}`` +""" +struct InterpolationSquaredCurrentVariable <: VariableType end + +""" +Struct to dispatch the creation of Binary Interpolation Variable for Squared Converter Current + +Docs abbreviation: ``z_c^{i}`` +""" +struct InterpolationBinarySquaredCurrentVariable <: VariableType end + +""" +Struct to dispatch the creation of Continuous Interpolation Variable for Squared Converter AuxVar + +Docs abbreviation: ``\\delta_c^{\\gamma}`` +""" +struct InterpolationSquaredBilinearVariable <: VariableType end + +""" +Struct to dispatch the creation of Binary Interpolation Variable for Squared Converter AuxVar + +Docs abbreviation: ``z_c^{\\gamma}`` +""" +struct InterpolationBinarySquaredBilinearVariable <: VariableType end + """ Struct to dispatch the creation of bidirectional Active Power Flow Variables diff --git a/src/devices_models/device_constructors/hvdcsystems_constructor.jl b/src/devices_models/device_constructors/hvdcsystems_constructor.jl index 668b41f70e..f95f088640 100644 --- a/src/devices_models/device_constructors/hvdcsystems_constructor.jl +++ b/src/devices_models/device_constructors/hvdcsystems_constructor.jl @@ -39,6 +39,112 @@ function construct_device!( return end +function construct_device!( + container::OptimizationContainer, + sys::PSY.System, + ::ArgumentConstructStage, + model::DeviceModel{PSY.InterconnectingConverter, QuadraticLossConverter}, + network_model::NetworkModel{<:PM.AbstractActivePowerModel}, +) + devices = get_available_components( + model, + sys, + ) + # Add Power Variable + add_variables!(container, ActivePowerVariable, devices, QuadraticLossConverter()) # p_c + add_variables!(container, ConverterPowerDirection, devices, QuadraticLossConverter()) #κ + # Add Current Variables: i, δ^i, z^i, i+, i- + add_variables!(container, ConverterCurrent, devices, QuadraticLossConverter()) # i + add_variables!(container, SquaredConverterCurrent, devices, QuadraticLossConverter()) # i^sq + add_variables!( + container, + InterpolationSquaredCurrentVariable, + devices, + QuadraticLossConverter(), + ) # δ^i + add_variables!( + container, + InterpolationBinarySquaredCurrentVariable, + devices, + QuadraticLossConverter(), + ) # z^i + add_variables!(container, ConverterPositiveCurrent, devices, QuadraticLossConverter()) # i^+ + add_variables!(container, ConverterNegativeCurrent, devices, QuadraticLossConverter()) # i^- + add_variables!( + container, + ConverterBinaryAbsoluteValueCurrent, + devices, + QuadraticLossConverter(), + ) # ν + # Add Voltage Variables: v^sq, δ^v, z^v + add_variables!(container, SquaredDCVoltage, devices, QuadraticLossConverter()) + add_variables!( + container, + InterpolationSquaredVoltageVariable, + devices, + QuadraticLossConverter(), + ) # δ^v + add_variables!( + container, + InterpolationBinarySquaredVoltageVariable, + devices, + QuadraticLossConverter(), + ) # z^v + # Add Bilinear Variables: γ, γ^{sq} + add_variables!( + container, + AuxBilinearConverterVariable, + devices, + QuadraticLossConverter(), + ) # γ + add_variables!( + container, + AuxBilinearSquaredConverterVariable, + devices, + QuadraticLossConverter(), + ) # γ^{sq} + add_variables!( + container, + InterpolationSquaredBilinearVariable, + devices, + QuadraticLossConverter(), + ) # δ^γ + add_variables!( + container, + InterpolationBinarySquaredBilinearVariable, + devices, + QuadraticLossConverter(), + ) # z^γ + 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, QuadraticLossConverter}, + network_model::NetworkModel{<:PM.AbstractActivePowerModel}, +) + devices = get_available_components( + model, + sys, + ) + # TODO Constraints + add_feedforward_constraints!(container, model, devices) + objective_function!(container, devices, model, get_network_formulation(network_model)) + add_constraint_dual!(container, sys, model) + return +end + function construct_device!( container::OptimizationContainer, sys::PSY.System, @@ -71,3 +177,35 @@ function construct_device!( ::NetworkModel{<:PM.AbstractActivePowerModel}, ) end + +function construct_device!( + container::OptimizationContainer, + sys::PSY.System, + ::ArgumentConstructStage, + model::DeviceModel{PSY.TModelHVDCLine, DCLossyLine}, + network_model::NetworkModel{<:PM.AbstractActivePowerModel}, +) + devices = get_available_components( + model, + sys, + ) + + dc_buses = PSY.get_components( + DCBus, + sys, + ) + add_variables!(container, DCVoltage, dc_buses, DCLossyLine()) + add_variables!(container, DCLineCurrent, devices, DCLossyLine()) + add_variables!(container, DCLineLosses, devices, DCLossyLine()) + add_feedforward_arguments!(container, model, devices) + return +end + +function construct_device!( + ::OptimizationContainer, + sys::PSY.System, + ::ModelConstructStage, + model::DeviceModel{PSY.TModelHVDCLine, LossLessLine}, + ::NetworkModel{<:PM.AbstractActivePowerModel}, +) +end From b485312070cb42a266c61746bda86cae0b9328dc Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 29 Jul 2024 21:48:58 -0700 Subject: [PATCH 03/10] add converter dc power variable --- src/core/variables.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/variables.jl b/src/core/variables.jl index 3ef58aa05b..2a0b953794 100644 --- a/src/core/variables.jl +++ b/src/core/variables.jl @@ -189,6 +189,13 @@ Docs abbreviation: ``i_c^{dc}`` """ struct ConverterCurrent <: VariableType end +""" +Struct to dispatch the creation of DC Converter Power Variables for DC formulations + +Docs abbreviation: ``p_c^{dc}`` +""" +struct ConverterDCPower <: VariableType end + """ Struct to dispatch the creation of Squared DC Converter Current Variables for DC formulations From 180677e792f6d4f74e5027a4390d3a3d110448ad Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 29 Jul 2024 21:49:08 -0700 Subject: [PATCH 04/10] add dc current balance expression --- src/core/expressions.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/expressions.jl b/src/core/expressions.jl index f5ad354a7d..1f901aba2c 100644 --- a/src/core/expressions.jl +++ b/src/core/expressions.jl @@ -14,11 +14,13 @@ struct ComponentReserveUpBalanceExpression <: ExpressionType end struct ComponentReserveDownBalanceExpression <: ExpressionType end struct InterfaceTotalFlow <: ExpressionType end struct PTDFBranchFlow <: ExpressionType end +struct DCCurrentBalance <: ExpressionType end should_write_resulting_value(::Type{<:CostExpressions}) = true should_write_resulting_value(::Type{InterfaceTotalFlow}) = true should_write_resulting_value(::Type{RawACE}) = true should_write_resulting_value(::Type{ActivePowerBalance}) = true should_write_resulting_value(::Type{ReactivePowerBalance}) = true +should_write_resulting_value(::Type{DCCurrentBalance}) = true convert_result_to_natural_units(::Type{InterfaceTotalFlow}) = true From 2944a0030841f93e67d5d8dfce128ad5832047e8 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 29 Jul 2024 21:49:21 -0700 Subject: [PATCH 05/10] add converter current balance constraint --- src/core/constraints.jl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/core/constraints.jl b/src/core/constraints.jl index a36e8257cd..41d80bc9c6 100644 --- a/src/core/constraints.jl +++ b/src/core/constraints.jl @@ -416,3 +416,18 @@ struct LineFlowBoundConstraint <: ConstraintType end abstract type EventConstraint <: ConstraintType end struct OutageConstraint <: EventConstraint end + +""" +Struct to create the constraints that set the losses through a lossy Interconnecting Power Converter. + +For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). + +The specified constraint is formulated as: + +```math +\\begin{align*} +& i_c^{dc} = \\sum_{j \\in \\mathcal{B}^{DC}} \\frac{1}{r_{i,j}} (v_i - v_j), \\quad \\forall t \\in \\{1,\\dots, T\\} +\\end{align*} +``` +""" +struct ConverterCurrentBalanceConstraint <: ConstraintType end From 8914de29e605e5c4c62a780527ef5fa4dd2f793f Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 29 Jul 2024 21:49:38 -0700 Subject: [PATCH 06/10] add constructor for lossy models --- .../hvdcsystems_constructor.jl | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/devices_models/device_constructors/hvdcsystems_constructor.jl b/src/devices_models/device_constructors/hvdcsystems_constructor.jl index f95f088640..4b768473be 100644 --- a/src/devices_models/device_constructors/hvdcsystems_constructor.jl +++ b/src/devices_models/device_constructors/hvdcsystems_constructor.jl @@ -50,8 +50,13 @@ function construct_device!( model, sys, ) + ##################### + ##### Variables ##### + ##################### + # Add Power Variable - add_variables!(container, ActivePowerVariable, devices, QuadraticLossConverter()) # p_c + add_variables!(container, ActivePowerVariable, devices, QuadraticLossConverter()) # p_c^{ac} + #add_variables!(container, ConverterDCPower, devices, QuadraticLossConverter()) # p_c add_variables!(container, ConverterPowerDirection, devices, QuadraticLossConverter()) #κ # Add Current Variables: i, δ^i, z^i, i+, i- add_variables!(container, ConverterCurrent, devices, QuadraticLossConverter()) # i @@ -115,6 +120,12 @@ function construct_device!( devices, QuadraticLossConverter(), ) # z^γ + + ##################### + #### Expressions #### + ##################### + + # No losses for now: ActivePowerVariable = DCPower and ACPower add_to_expression!( container, ActivePowerBalance, @@ -139,6 +150,15 @@ function construct_device!( sys, ) # TODO Constraints + add_constraints!( + container, + sys, + ConverterCurrentBalanceConstraint, + devices, + model, + network_model, + ) + add_feedforward_constraints!(container, model, devices) objective_function!(container, devices, model, get_network_formulation(network_model)) add_constraint_dual!(container, sys, model) @@ -191,12 +211,12 @@ function construct_device!( ) dc_buses = PSY.get_components( - DCBus, + PSY.DCBus, sys, ) add_variables!(container, DCVoltage, dc_buses, DCLossyLine()) - add_variables!(container, DCLineCurrent, devices, DCLossyLine()) - add_variables!(container, DCLineLosses, devices, DCLossyLine()) + #add_variables!(container, DCLineCurrent, devices, DCLossyLine()) + #add_variables!(container, DCLineLosses, devices, DCLossyLine()) add_feedforward_arguments!(container, model, devices) return end @@ -205,7 +225,7 @@ function construct_device!( ::OptimizationContainer, sys::PSY.System, ::ModelConstructStage, - model::DeviceModel{PSY.TModelHVDCLine, LossLessLine}, + model::DeviceModel{PSY.TModelHVDCLine, DCLossyLine}, ::NetworkModel{<:PM.AbstractActivePowerModel}, ) end From 67c0602f4abbf73c572b752c97169a814578b91c Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 29 Jul 2024 21:49:56 -0700 Subject: [PATCH 07/10] add binary methods and current balance constraint --- src/devices_models/devices/HVDCsystems.jl | 89 ++++++++++++++++++++++- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/src/devices_models/devices/HVDCsystems.jl b/src/devices_models/devices/HVDCsystems.jl index ecf47f4d89..958bbd76af 100644 --- a/src/devices_models/devices/HVDCsystems.jl +++ b/src/devices_models/devices/HVDCsystems.jl @@ -1,7 +1,32 @@ #! format: off +### Binaries ### +# Converter get_variable_binary(::ActivePowerVariable, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = false +get_variable_binary(::ConverterPowerDirection, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = true +get_variable_binary(::ConverterCurrent, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = false +get_variable_binary(::ConverterPositiveCurrent, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = false +get_variable_binary(::ConverterNegativeCurrent, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = false +get_variable_binary(::ConverterBinaryAbsoluteValueCurrent, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = true +get_variable_binary(::SquaredConverterCurrent, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = false +get_variable_binary(::InterpolationSquaredCurrentVariable, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = false +get_variable_binary(::InterpolationBinarySquaredCurrentVariable, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = true +get_variable_binary(::SquaredDCVoltage, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = false +get_variable_binary(::InterpolationSquaredVoltageVariable, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = false +get_variable_binary(::InterpolationBinarySquaredVoltageVariable, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = true +get_variable_binary(::AuxBilinearConverterVariable, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = false +get_variable_binary(::AuxBilinearSquaredConverterVariable, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = false +get_variable_binary(::InterpolationSquaredBilinearVariable, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = false +get_variable_binary(::InterpolationBinarySquaredBilinearVariable, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = true +# DCBuses +get_variable_binary(::DCVoltage, ::Type{PSY.DCBus}, ::AbstractBranchFormulation) = false + +### Warm Start ### get_variable_warm_start_value(::ActivePowerVariable, d::PSY.InterconnectingConverter, ::AbstractConverterFormulation) = PSY.get_active_power(d) + +### Lower Bounds ### get_variable_lower_bound(::ActivePowerVariable, d::PSY.InterconnectingConverter, ::AbstractConverterFormulation) = PSY.get_active_power_limits(d).min + +### Upper Bounds ### 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 @@ -59,8 +84,8 @@ end function get_initial_conditions_device_model( ::OperationModel, - model::DeviceModel{PSY.TModelHVDCLine, LossLessLine}, -) + model::DeviceModel{PSY.TModelHVDCLine, D}, +) where {D <: Union{LossLessLine, DCLossyLine}} return model end @@ -317,11 +342,67 @@ function add_to_expression!( return end +########################## +###### Constraints ####### +########################## + +function add_constraints!( + container::OptimizationContainer, + sys::PSY.System, + ::Type{ConverterCurrentBalanceConstraint}, + devices::IS.FlattenIteratorWrapper{U}, + model::DeviceModel{U, V}, + network_model::NetworkModel{X}, +) where { + U <: PSY.InterconnectingConverter, + V <: QuadraticLossConverter, + X <: PM.AbstractActivePowerModel, +} + time_steps = get_time_steps(container) + varcurrent = get_variable(container, ConverterCurrent(), U) + var_dcvoltage = get_variable(container, DCVoltage(), PSY.DCBus) + ipc_names = axes(varcurrent, 1) + constraint = + add_constraints_container!(container, ConverterCurrentBalanceConstraint(), U, ipc_names, time_steps) + + for device in devices + name = PSY.get_name(device) + dc_bus = PSY.get_dc_bus(device) + dc_bus_name = PSY.get_name(dc_bus) + from_branches = PSY.get_components(x-> x.available && (x.arc.from == dc_bus), PSY.DCBranch, sys) + to_branches = PSY.get_components(x-> x.available && (x.arc.to == dc_bus), PSY.DCBranch, sys) + for t in time_steps + total_current_flow = JuMP.AffExpr() + for br in from_branches + r = PSY.get_r(br) + to_bus_name = PSY.get_name(br.arc.to) + if r <= 0.0 + error("Series resistance of DCBranch $(PSY.get_name(br)) is non-positive. Consider updating your data") + end + total_current_flow += (1.0 / r) * (var_dcvoltage[dc_bus_name, t] - var_dcvoltage[to_bus_name, t]) + end + for br in to_branches + r = PSY.get_r(br) + from_bus_name = PSY.get_name(br.arc.from) + if r <= 0.0 + error("Series resistance of DCBranch $(PSY.get_name(br)) is non-positive. Consider updating your data") + end + total_current_flow += (1.0 / r) * (var_dcvoltage[dc_bus_name, t] - var_dcvoltage[from_bus_name, t]) + end + constraint[name, t] = JuMP.@constraint( + get_jump_model(container), + varcurrent[name, t] == total_current_flow + ) + end + end + return +end + function objective_function!( ::OptimizationContainer, ::IS.FlattenIteratorWrapper{PSY.InterconnectingConverter}, - ::DeviceModel{PSY.InterconnectingConverter, LossLessConverter}, + ::DeviceModel{PSY.InterconnectingConverter, T}, ::Type{<:PM.AbstractPowerModel}, -) +) where {T <: Union{LossLessConverter, QuadraticLossConverter}} return end From 406689b578ab287b358beb14be95f9a67656b7ce Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 29 Jul 2024 21:50:04 -0700 Subject: [PATCH 08/10] export formulations --- src/PowerSimulations.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PowerSimulations.jl b/src/PowerSimulations.jl index 36af71cee2..98639c564f 100644 --- a/src/PowerSimulations.jl +++ b/src/PowerSimulations.jl @@ -49,7 +49,9 @@ export PhaseAngleControl ######## HVDC models ######## export LossLessConverter +export QuadraticLossConverter export LossLessLine +export DCLossyLine ######## Load Models ######## export StaticPowerLoad export PowerLoadInterruption From cd586eb35107cbb38ff824a048a9b88af6d99596 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Tue, 30 Jul 2024 12:21:32 -0700 Subject: [PATCH 09/10] add bilinear power constraint --- src/core/constraints.jl | 16 +++++++++ src/devices_models/devices/HVDCsystems.jl | 43 +++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/core/constraints.jl b/src/core/constraints.jl index 41d80bc9c6..206867af90 100644 --- a/src/core/constraints.jl +++ b/src/core/constraints.jl @@ -431,3 +431,19 @@ The specified constraint is formulated as: ``` """ struct ConverterCurrentBalanceConstraint <: ConstraintType end + +""" +Struct to create the constraints that compute the converter DC power based on current and voltage. + +For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). + +The specified constraints are formulated as: + +```math +\\begin{align*} +& p_c = 0.5 * (γ^sq - v^sq - i^sq), \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& γ_c = v_c + i_c, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +\\end{align*} +``` +""" +struct ConverterPowerCalculationConstraint <: ConstraintType end diff --git a/src/devices_models/devices/HVDCsystems.jl b/src/devices_models/devices/HVDCsystems.jl index 958bbd76af..1536ad2b88 100644 --- a/src/devices_models/devices/HVDCsystems.jl +++ b/src/devices_models/devices/HVDCsystems.jl @@ -398,6 +398,49 @@ function add_constraints!( return end +function add_constraints!( + container::OptimizationContainer, + sys::PSY.System, + ::Type{ConverterPowerCalculationConstraint}, + devices::IS.FlattenIteratorWrapper{U}, + model::DeviceModel{U, V}, + network_model::NetworkModel{X}, +) where { + U <: PSY.InterconnectingConverter, + V <: QuadraticLossConverter, + X <: PM.AbstractActivePowerModel, +} + time_steps = get_time_steps(container) + varcurrent = get_variable(container, ConverterCurrent(), U) + var_dcvoltage = get_variable(container, DCVoltage(), PSY.DCBus) + var_sq_current = get_variable(container, SquaredConverterCurrent(), U) + var_sq_voltage = get_variable(container, SquaredConverterVoltage(), U) + var_bilinear = get_variable(container, AuxBilinearConverterVariable(), U) + var_sq_bilinear = get_variable(container, AuxBilinearSquaredConverterVariable(), U) + var_dc_power = get_variable(container, ActivePowerVariable(), U) + ipc_names = axes(varcurrent, 1) + constraint = + add_constraints_container!(container, ConverterPowerCalculationConstraint(), U, ipc_names, time_steps) + constraint_aux = + add_constraints_container!(container, ConverterPowerCalculationConstraint(), U, ipc_names, time_steps; meta = "aux") + + for device in devices + name = PSY.get_name(device) + dc_bus_name = PSY.get_name(PSY.get_dc_bus(device)) + for t in time_steps + constraint[name, t] = JuMP.@constraint( + get_jump_model(container), + var_dc_power[name, t] == 0.5 * (var_sq_bilinear[name, t] - var_sq_voltage[name, t] - var_sq_current[name, t]) + ) + constraint_aux[name, t] = JuMP.@constraint( + get_jump_model(container), + var_bilinear[name, t] == var_dcvoltage[dc_bus_name, t] + var_current[name, t] + ) + end + end + return +end + function objective_function!( ::OptimizationContainer, ::IS.FlattenIteratorWrapper{PSY.InterconnectingConverter}, From c00394c67ae55f2e923222d2f2e5d338a0b0da1e Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Tue, 30 Jul 2024 16:58:25 -0700 Subject: [PATCH 10/10] add envelopes, direction and bilinear constraints --- src/core/constraints.jl | 34 ++++++ .../hvdcsystems_constructor.jl | 21 ++++ src/devices_models/devices/HVDCsystems.jl | 113 +++++++++++++++++- 3 files changed, 165 insertions(+), 3 deletions(-) diff --git a/src/core/constraints.jl b/src/core/constraints.jl index 206867af90..1e124252d1 100644 --- a/src/core/constraints.jl +++ b/src/core/constraints.jl @@ -447,3 +447,37 @@ The specified constraints are formulated as: ``` """ struct ConverterPowerCalculationConstraint <: ConstraintType end + +""" +Struct to create the constraints that decide the operation direction of the converter. + +For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). + +The specified constraints are formulated as: + +```math +\\begin{align*} +& I_c^{min} (1 - κ_c) <= i_c <= κ_c * I_c^{max}, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& P_c^{min} (1 - κ_c) <= p_c <= κ_c * P_c^{max}, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +\\end{align*} +``` +""" +struct ConverterDirectionConstraint <: ConstraintType end + +""" +Struct to create the McCormick envelopes constraints that decide the bounds on the DC active power. + +For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). + +The specified constraints are formulated as: + +```math +\\begin{align*} +& p_c >= V^{min} i_c + v_c I^{min} - I^{min}V^{min}, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& p_c >= V^{max} i_c + v_c I^{max} - I^{max}V^{max}, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& p_c <= V^{max} i_c + v_c I^{min} - I^{min}V^{max}, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& p_c <= V^{min} i_c + v_c I^{max} - I^{max}V^{min}, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +\\end{align*} +``` +""" +struct ConverterMcCormickEnvelopes <: ConstraintType end diff --git a/src/devices_models/device_constructors/hvdcsystems_constructor.jl b/src/devices_models/device_constructors/hvdcsystems_constructor.jl index 4b768473be..edb39c2576 100644 --- a/src/devices_models/device_constructors/hvdcsystems_constructor.jl +++ b/src/devices_models/device_constructors/hvdcsystems_constructor.jl @@ -158,6 +158,27 @@ function construct_device!( model, network_model, ) + add_constraints!( + container, + ConverterPowerCalculationConstraint, + devices, + model, + network_model, + ) + add_constraints!( + container, + ConverterDirectionConstraint, + devices, + model, + network_model, + ) + add_constraints!( + container, + ConverterMcCormickEnvelopes, + devices, + model, + network_model, + ) add_feedforward_constraints!(container, model, devices) objective_function!(container, devices, model, get_network_formulation(network_model)) diff --git a/src/devices_models/devices/HVDCsystems.jl b/src/devices_models/devices/HVDCsystems.jl index 1536ad2b88..988c8d0b1a 100644 --- a/src/devices_models/devices/HVDCsystems.jl +++ b/src/devices_models/devices/HVDCsystems.jl @@ -22,12 +22,16 @@ get_variable_binary(::DCVoltage, ::Type{PSY.DCBus}, ::AbstractBranchFormulation) ### Warm Start ### get_variable_warm_start_value(::ActivePowerVariable, d::PSY.InterconnectingConverter, ::AbstractConverterFormulation) = PSY.get_active_power(d) +get_variable_warm_start_value(::ConverterCurrent, d::PSY.InterconnectingConverter, ::AbstractConverterFormulation) = PSY.get_dc_current(d) ### Lower Bounds ### get_variable_lower_bound(::ActivePowerVariable, d::PSY.InterconnectingConverter, ::AbstractConverterFormulation) = PSY.get_active_power_limits(d).min +get_variable_lower_bound(::ConverterCurrent, d::PSY.InterconnectingConverter, ::AbstractConverterFormulation) = PSY.get_dc_current_limits(d).min ### Upper Bounds ### get_variable_upper_bound(::ActivePowerVariable, d::PSY.InterconnectingConverter, ::AbstractConverterFormulation) = PSY.get_active_power_limits(d).max +get_variable_upper_bound(::ConverterCurrent, d::PSY.InterconnectingConverter, ::AbstractConverterFormulation) = PSY.get_dc_current_limits(d).max + get_variable_multiplier(_, ::Type{PSY.InterconnectingConverter}, ::AbstractConverterFormulation) = 1.0 @@ -400,7 +404,6 @@ end function add_constraints!( container::OptimizationContainer, - sys::PSY.System, ::Type{ConverterPowerCalculationConstraint}, devices::IS.FlattenIteratorWrapper{U}, model::DeviceModel{U, V}, @@ -414,7 +417,7 @@ function add_constraints!( varcurrent = get_variable(container, ConverterCurrent(), U) var_dcvoltage = get_variable(container, DCVoltage(), PSY.DCBus) var_sq_current = get_variable(container, SquaredConverterCurrent(), U) - var_sq_voltage = get_variable(container, SquaredConverterVoltage(), U) + var_sq_voltage = get_variable(container, SquaredDCVoltage(), U) var_bilinear = get_variable(container, AuxBilinearConverterVariable(), U) var_sq_bilinear = get_variable(container, AuxBilinearSquaredConverterVariable(), U) var_dc_power = get_variable(container, ActivePowerVariable(), U) @@ -434,7 +437,111 @@ function add_constraints!( ) constraint_aux[name, t] = JuMP.@constraint( get_jump_model(container), - var_bilinear[name, t] == var_dcvoltage[dc_bus_name, t] + var_current[name, t] + var_bilinear[name, t] == var_dcvoltage[dc_bus_name, t] + varcurrent[name, t] + ) + end + end + return +end + +function add_constraints!( + container::OptimizationContainer, + ::Type{ConverterDirectionConstraint}, + devices::IS.FlattenIteratorWrapper{U}, + model::DeviceModel{U, V}, + network_model::NetworkModel{X}, +) where { + U <: PSY.InterconnectingConverter, + V <: QuadraticLossConverter, + X <: PM.AbstractActivePowerModel, +} + time_steps = get_time_steps(container) + varcurrent = get_variable(container, ConverterCurrent(), U) + var_dc_power = get_variable(container, ActivePowerVariable(), U) + var_binary = get_variable(container, ConverterPowerDirection(), U) + ipc_names = axes(varcurrent, 1) + constraint_i_ub = + add_constraints_container!(container, ConverterDirectionConstraint(), U, ipc_names, time_steps; meta = "current_ub") + constraint_i_lb = + add_constraints_container!(container, ConverterDirectionConstraint(), U, ipc_names, time_steps; meta = "current_lb") + constraint_p_ub = + add_constraints_container!(container, ConverterDirectionConstraint(), U, ipc_names, time_steps; meta = "power_ub") + constraint_p_lb = + add_constraints_container!(container, ConverterDirectionConstraint(), U, ipc_names, time_steps; meta = "power_lb") + + for device in devices + name = PSY.get_name(device) + P_min, P_max = PSY.get_active_power_limits(device) + I_min, I_max = PSY.get_dc_current_limits(device) + for t in time_steps + constraint_i_ub[name, t] = JuMP.@constraint( + get_jump_model(container), + varcurrent[name, t] <= var_binary[name, t] * I_max + ) + constraint_i_lb[name, t] = JuMP.@constraint( + get_jump_model(container), + varcurrent[name, t] >= (1 - var_binary[name, t]) * I_min + ) + constraint_p_ub[name, t] = JuMP.@constraint( + get_jump_model(container), + var_dc_power[name, t] <= var_binary[name, t] * P_max + ) + constraint_p_lb[name, t] = JuMP.@constraint( + get_jump_model(container), + var_dc_power[name, t] >= (1 - var_binary[name, t]) * P_min + ) + end + end + return +end + +function add_constraints!( + container::OptimizationContainer, + ::Type{ConverterMcCormickEnvelopes}, + devices::IS.FlattenIteratorWrapper{U}, + model::DeviceModel{U, V}, + network_model::NetworkModel{X}, +) where { + U <: PSY.InterconnectingConverter, + V <: QuadraticLossConverter, + X <: PM.AbstractActivePowerModel, +} + time_steps = get_time_steps(container) + varcurrent = get_variable(container, ConverterCurrent(), U) + var_dcvoltage = get_variable(container, DCVoltage(), PSY.DCBus) + var_dc_power = get_variable(container, ActivePowerVariable(), U) + ipc_names = axes(varcurrent, 1) + constraint1_under = + add_constraints_container!(container, ConverterMcCormickEnvelopes(), U, ipc_names, time_steps; meta = "under_1") + constraint2_under = + add_constraints_container!(container, ConverterMcCormickEnvelopes(), U, ipc_names, time_steps; meta = "under_2") + constraint1_over = + add_constraints_container!(container, ConverterMcCormickEnvelopes(), U, ipc_names, time_steps; meta = "over_1") + constraint2_over = + add_constraints_container!(container, ConverterMcCormickEnvelopes(), U, ipc_names, time_steps; meta = "over_2") + + for device in devices + name = PSY.get_name(device) + dc_bus = PSY.get_dc_bus(device) + dc_bus_name = PSY.get_name(dc_bus) + V_min, V_max = PSY.get_voltage_limits(dc_bus) + I_min, I_max = PSY.get_dc_current_limits(device) + for t in time_steps + constraint1_under[name, t] = JuMP.@constraint( + get_jump_model(container), + var_dc_power[name, t] >= V_min * varcurrent[name, t] + var_dcvoltage[dc_bus_name, t] * I_min - I_min * V_min + ) + constraint2_under[name, t] = JuMP.@constraint( + get_jump_model(container), + var_dc_power[name, t] >= V_max * varcurrent[name, t] + var_dcvoltage[dc_bus_name, t] * I_max - I_max * V_max + ) + constraint1_over[name, t] = JuMP.@constraint( + get_jump_model(container), + var_dc_power[name, t] <= V_max * varcurrent[name, t] + var_dcvoltage[dc_bus_name, t] * I_min - I_min * V_max + ) + constraint2_over[name, t] = JuMP.@constraint( + get_jump_model(container), + var_dc_power[name, t] <= V_min * varcurrent[name, t] + var_dcvoltage[dc_bus_name, t] * I_max - I_max * V_min ) end end