From c1c4aae36782cbdf517577d8d3082f797a8fd9ff Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Tue, 22 Oct 2024 16:42:03 -0700 Subject: [PATCH 01/34] add vars and constraints --- src/core/constraints.jl | 53 +++++++++++++++++++ src/core/formulations.jl | 4 ++ src/core/variables.jl | 109 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) diff --git a/src/core/constraints.jl b/src/core/constraints.jl index 817130ba4..f20584d22 100644 --- a/src/core/constraints.jl +++ b/src/core/constraints.jl @@ -401,3 +401,56 @@ 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 + +""" +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 + +""" +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 \ No newline at end of file diff --git a/src/core/formulations.jl b/src/core/formulations.jl index 52f1d5e06..112aa2b2d 100644 --- a/src/core/formulations.jl +++ b/src/core/formulations.jl @@ -138,6 +138,10 @@ struct HVDCTwoTerminalDispatch <: AbstractTwoTerminalDCLineFormulation end Branch type to represent piecewise lossy power flow on two terminal DC lines """ struct HVDCTwoTerminalPiecewiseLoss <: AbstractTwoTerminalDCLineFormulation end +""" +Branch type to represent physical lossy model on two terminal DC lines +""" +struct HVDCTwoTerminalPhysicalLoss <: AbstractTwoTerminalDCLineFormulation end # Not Implemented # struct VoltageSourceDC <: AbstractTwoTerminalDCLineFormulation end diff --git a/src/core/variables.jl b/src/core/variables.jl index 3050c31f5..7f28b17eb 100644 --- a/src/core/variables.jl +++ b/src/core/variables.jl @@ -168,6 +168,115 @@ 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 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 +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 From b24e0226f417df8d62f6eb4a4bb85ed2fa87721b Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Tue, 22 Oct 2024 16:48:50 -0700 Subject: [PATCH 02/34] add constructors --- src/core/constraints.jl | 2 +- .../device_constructors/branch_constructor.jl | 142 ++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) diff --git a/src/core/constraints.jl b/src/core/constraints.jl index f20584d22..8cecdfacd 100644 --- a/src/core/constraints.jl +++ b/src/core/constraints.jl @@ -453,4 +453,4 @@ The specified constraints are formulated as: \\end{align*} ``` """ -struct ConverterMcCormickEnvelopes <: ConstraintType end \ No newline at end of file +struct ConverterMcCormickEnvelopes <: ConstraintType end diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index 8230cef82..c2d99c356 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -899,6 +899,148 @@ function construct_device!( return end +function construct_device!( + container::OptimizationContainer, + sys::PSY.System, + ::ArgumentConstructStage, + model::DeviceModel{PSY.TwoTerminalHVDCDetailedLine, HVDCTwoTerminalPhysicalLoss}, + network_model::NetworkModel{<:PM.AbstractActivePowerModel}, +) + devices = get_available_components(model, sys) + + ##################### + ##### Variables ##### + ##################### + V = HVDCTwoTerminalPhysicalLoss + # Add Power Variable + add_variables!(container, ActivePowerVariable, devices, V()) # p_c^{ac} + add_variables!(container, DCVoltage, devices, V()) # v_dc + add_variables!(container, ConverterPowerDirection, devices, V()) #κ + # Add Current Variables: i, δ^i, z^i, i+, i- + add_variables!(container, ConverterCurrent, devices, V()) # i + add_variables!(container, SquaredConverterCurrent, devices, V()) # i^sq + add_variables!( + container, + InterpolationSquaredCurrentVariable, + devices, + V(), + ) # δ^i + add_variables!( + container, + InterpolationBinarySquaredCurrentVariable, + devices, + V(), + ) # z^i + add_variables!(container, ConverterPositiveCurrent, devices, V()) # i^+ + add_variables!(container, ConverterNegativeCurrent, devices, V()) # i^- + add_variables!( + container, + ConverterBinaryAbsoluteValueCurrent, + devices, + V(), + ) # ν + # Add Voltage Variables: v^sq, δ^v, z^v + add_variables!(container, SquaredDCVoltage, devices, V()) + add_variables!( + container, + InterpolationSquaredVoltageVariable, + devices, + V(), + ) # δ^v + add_variables!( + container, + InterpolationBinarySquaredVoltageVariable, + devices, + V(), + ) # z^v + # Add Bilinear Variables: γ, γ^{sq} + add_variables!( + container, + AuxBilinearConverterVariable, + devices, + V(), + ) # γ + add_variables!( + container, + AuxBilinearSquaredConverterVariable, + devices, + V(), + ) # γ^{sq} + add_variables!( + container, + InterpolationSquaredBilinearVariable, + devices, + V(), + ) # δ^γ + add_variables!( + container, + InterpolationBinarySquaredBilinearVariable, + devices, + V(), + ) # z^γ + + ##################### + #### Expressions #### + ##################### + + # No losses for now: ActivePowerVariable = DCPower and ACPower + 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.TwoTerminalHVDCDetailedLine, HVDCTwoTerminalPhysicalLoss}, + network_model::NetworkModel{<:PM.AbstractActivePowerModel}, +) + devices = get_available_components(model, sys) + # TODO Constraints + add_constraints!( + container, + sys, + ConverterCurrentBalanceConstraint, + devices, + 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)) + add_constraint_dual!(container, sys, model) + return +end + ############################# Phase Shifter Transformer Models ############################# function construct_device!( From ca75343ffde6e0ab15491cc3190223f26f26bd1b Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Thu, 24 Oct 2024 11:45:07 -0700 Subject: [PATCH 03/34] update constructor with from and to vars --- src/core/variables.jl | 73 ++++++++++++--- .../device_constructors/branch_constructor.jl | 90 +++++++++++++++---- 2 files changed, 134 insertions(+), 29 deletions(-) diff --git a/src/core/variables.jl b/src/core/variables.jl index 7f28b17eb..413020aa8 100644 --- a/src/core/variables.jl +++ b/src/core/variables.jl @@ -172,13 +172,25 @@ struct VoltageAngle <: VariableType end Struct to dispatch the creation of Voltage Variables for DC formulations Docs abbreviation: ``v^{dc}`` """ -struct DCVoltage <: VariableType end +struct DCVoltageFrom <: VariableType end """ Struct to dispatch the creation of Squared Voltage Variables for DC formulations Docs abbreviation: ``v^{sq,dc}`` """ -struct SquaredDCVoltage <: VariableType end +struct SquaredDCVoltageFrom <: VariableType end + +""" +Struct to dispatch the creation of Voltage Variables for DC formulations +Docs abbreviation: ``v^{dc}`` +""" +struct DCVoltageTo <: VariableType end + +""" +Struct to dispatch the creation of Squared Voltage Variables for DC formulations +Docs abbreviation: ``v^{sq,dc}`` +""" +struct SquaredDCVoltageTo <: VariableType end """ Struct to dispatch the creation of DC Converter Current Variables for DC formulations @@ -226,28 +238,55 @@ 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 AuxBilinearConverterVariableFrom <: VariableType end + +""" +Struct to dispatch the creation of Auxiliary Variable for Squared Converter Bilinear term: v * i + +Docs abbreviation: ``\\gamma_c^{sq,dc}`` +""" +struct AuxBilinearSquaredConverterVariableFrom <: VariableType end + +""" +Struct to dispatch the creation of Auxiliary Variable for Converter Bilinear term: v * i +Docs abbreviation: ``\\gamma_c^{dc}`` +""" +struct AuxBilinearConverterVariableTo <: 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 AuxBilinearSquaredConverterVariableTo <: VariableType end """ Struct to dispatch the creation of Continuous Interpolation Variable for Squared Converter Voltage -Docs abbreviation: ``\\delta_c^{v}`` +Docs abbreviation: ``\\delta_c^{v,from}`` """ -struct InterpolationSquaredVoltageVariable <: VariableType end +struct InterpolationSquaredVoltageVariableFrom <: VariableType end + +""" +Struct to dispatch the creation of Continuous Interpolation Variable for Squared Converter Voltage + +Docs abbreviation: ``\\delta_c^{v,to}`` +""" +struct InterpolationSquaredVoltageVariableTo <: VariableType end """ Struct to dispatch the creation of Binary Interpolation Variable for Squared Converter Voltage -Docs abbreviation: ``z_c^{v}`` +Docs abbreviation: ``z_c^{v,from}`` """ -struct InterpolationBinarySquaredVoltageVariable <: VariableType end +struct InterpolationBinarySquaredVoltageVariableFrom <: VariableType end + +""" +Struct to dispatch the creation of Binary Interpolation Variable for Squared Converter Voltage + +Docs abbreviation: ``z_c^{v,to}`` +""" +struct InterpolationBinarySquaredVoltageVariableTo <: VariableType end """ Struct to dispatch the creation of Continuous Interpolation Variable for Squared Converter Current @@ -268,14 +307,28 @@ Struct to dispatch the creation of Continuous Interpolation Variable for Squared Docs abbreviation: ``\\delta_c^{\\gamma}`` """ -struct InterpolationSquaredBilinearVariable <: VariableType end +struct InterpolationSquaredBilinearVariableFrom <: VariableType end + +""" +Struct to dispatch the creation of Binary Interpolation Variable for Squared Converter AuxVar + +Docs abbreviation: ``z_c^{\\gamma}`` +""" +struct InterpolationBinarySquaredBilinearVariableFrom <: VariableType end + +""" +Struct to dispatch the creation of Continuous Interpolation Variable for Squared Converter AuxVar + +Docs abbreviation: ``\\delta_c^{\\gamma}`` +""" +struct InterpolationSquaredBilinearVariableTo <: 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 InterpolationBinarySquaredBilinearVariableTo <: VariableType end """ Struct to dispatch the creation of bidirectional Active Power Flow Variables diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index c2d99c356..9155fb65a 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -913,9 +913,39 @@ function construct_device!( ##################### V = HVDCTwoTerminalPhysicalLoss # Add Power Variable - add_variables!(container, ActivePowerVariable, devices, V()) # p_c^{ac} - add_variables!(container, DCVoltage, devices, V()) # v_dc + add_variables!(container, HVDCActivePowerReceivedFromVariable, devices, V()) # p_c^{ac,from} + add_variables!(container, HVDCActivePowerReceivedToVariable, devices, V()) # p_c^{ac,from} add_variables!(container, ConverterPowerDirection, devices, V()) #κ + # Add Voltage Variables: v_dc, v^sq, δ^v, z^v + add_variables!(container, DCVoltageFrom, devices, V()) # v_dc^{from} + add_variables!(container, DCVoltageTo, devices, V()) # v_dc^{from} + add_variables!(container, SquaredDCVoltageFrom, devices, V()) # v_dc^{sq, from} + add_variables!(container, SquaredDCVoltageTo, devices, V()) # # v_dc^{sq, to} + add_variables!( + container, + InterpolationSquaredVoltageVariableFrom, + devices, + V(), + ) # δ^{v,from} + add_variables!( + container, + InterpolationSquaredVoltageVariableTo, + devices, + V(), + ) # δ^{v,to} + add_variables!( + container, + InterpolationBinarySquaredVoltageVariableFrom, + devices, + V(), + ) # z^{v,from} + add_variables!( + container, + InterpolationBinarySquaredVoltageVariableTo, + devices, + V(), + ) # z^{v,to} + # Add Current Variables: i, δ^i, z^i, i+, i- add_variables!(container, ConverterCurrent, devices, V()) # i add_variables!(container, SquaredConverterCurrent, devices, V()) # i^sq @@ -939,55 +969,76 @@ function construct_device!( devices, V(), ) # ν - # Add Voltage Variables: v^sq, δ^v, z^v - add_variables!(container, SquaredDCVoltage, devices, V()) + + # Add Bilinear Variables: γ, γ^{sq} add_variables!( container, - InterpolationSquaredVoltageVariable, + AuxBilinearConverterVariableFrom, devices, V(), - ) # δ^v + ) # γ^{from} add_variables!( container, - InterpolationBinarySquaredVoltageVariable, + AuxBilinearSquaredConverterVariableFrom, devices, V(), - ) # z^v - # Add Bilinear Variables: γ, γ^{sq} + ) # γ^{sq,from} + add_variables!( + container, + InterpolationSquaredBilinearVariableFrom, + devices, + V(), + ) # δ^{γ,from} + add_variables!( + container, + InterpolationBinarySquaredBilinearVariableFrom, + devices, + V(), + ) # z^{γ,from} + add_variables!( container, - AuxBilinearConverterVariable, + AuxBilinearConverterVariableTo, devices, V(), - ) # γ + ) # γ^{to} add_variables!( container, - AuxBilinearSquaredConverterVariable, + AuxBilinearSquaredConverterVariableTo, devices, V(), - ) # γ^{sq} + ) # γ^{sq,to} add_variables!( container, - InterpolationSquaredBilinearVariable, + InterpolationSquaredBilinearVariableTo, devices, V(), - ) # δ^γ + ) # δ^{γ,to} add_variables!( container, - InterpolationBinarySquaredBilinearVariable, + InterpolationBinarySquaredBilinearVariableTo, devices, V(), - ) # z^γ + ) # z^{γ,to} ##################### #### Expressions #### ##################### - # No losses for now: ActivePowerVariable = DCPower and ACPower + # HVDCActivePowerReceivedFromVariable: AC Power add_to_expression!( container, ActivePowerBalance, - ActivePowerVariable, + HVDCActivePowerReceivedFromVariable, + devices, + model, + network_model, + ) + # HVDCActivePowerReceivedToVariable: AC Power + add_to_expression!( + container, + ActivePowerBalance, + HVDCActivePowerReceivedToVariable, devices, model, network_model, @@ -1003,6 +1054,7 @@ function construct_device!( model::DeviceModel{PSY.TwoTerminalHVDCDetailedLine, HVDCTwoTerminalPhysicalLoss}, network_model::NetworkModel{<:PM.AbstractActivePowerModel}, ) + error("here") devices = get_available_components(model, sys) # TODO Constraints add_constraints!( From a53150a15a53ea06965db9b0f2d009ed4ba5ce2b Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Thu, 24 Oct 2024 11:45:15 -0700 Subject: [PATCH 04/34] add bounds for variables --- .../devices/TwoTerminalDC_branches.jl | 89 ++++++++++++++++++- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/src/devices_models/devices/TwoTerminalDC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl index 29685dbb8..3f6fa15c5 100644 --- a/src/devices_models/devices/TwoTerminalDC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -17,6 +17,37 @@ get_variable_binary( ::AbstractTwoTerminalDCLineFormulation, ) = true +get_variable_binary( + _, + ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::HVDCTwoTerminalPhysicalLoss, +) = false +get_variable_binary( + ::InterpolationBinarySquaredVoltageVariableFrom, + ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::HVDCTwoTerminalPhysicalLoss, +) = true +get_variable_binary( + ::InterpolationBinarySquaredVoltageVariableTo, + ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::HVDCTwoTerminalPhysicalLoss, +) = true +get_variable_binary( + ::InterpolationBinarySquaredBilinearVariableFrom, + ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::HVDCTwoTerminalPhysicalLoss, +) = true +get_variable_binary( + ::InterpolationBinarySquaredBilinearVariableTo, + ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::HVDCTwoTerminalPhysicalLoss, +) = true +get_variable_binary( + ::ConverterPowerDirection, + ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::HVDCTwoTerminalPhysicalLoss, +) = true + get_variable_multiplier(::FlowActivePowerVariable, ::Type{<:PSY.TwoTerminalHVDCLine}, _) = NaN get_parameter_multiplier( @@ -81,6 +112,7 @@ get_variable_upper_bound( ::AbstractTwoTerminalDCLineFormulation, ) = nothing +### Two Terminal Dispatch ### get_variable_lower_bound( ::HVDCLosses, d::PSY.TwoTerminalHVDCLine, @@ -113,25 +145,25 @@ get_variable_lower_bound( get_variable_upper_bound( ::HVDCActivePowerReceivedFromVariable, - d::PSY.TwoTerminalHVDCLine, + d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalHVDCDetailedLine}, ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_from(d).max get_variable_lower_bound( ::HVDCActivePowerReceivedFromVariable, - d::PSY.TwoTerminalHVDCLine, + d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalHVDCDetailedLine}, ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_from(d).min get_variable_upper_bound( ::HVDCActivePowerReceivedToVariable, - d::PSY.TwoTerminalHVDCLine, + d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalHVDCDetailedLine}, ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_to(d).max get_variable_lower_bound( ::HVDCActivePowerReceivedToVariable, - d::PSY.TwoTerminalHVDCLine, + d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalHVDCDetailedLine}, ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_to(d).min @@ -167,6 +199,55 @@ get_variable_lower_bound( ::Union{HVDCTwoTerminalDispatch, HVDCTwoTerminalPiecewiseLoss}, ) = 0.0 +### Two Terminal Physical Loss ### +get_variable_upper_bound( + ::Union{DCVoltageFrom, DCVoltageTo}, + d::PSY.TwoTerminalHVDCDetailedLine, + ::HVDCTwoTerminalPhysicalLoss, +) = PSY.get_voltage_limits(d).max + +get_variable_lower_bound( + ::Union{DCVoltageFrom, DCVoltageTo}, + d::PSY.TwoTerminalHVDCDetailedLine, + ::HVDCTwoTerminalPhysicalLoss, +) = PSY.get_voltage_limits(d).min + +get_variable_upper_bound( + ::Union{SquaredDCVoltageFrom, SquaredDCVoltageTo}, + d::PSY.TwoTerminalHVDCDetailedLine, + ::HVDCTwoTerminalPhysicalLoss, +) = PSY.get_voltage_limits(d).max^2 + +get_variable_lower_bound( + ::Union{SquaredDCVoltageFrom, SquaredDCVoltageTo}, + d::PSY.TwoTerminalHVDCDetailedLine, + ::HVDCTwoTerminalPhysicalLoss, +) = 0.0 + +get_variable_upper_bound( + ::Union{ + InterpolationSquaredVoltageVariableFrom, + InterpolationSquaredVoltageVariableTo, + InterpolationSquaredCurrentVariable, + InterpolationSquaredBilinearVariableFrom, + InterpolationSquaredBilinearVariableTo, + }, + d::PSY.TwoTerminalHVDCDetailedLine, + ::HVDCTwoTerminalPhysicalLoss, +) = 1.0 + +get_variable_lower_bound( + ::Union{ + InterpolationSquaredVoltageVariableFrom, + InterpolationSquaredVoltageVariableTo, + InterpolationSquaredCurrentVariable, + InterpolationSquaredBilinearVariableFrom, + InterpolationSquaredBilinearVariableTo, + }, + d::PSY.TwoTerminalHVDCDetailedLine, + ::HVDCTwoTerminalPhysicalLoss, +) = 0.0 + function get_default_time_series_names( ::Type{U}, ::Type{V}, From 62f59d330d89b77267424e51f27da3c546aed466 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Thu, 24 Oct 2024 15:54:10 -0700 Subject: [PATCH 05/34] add constraints --- src/core/definitions.jl | 6 +- .../device_constructors/branch_constructor.jl | 15 +- .../devices/TwoTerminalDC_branches.jl | 359 ++++++++++++++++++ .../devices/common/add_to_expression.jl | 4 +- 4 files changed, 370 insertions(+), 14 deletions(-) diff --git a/src/core/definitions.jl b/src/core/definitions.jl index 74de4d65f..8e1291ddb 100644 --- a/src/core/definitions.jl +++ b/src/core/definitions.jl @@ -37,7 +37,11 @@ const JuMPFloatMatrix = DenseAxisArray{Float64, 2} const JuMPFloatArray = DenseAxisArray{Float64} const JuMPVariableArray = DenseAxisArray{JuMP.VariableRef} -const TwoTerminalHVDCTypes = Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCDCLine} +const TwoTerminalHVDCTypes = Union{ + PSY.TwoTerminalHVDCLine, + PSY.TwoTerminalVSCDCLine, + PSY.TwoTerminalHVDCDetailedLine, +} # Settings constants const UNSET_HORIZON = Dates.Millisecond(0) const UNSET_RESOLUTION = Dates.Millisecond(0) diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index 9155fb65a..946f85858 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -1025,7 +1025,7 @@ function construct_device!( #### Expressions #### ##################### - # HVDCActivePowerReceivedFromVariable: AC Power + # HVDCActivePowerReceivedFromVariable: DC Power Received on From Bus add_to_expression!( container, ActivePowerBalance, @@ -1034,7 +1034,7 @@ function construct_device!( model, network_model, ) - # HVDCActivePowerReceivedToVariable: AC Power + # HVDCActivePowerReceivedToVariable: DC Power Received on To Bus add_to_expression!( container, ActivePowerBalance, @@ -1043,6 +1043,7 @@ function construct_device!( model, network_model, ) + # TODO: Add losses to balance expression to get full AC add_feedforward_arguments!(container, model, devices) return end @@ -1054,17 +1055,8 @@ function construct_device!( model::DeviceModel{PSY.TwoTerminalHVDCDetailedLine, HVDCTwoTerminalPhysicalLoss}, network_model::NetworkModel{<:PM.AbstractActivePowerModel}, ) - error("here") devices = get_available_components(model, sys) # TODO Constraints - add_constraints!( - container, - sys, - ConverterCurrentBalanceConstraint, - devices, - model, - network_model, - ) add_constraints!( container, ConverterPowerCalculationConstraint, @@ -1086,6 +1078,7 @@ function construct_device!( model, network_model, ) + error("here") add_feedforward_constraints!(container, model, devices) objective_function!(container, devices, model, get_network_formulation(network_model)) diff --git a/src/devices_models/devices/TwoTerminalDC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl index 3f6fa15c5..caa245ff6 100644 --- a/src/devices_models/devices/TwoTerminalDC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -799,3 +799,362 @@ function add_constraints!( end return end + +##### Two Terminal Physical Loss #### + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:AbstractPTDFModel}, +) where { + T <: ConverterPowerCalculationConstraint, + U <: PSY.TwoTerminalHVDCDetailedLine, + V <: HVDCTwoTerminalPhysicalLoss, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + # power vars # + from_power_var = get_variable(container, HVDCActivePowerReceivedFromVariable(), U) + to_power_var = get_variable(container, HVDCActivePowerReceivedToVariable(), U) + # voltage vars # + from_voltage_var = get_variable(container, DCVoltageFrom(), U) + to_voltage_var = get_variable(container, DCVoltageTo(), U) + from_voltage_sq_var = get_variable(container, SquaredDCVoltageFrom(), U) + to_voltage_sq_var = get_variable(container, SquaredDCVoltageTo(), U) + # current vars # + current_var = get_variable(container, ConverterCurrent(), U) # From direction + current_sq_var = get_variable(container, SquaredConverterCurrent(), U) # From direction + # bilinear vars # + from_bilinear_var = get_variable(container, AuxBilinearConverterVariableFrom(), U) + from_bilinear_sq_var = + get_variable(container, AuxBilinearSquaredConverterVariableFrom(), U) + to_bilinear_var = get_variable(container, AuxBilinearConverterVariableTo(), U) + to_bilinear_sq_var = get_variable(container, AuxBilinearSquaredConverterVariableTo(), U) + + constraint_from_calc = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "from_calc", + ) + constraint_from_aux = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "from_aux", + ) + constraint_to_calc = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "to_calc", + ) + constraint_to_aux = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "to_aux", + ) + + for d in devices + name = PSY.get_name(d) + for t in get_time_steps(container) + constraint_from_calc[name, t] = JuMP.@constraint( + get_jump_model(container), + from_power_var[name, t] == + 0.5 * ( + from_bilinear_sq_var[name, t] - from_voltage_sq_var[name, t] - + current_sq_var[name, t] + ) + ) + constraint_to_calc[name, t] = JuMP.@constraint( + get_jump_model(container), + to_power_var[name, t] == + 0.5 * ( + to_bilinear_sq_var[name, t] - to_voltage_sq_var[name, t] - + current_sq_var[name, t] + ) + ) + constraint_from_aux[name, t] = JuMP.@constraint( + get_jump_model(container), + from_bilinear_var[name, t] == + from_voltage_var[name, t] + current_var[name, t] + ) + constraint_to_aux[name, t] = JuMP.@constraint( + get_jump_model(container), + to_bilinear_var[name, t] == to_voltage_var[name, t] - current_var[name, t] # change current sign + ) + end + end + return +end + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:AbstractPTDFModel}, +) where { + T <: ConverterDirectionConstraint, + U <: PSY.TwoTerminalHVDCDetailedLine, + V <: HVDCTwoTerminalPhysicalLoss, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + JuMPmodel = get_jump_model(container) + # power vars # + from_power_var = get_variable(container, HVDCActivePowerReceivedFromVariable(), U) + to_power_var = get_variable(container, HVDCActivePowerReceivedToVariable(), U) + # current vars # + current_var = get_variable(container, ConverterCurrent(), U) # From direction + direction_var = get_variable(container, ConverterPowerDirection(), U) + + constraint_from_power_ub = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "from_power_ub", + ) + constraint_from_power_lb = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "from_power_lb", + ) + constraint_current_ub = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "current_ub", + ) + constraint_current_lb = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "current_lb", + ) + constraint_to_power_ub = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "to_power_ub", + ) + constraint_to_power_lb = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "to_power_lb", + ) + for d in devices + name = PSY.get_name(d) + I_max = PSY.get_max_dc_current(d) + I_neg = -I_max + P_min_from, P_max_from = PSY.get_active_power_limits_from(d) + P_min_to, P_max_to = PSY.get_active_power_limits_to(d) + for t in time_steps + constraint_from_power_ub[name, t] = JuMP.@constraint( + JuMPmodel, + from_power_var[name, t] <= P_max_from * direction_var[name, t] + ) + constraint_from_power_lb[name, t] = JuMP.@constraint( + JuMPmodel, + from_power_var[name, t] >= P_min_from * (1.0 - direction_var[name, t]) + ) + constraint_current_ub[name, t] = JuMP.@constraint( + JuMPmodel, + current_var[name, t] <= I_max * direction_var[name, t] + ) + constraint_current_lb[name, t] = JuMP.@constraint( + JuMPmodel, + current_var[name, t] >= I_neg * (1.0 - direction_var[name, t]) + ) + constraint_to_power_ub[name, t] = JuMP.@constraint( + JuMPmodel, + to_power_var[name, t] <= P_max_to * (1.0 - direction_var[name, t]) + ) + constraint_to_power_lb[name, t] = JuMP.@constraint( + JuMPmodel, + to_power_var[name, t] >= P_min_to * direction_var[name, t] + ) + end + end + return +end + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:AbstractPTDFModel}, +) where { + T <: ConverterMcCormickEnvelopes, + U <: PSY.TwoTerminalHVDCDetailedLine, + V <: HVDCTwoTerminalPhysicalLoss, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + JuMPmodel = get_jump_model(container) + # power vars # + from_power_var = get_variable(container, HVDCActivePowerReceivedFromVariable(), U) + to_power_var = get_variable(container, HVDCActivePowerReceivedToVariable(), U) + # current vars # + current_var = get_variable(container, ConverterCurrent(), U) # From direction + # voltage vars # + from_voltage_var = get_variable(container, DCVoltageFrom(), U) + to_voltage_var = get_variable(container, DCVoltageTo(), U) + + from_constraint1_under = + add_constraints_container!( + container, + ConverterMcCormickEnvelopes(), + U, + names, + time_steps; + meta = "from_under_1", + ) + from_constraint2_under = + add_constraints_container!( + container, + ConverterMcCormickEnvelopes(), + U, + names, + time_steps; + meta = "from_under_2", + ) + from_constraint1_over = + add_constraints_container!( + container, + ConverterMcCormickEnvelopes(), + U, + names, + time_steps; + meta = "from_over_1", + ) + from_constraint2_over = + add_constraints_container!( + container, + ConverterMcCormickEnvelopes(), + U, + names, + time_steps; + meta = "from_over_2", + ) + to_constraint1_under = + add_constraints_container!( + container, + ConverterMcCormickEnvelopes(), + U, + names, + time_steps; + meta = "to_under_1", + ) + to_constraint2_under = + add_constraints_container!( + container, + ConverterMcCormickEnvelopes(), + U, + names, + time_steps; + meta = "to_under_2", + ) + to_constraint1_over = + add_constraints_container!( + container, + ConverterMcCormickEnvelopes(), + U, + names, + time_steps; + meta = "to_over_1", + ) + to_constraint2_over = + add_constraints_container!( + container, + ConverterMcCormickEnvelopes(), + U, + names, + time_steps; + meta = "to_over_2", + ) + + for d in devices + name = PSY.get_name(d) + V_min, V_max = PSY.get_voltage_limits(d) + I_max = PSY.get_max_dc_current(d) + I_neg = -I_max + for t in time_steps + from_constraint1_under[name, t] = JuMP.@constraint( + JuMPmodel, + from_power_var[name, t] >= + V_min * current_var[name, t] + from_voltage_var[name, t] * I_neg - + I_neg * V_min + ) + from_constraint2_under[name, t] = JuMP.@constraint( + JuMPmodel, + from_power_var[name, t] >= + V_max * current_var[name, t] + from_voltage_var[name, t] * I_max - + I_max * V_max + ) + from_constraint1_over[name, t] = JuMP.@constraint( + JuMPmodel, + from_power_var[name, t] <= + V_max * current_var[name, t] + from_voltage_var[name, t] * I_neg - + I_neg * V_max + ) + from_constraint2_over[name, t] = JuMP.@constraint( + JuMPmodel, + from_power_var[name, t] <= + V_min * current_var[name, t] + from_voltage_var[name, t] * I_max - + I_max * V_min + ) + to_constraint1_under[name, t] = JuMP.@constraint( + JuMPmodel, + to_power_var[name, t] >= + V_min * (-current_var[name, t]) + to_voltage_var[name, t] * I_neg - + I_neg * V_min + ) + to_constraint2_under[name, t] = JuMP.@constraint( + JuMPmodel, + to_power_var[name, t] >= + V_max * (-current_var[name, t]) + to_voltage_var[name, t] * I_max - + I_max * V_max + ) + to_constraint1_over[name, t] = JuMP.@constraint( + JuMPmodel, + to_power_var[name, t] <= + V_max * (-current_var[name, t]) + to_voltage_var[name, t] * I_neg - + I_neg * V_max + ) + to_constraint2_over[name, t] = JuMP.@constraint( + JuMPmodel, + to_power_var[name, t] <= + V_min * (-current_var[name, t]) + to_voltage_var[name, t] * I_max - + I_max * V_min + ) + end + end + return +end diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index 9c53a40e0..7bdedca7b 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -393,7 +393,7 @@ function add_to_expression!( T <: ActivePowerBalance, U <: HVDCActivePowerReceivedFromVariable, V <: TwoTerminalHVDCTypes, - W <: HVDCTwoTerminalPiecewiseLoss, + W <: Union{HVDCTwoTerminalPiecewiseLoss, HVDCTwoTerminalPhysicalLoss}, X <: AbstractPTDFModel, } var = get_variable(container, U(), V) @@ -430,7 +430,7 @@ function add_to_expression!( T <: ActivePowerBalance, U <: HVDCActivePowerReceivedToVariable, V <: TwoTerminalHVDCTypes, - W <: HVDCTwoTerminalPiecewiseLoss, + W <: Union{HVDCTwoTerminalPiecewiseLoss, HVDCTwoTerminalPhysicalLoss}, X <: AbstractPTDFModel, } var = get_variable(container, U(), V) From fdd267d1eed54654916a11854d39ee7db27c3ac1 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 28 Oct 2024 17:22:32 -0700 Subject: [PATCH 06/34] add pwl variables --- src/core/variables.jl | 24 +++--- .../devices/TwoTerminalDC_branches.jl | 84 +++++++++++++++---- 2 files changed, 81 insertions(+), 27 deletions(-) diff --git a/src/core/variables.jl b/src/core/variables.jl index 413020aa8..6d215c754 100644 --- a/src/core/variables.jl +++ b/src/core/variables.jl @@ -1,3 +1,5 @@ +abstract type SparseVariableType <: VariableType end + """ Struct to dispatch the creation of Active Power Variables @@ -265,70 +267,70 @@ Struct to dispatch the creation of Continuous Interpolation Variable for Squared Docs abbreviation: ``\\delta_c^{v,from}`` """ -struct InterpolationSquaredVoltageVariableFrom <: VariableType end +struct InterpolationSquaredVoltageVariableFrom <: SparseVariableType end """ Struct to dispatch the creation of Continuous Interpolation Variable for Squared Converter Voltage Docs abbreviation: ``\\delta_c^{v,to}`` """ -struct InterpolationSquaredVoltageVariableTo <: VariableType end +struct InterpolationSquaredVoltageVariableTo <: SparseVariableType end """ Struct to dispatch the creation of Binary Interpolation Variable for Squared Converter Voltage Docs abbreviation: ``z_c^{v,from}`` """ -struct InterpolationBinarySquaredVoltageVariableFrom <: VariableType end +struct InterpolationBinarySquaredVoltageVariableFrom <: SparseVariableType end """ Struct to dispatch the creation of Binary Interpolation Variable for Squared Converter Voltage Docs abbreviation: ``z_c^{v,to}`` """ -struct InterpolationBinarySquaredVoltageVariableTo <: VariableType end +struct InterpolationBinarySquaredVoltageVariableTo <: SparseVariableType end """ Struct to dispatch the creation of Continuous Interpolation Variable for Squared Converter Current Docs abbreviation: ``\\delta_c^{i}`` """ -struct InterpolationSquaredCurrentVariable <: VariableType end +struct InterpolationSquaredCurrentVariable <: SparseVariableType end """ Struct to dispatch the creation of Binary Interpolation Variable for Squared Converter Current Docs abbreviation: ``z_c^{i}`` """ -struct InterpolationBinarySquaredCurrentVariable <: VariableType end +struct InterpolationBinarySquaredCurrentVariable <: SparseVariableType end """ Struct to dispatch the creation of Continuous Interpolation Variable for Squared Converter AuxVar Docs abbreviation: ``\\delta_c^{\\gamma}`` """ -struct InterpolationSquaredBilinearVariableFrom <: VariableType end +struct InterpolationSquaredBilinearVariableFrom <: SparseVariableType end """ Struct to dispatch the creation of Binary Interpolation Variable for Squared Converter AuxVar Docs abbreviation: ``z_c^{\\gamma}`` """ -struct InterpolationBinarySquaredBilinearVariableFrom <: VariableType end +struct InterpolationBinarySquaredBilinearVariableFrom <: SparseVariableType end """ Struct to dispatch the creation of Continuous Interpolation Variable for Squared Converter AuxVar Docs abbreviation: ``\\delta_c^{\\gamma}`` """ -struct InterpolationSquaredBilinearVariableTo <: VariableType end +struct InterpolationSquaredBilinearVariableTo <: SparseVariableType end """ Struct to dispatch the creation of Binary Interpolation Variable for Squared Converter AuxVar Docs abbreviation: ``z_c^{\\gamma}`` """ -struct InterpolationBinarySquaredBilinearVariableTo <: VariableType end +struct InterpolationBinarySquaredBilinearVariableTo <: SparseVariableType end """ Struct to dispatch the creation of bidirectional Active Power Flow Variables @@ -404,8 +406,6 @@ Docs abbreviation: ``y`` """ struct HVDCActivePowerReceivedToVariable <: VariableType end -abstract type SparseVariableType <: VariableType end - """ Struct to dispatch the creation of HVDC Piecewise Loss Variables diff --git a/src/devices_models/devices/TwoTerminalDC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl index caa245ff6..09f736beb 100644 --- a/src/devices_models/devices/TwoTerminalDC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -20,32 +20,32 @@ get_variable_binary( get_variable_binary( _, ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, - ::HVDCTwoTerminalPhysicalLoss, + ::HVDCTwoTerminalVSCLoss, ) = false get_variable_binary( ::InterpolationBinarySquaredVoltageVariableFrom, ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, - ::HVDCTwoTerminalPhysicalLoss, + ::HVDCTwoTerminalVSCLoss, ) = true get_variable_binary( ::InterpolationBinarySquaredVoltageVariableTo, ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, - ::HVDCTwoTerminalPhysicalLoss, + ::HVDCTwoTerminalVSCLoss, ) = true get_variable_binary( ::InterpolationBinarySquaredBilinearVariableFrom, ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, - ::HVDCTwoTerminalPhysicalLoss, + ::HVDCTwoTerminalVSCLoss, ) = true get_variable_binary( ::InterpolationBinarySquaredBilinearVariableTo, ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, - ::HVDCTwoTerminalPhysicalLoss, + ::HVDCTwoTerminalVSCLoss, ) = true get_variable_binary( ::ConverterPowerDirection, ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, - ::HVDCTwoTerminalPhysicalLoss, + ::HVDCTwoTerminalVSCLoss, ) = true get_variable_multiplier(::FlowActivePowerVariable, ::Type{<:PSY.TwoTerminalHVDCLine}, _) = @@ -203,25 +203,25 @@ get_variable_lower_bound( get_variable_upper_bound( ::Union{DCVoltageFrom, DCVoltageTo}, d::PSY.TwoTerminalHVDCDetailedLine, - ::HVDCTwoTerminalPhysicalLoss, + ::HVDCTwoTerminalVSCLoss, ) = PSY.get_voltage_limits(d).max get_variable_lower_bound( ::Union{DCVoltageFrom, DCVoltageTo}, d::PSY.TwoTerminalHVDCDetailedLine, - ::HVDCTwoTerminalPhysicalLoss, + ::HVDCTwoTerminalVSCLoss, ) = PSY.get_voltage_limits(d).min get_variable_upper_bound( ::Union{SquaredDCVoltageFrom, SquaredDCVoltageTo}, d::PSY.TwoTerminalHVDCDetailedLine, - ::HVDCTwoTerminalPhysicalLoss, + ::HVDCTwoTerminalVSCLoss, ) = PSY.get_voltage_limits(d).max^2 get_variable_lower_bound( ::Union{SquaredDCVoltageFrom, SquaredDCVoltageTo}, d::PSY.TwoTerminalHVDCDetailedLine, - ::HVDCTwoTerminalPhysicalLoss, + ::HVDCTwoTerminalVSCLoss, ) = 0.0 get_variable_upper_bound( @@ -233,7 +233,7 @@ get_variable_upper_bound( InterpolationSquaredBilinearVariableTo, }, d::PSY.TwoTerminalHVDCDetailedLine, - ::HVDCTwoTerminalPhysicalLoss, + ::HVDCTwoTerminalVSCLoss, ) = 1.0 get_variable_lower_bound( @@ -245,7 +245,7 @@ get_variable_lower_bound( InterpolationSquaredBilinearVariableTo, }, d::PSY.TwoTerminalHVDCDetailedLine, - ::HVDCTwoTerminalPhysicalLoss, + ::HVDCTwoTerminalVSCLoss, ) = 0.0 function get_default_time_series_names( @@ -268,6 +268,60 @@ get_initial_conditions_device_model( ) where {T <: PSY.TwoTerminalHVDCLine, U <: AbstractTwoTerminalDCLineFormulation} = DeviceModel(T, U) +#### PWL Variables #### + +function _add_sparse_pwl_interpolation_variables!( + container::OptimizationContainer, + devices, + ::DeviceModel{D, HVDCTwoTerminalVSCLoss}, +) where {D <: PSY.TwoTerminalHVDCDetailedLine} + # TODO: Implement approach for deciding segment length + # Create Variables + time_steps = get_time_steps(container) + formulation = HVDCTwoTerminalVSCLoss() + len_segments = DEFAULT_INTERPOLATION_LENGTH + vars_vector = [ + # Voltage v # + InterpolationSquaredVoltageVariableFrom, + InterpolationSquaredVoltageVariableTo, + InterpolationBinarySquaredVoltageVariableFrom, + InterpolationBinarySquaredVoltageVariableTo, + # Current i # + InterpolationSquaredCurrentVariable, + InterpolationBinarySquaredCurrentVariable, + # Bilinear γ # + InterpolationSquaredBilinearVariableFrom, + InterpolationSquaredBilinearVariableTo, + InterpolationBinarySquaredBilinearVariableFrom, + InterpolationBinarySquaredBilinearVariableTo, + ] + for T in vars_vector + var_container = lazy_container_addition!(container, T(), D) + binary_flag = get_variable_binary(T(), D, formulation) + + for d in devices + name = PSY.get_name(d) + for t in time_steps + pwlvars = Array{JuMP.VariableRef}(undef, len_segments) + for i in 1:len_segments + pwlvars[i] = + var_container[(name, i, t)] = JuMP.@variable( + get_jump_model(container), + base_name = "$(T)_$(name)_{pwl_$(i), $(t)}", + binary = binary_flag + ) + ub = get_variable_upper_bound(T(), d, formulation) + ub !== nothing && JuMP.set_upper_bound(var_container[name, i, t], ub) + + lb = get_variable_lower_bound(T(), d, formulation) + lb !== nothing && JuMP.set_lower_bound(var_container[name, i, t], lb) + end + end + end + end + return +end + ####################################### PWL Constraints ####################################################### function _get_range_segments(::PSY.TwoTerminalHVDCLine, loss::PSY.LinearCurve) @@ -811,7 +865,7 @@ function add_constraints!( ) where { T <: ConverterPowerCalculationConstraint, U <: PSY.TwoTerminalHVDCDetailedLine, - V <: HVDCTwoTerminalPhysicalLoss, + V <: HVDCTwoTerminalVSCLoss, } time_steps = get_time_steps(container) names = [PSY.get_name(d) for d in devices] @@ -908,7 +962,7 @@ function add_constraints!( ) where { T <: ConverterDirectionConstraint, U <: PSY.TwoTerminalHVDCDetailedLine, - V <: HVDCTwoTerminalPhysicalLoss, + V <: HVDCTwoTerminalVSCLoss, } time_steps = get_time_steps(container) names = [PSY.get_name(d) for d in devices] @@ -1013,7 +1067,7 @@ function add_constraints!( ) where { T <: ConverterMcCormickEnvelopes, U <: PSY.TwoTerminalHVDCDetailedLine, - V <: HVDCTwoTerminalPhysicalLoss, + V <: HVDCTwoTerminalVSCLoss, } time_steps = get_time_steps(container) names = [PSY.get_name(d) for d in devices] From 46ccb066f03858e8c41a9288c3dff9e295262a0b Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 28 Oct 2024 17:22:47 -0700 Subject: [PATCH 07/34] update name to VSC loss --- src/core/constraints.jl | 15 +++++++++++++ src/core/definitions.jl | 1 + src/core/formulations.jl | 2 +- .../device_constructors/branch_constructor.jl | 22 +++++++++++++------ .../devices/common/add_to_expression.jl | 4 ++-- 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/core/constraints.jl b/src/core/constraints.jl index 8cecdfacd..2cc8931ab 100644 --- a/src/core/constraints.jl +++ b/src/core/constraints.jl @@ -454,3 +454,18 @@ The specified constraints are formulated as: ``` """ struct ConverterMcCormickEnvelopes <: ConstraintType end + +""" +Struct to create the Quadratic PWL interpolation constraints that decide square value of the voltage. +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 InterpolationVoltageConstraints <: ConstraintType end diff --git a/src/core/definitions.jl b/src/core/definitions.jl index 8e1291ddb..e6bc76347 100644 --- a/src/core/definitions.jl +++ b/src/core/definitions.jl @@ -65,6 +65,7 @@ const OBJECTIVE_FUNCTION_NEGATIVE = -1.0 const INITIALIZATION_PROBLEM_HORIZON_COUNT = 3 # The DEFAULT_RESERVE_COST value is used to avoid degeneracy of the solutions, reserve cost isn't provided. const DEFAULT_RESERVE_COST = 1.0 +const DEFAULT_INTERPOLATION_LENGTH = 4 const KiB = 1024 const MiB = KiB * KiB const GiB = MiB * KiB diff --git a/src/core/formulations.jl b/src/core/formulations.jl index 112aa2b2d..dc4e9d055 100644 --- a/src/core/formulations.jl +++ b/src/core/formulations.jl @@ -141,7 +141,7 @@ struct HVDCTwoTerminalPiecewiseLoss <: AbstractTwoTerminalDCLineFormulation end """ Branch type to represent physical lossy model on two terminal DC lines """ -struct HVDCTwoTerminalPhysicalLoss <: AbstractTwoTerminalDCLineFormulation end +struct HVDCTwoTerminalVSCLoss <: AbstractTwoTerminalDCLineFormulation end # Not Implemented # struct VoltageSourceDC <: AbstractTwoTerminalDCLineFormulation end diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index 946f85858..fa1288508 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -903,7 +903,7 @@ function construct_device!( container::OptimizationContainer, sys::PSY.System, ::ArgumentConstructStage, - model::DeviceModel{PSY.TwoTerminalHVDCDetailedLine, HVDCTwoTerminalPhysicalLoss}, + model::DeviceModel{PSY.TwoTerminalHVDCDetailedLine, HVDCTwoTerminalVSCLoss}, network_model::NetworkModel{<:PM.AbstractActivePowerModel}, ) devices = get_available_components(model, sys) @@ -911,7 +911,7 @@ function construct_device!( ##################### ##### Variables ##### ##################### - V = HVDCTwoTerminalPhysicalLoss + V = HVDCTwoTerminalVSCLoss # Add Power Variable add_variables!(container, HVDCActivePowerReceivedFromVariable, devices, V()) # p_c^{ac,from} add_variables!(container, HVDCActivePowerReceivedToVariable, devices, V()) # p_c^{ac,from} @@ -921,6 +921,7 @@ function construct_device!( add_variables!(container, DCVoltageTo, devices, V()) # v_dc^{from} add_variables!(container, SquaredDCVoltageFrom, devices, V()) # v_dc^{sq, from} add_variables!(container, SquaredDCVoltageTo, devices, V()) # # v_dc^{sq, to} + #= add_variables!( container, InterpolationSquaredVoltageVariableFrom, @@ -932,7 +933,7 @@ function construct_device!( InterpolationSquaredVoltageVariableTo, devices, V(), - ) # δ^{v,to} + ) # δ^{v,to} add_variables!( container, InterpolationBinarySquaredVoltageVariableFrom, @@ -945,10 +946,12 @@ function construct_device!( devices, V(), ) # z^{v,to} + =# # Add Current Variables: i, δ^i, z^i, i+, i- add_variables!(container, ConverterCurrent, devices, V()) # i add_variables!(container, SquaredConverterCurrent, devices, V()) # i^sq + #= add_variables!( container, InterpolationSquaredCurrentVariable, @@ -961,8 +964,9 @@ function construct_device!( devices, V(), ) # z^i - add_variables!(container, ConverterPositiveCurrent, devices, V()) # i^+ - add_variables!(container, ConverterNegativeCurrent, devices, V()) # i^- + =# + #add_variables!(container, ConverterPositiveCurrent, devices, V()) # i^+ + #add_variables!(container, ConverterNegativeCurrent, devices, V()) # i^- add_variables!( container, ConverterBinaryAbsoluteValueCurrent, @@ -983,6 +987,7 @@ function construct_device!( devices, V(), ) # γ^{sq,from} + #= add_variables!( container, InterpolationSquaredBilinearVariableFrom, @@ -995,7 +1000,7 @@ function construct_device!( devices, V(), ) # z^{γ,from} - + =# add_variables!( container, AuxBilinearConverterVariableTo, @@ -1008,6 +1013,7 @@ function construct_device!( devices, V(), ) # γ^{sq,to} + #= add_variables!( container, InterpolationSquaredBilinearVariableTo, @@ -1020,6 +1026,8 @@ function construct_device!( devices, V(), ) # z^{γ,to} + =# + _add_sparse_pwl_interpolation_variables!(container, devices, model) ##################### #### Expressions #### @@ -1052,7 +1060,7 @@ function construct_device!( container::OptimizationContainer, sys::PSY.System, ::ModelConstructStage, - model::DeviceModel{PSY.TwoTerminalHVDCDetailedLine, HVDCTwoTerminalPhysicalLoss}, + model::DeviceModel{PSY.TwoTerminalHVDCDetailedLine, HVDCTwoTerminalVSCLoss}, network_model::NetworkModel{<:PM.AbstractActivePowerModel}, ) devices = get_available_components(model, sys) diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index 7bdedca7b..16c1e23ba 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -393,7 +393,7 @@ function add_to_expression!( T <: ActivePowerBalance, U <: HVDCActivePowerReceivedFromVariable, V <: TwoTerminalHVDCTypes, - W <: Union{HVDCTwoTerminalPiecewiseLoss, HVDCTwoTerminalPhysicalLoss}, + W <: Union{HVDCTwoTerminalPiecewiseLoss, HVDCTwoTerminalVSCLoss}, X <: AbstractPTDFModel, } var = get_variable(container, U(), V) @@ -430,7 +430,7 @@ function add_to_expression!( T <: ActivePowerBalance, U <: HVDCActivePowerReceivedToVariable, V <: TwoTerminalHVDCTypes, - W <: Union{HVDCTwoTerminalPiecewiseLoss, HVDCTwoTerminalPhysicalLoss}, + W <: Union{HVDCTwoTerminalPiecewiseLoss, HVDCTwoTerminalVSCLoss}, X <: AbstractPTDFModel, } var = get_variable(container, U(), V) From 9ba6e4c777f7e22f81da10fd3851e4862a952d61 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Tue, 29 Oct 2024 11:40:58 -0700 Subject: [PATCH 08/34] remove comments --- .../device_constructors/branch_constructor.jl | 69 +------------------ 1 file changed, 1 insertion(+), 68 deletions(-) diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index fa1288508..2b23214ff 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -921,50 +921,11 @@ function construct_device!( add_variables!(container, DCVoltageTo, devices, V()) # v_dc^{from} add_variables!(container, SquaredDCVoltageFrom, devices, V()) # v_dc^{sq, from} add_variables!(container, SquaredDCVoltageTo, devices, V()) # # v_dc^{sq, to} - #= - add_variables!( - container, - InterpolationSquaredVoltageVariableFrom, - devices, - V(), - ) # δ^{v,from} - add_variables!( - container, - InterpolationSquaredVoltageVariableTo, - devices, - V(), - ) # δ^{v,to} - add_variables!( - container, - InterpolationBinarySquaredVoltageVariableFrom, - devices, - V(), - ) # z^{v,from} - add_variables!( - container, - InterpolationBinarySquaredVoltageVariableTo, - devices, - V(), - ) # z^{v,to} - =# # Add Current Variables: i, δ^i, z^i, i+, i- add_variables!(container, ConverterCurrent, devices, V()) # i add_variables!(container, SquaredConverterCurrent, devices, V()) # i^sq - #= - add_variables!( - container, - InterpolationSquaredCurrentVariable, - devices, - V(), - ) # δ^i - add_variables!( - container, - InterpolationBinarySquaredCurrentVariable, - devices, - V(), - ) # z^i - =# + # TODO: Activate Abs Value method #add_variables!(container, ConverterPositiveCurrent, devices, V()) # i^+ #add_variables!(container, ConverterNegativeCurrent, devices, V()) # i^- add_variables!( @@ -987,20 +948,6 @@ function construct_device!( devices, V(), ) # γ^{sq,from} - #= - add_variables!( - container, - InterpolationSquaredBilinearVariableFrom, - devices, - V(), - ) # δ^{γ,from} - add_variables!( - container, - InterpolationBinarySquaredBilinearVariableFrom, - devices, - V(), - ) # z^{γ,from} - =# add_variables!( container, AuxBilinearConverterVariableTo, @@ -1013,20 +960,6 @@ function construct_device!( devices, V(), ) # γ^{sq,to} - #= - add_variables!( - container, - InterpolationSquaredBilinearVariableTo, - devices, - V(), - ) # δ^{γ,to} - add_variables!( - container, - InterpolationBinarySquaredBilinearVariableTo, - devices, - V(), - ) # z^{γ,to} - =# _add_sparse_pwl_interpolation_variables!(container, devices, model) ##################### From fc0acc51e6a7ba2c26e1f5f0f2b7cf75afa227fa Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Tue, 29 Oct 2024 17:07:01 -0700 Subject: [PATCH 09/34] add interpolation methods --- .../devices/TwoTerminalDC_branches.jl | 122 +++++++++++++++++- 1 file changed, 120 insertions(+), 2 deletions(-) diff --git a/src/devices_models/devices/TwoTerminalDC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl index 09f736beb..07e48acb6 100644 --- a/src/devices_models/devices/TwoTerminalDC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -298,12 +298,14 @@ function _add_sparse_pwl_interpolation_variables!( for T in vars_vector var_container = lazy_container_addition!(container, T(), D) binary_flag = get_variable_binary(T(), D, formulation) + # Binaries have one less segment than the interpolation continuous variable + len_segs = binary_flag ? (len_segments - 1) : len_segments for d in devices name = PSY.get_name(d) for t in time_steps - pwlvars = Array{JuMP.VariableRef}(undef, len_segments) - for i in 1:len_segments + pwlvars = Array{JuMP.VariableRef}(undef, len_segs) + for i in 1:len_segs pwlvars[i] = var_container[(name, i, t)] = JuMP.@variable( get_jump_model(container), @@ -1212,3 +1214,119 @@ function add_constraints!( end return end + +####### PWL Interpolation for Function ####### + +function _get_breakpoints_for_pwl_function( + min_val::Float64, + max_val::Float64, + f; + num_segments = DEFAULT_INTERPOLATION_LENGTH, +) + # num_segments is the number of variables + # num_bkpts is the total breakpoints for the segments + num_bkpts = num_segments + 1 + step = (max_val - min_val) / num_segments + x_bkpts = Vector{Float64}(undef, num_bkpts) + y_bkpts = Vector{Float64}(undef, num_bkpts) + # first breakpoint is always the minimum value + x_bkpts[1] = min_val + y_bkpts[1] = f(min_val) + for i in 1:num_segments + x_val = min_val + step * i + x_bkpts[i + 1] = x_val + y_bkpts[i + 1] = f(x_val) + end + return x_bkpts, y_bkpts +end + +function _add_generic_incremental_interpolation_constraint( + container::OptimizationContainer, + ::R, # original var : x + ::S, # approximated var : y = f(x) + ::T, # interpolation var : δ + ::U, # binary interpolation var : z + ::V, # constraint + devices::IS.FlattenIteratorWrapper{W}, + var_bkpts::Vector{Float64}, + function_bkpts::Vector{Float64}, +) where { + R <: VariableType, + S <: VariableType, + T <: VariableType, + U <: VariableType, + V <: ConstraintType, + W <: PSY.Component, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + JuMPmodel = get_jump_model(container) + + x_var = get_variable(container, R(), W()) + y_var = get_variable(container, S(), W()) + δ_var = get_variable(container, T(), W()) + z_var = get_variable(container, U(), W()) + num_segments = length(var_bkpts) - 1 + + const_container_var = add_constraints_container!( + container, + V(), + W, + names, + time_steps; + meta = "pwl_variable", + ) + + const_container_function = add_constraints_container!( + container, + V(), + W, + names, + time_steps; + meta = "pwl_function", + ) + + for d in devices + name = PSY.get_name(d) + for t in time_steps + const_container_var[name, t] = JuMP.@constraint( + JuMPmodel, + x_var[name, t] == + var_bkpts[1] + sum( + δ_var[name, i, t] * (var_bkpts[i + 1] - var_bkpts[i]) for + i in 1:num_segments + ) + ) + const_container_function[name, t] = JuMP.@constraint( + JuMPmodel, + y_var[name, t] == + function_bkpts[1] + sum( + δ_var[name, i, t] * (function_bkpts[i + 1] - function_bkpts[i]) for + i in 1:num_segments + ) + ) + + for i in 1:(num_segments - 1) + JuMP.@constraint(JuMPmodel, z_var[name, i, t] >= δ_var[name, i + 1, t]) + JuMP.@constraint(JuMPmodel, z_var[name, i, t] <= δ_var[name, i, t]) + end + end + end + return +end + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:AbstractPTDFModel}, +) where { + T <: InterpolationVoltageConstraints, + U <: PSY.TwoTerminalHVDCDetailedLine, + V <: HVDCTwoTerminalVSCLoss, +} + + # TODO + +end From 70c9ce9d451945aff34fe6bc7f0ad38bde88842e Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Wed, 30 Oct 2024 15:44:05 -0700 Subject: [PATCH 10/34] add constraints names for interpolation --- src/core/constraints.jl | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/src/core/constraints.jl b/src/core/constraints.jl index 2cc8931ab..5e4ca7dfd 100644 --- a/src/core/constraints.jl +++ b/src/core/constraints.jl @@ -457,15 +457,48 @@ struct ConverterMcCormickEnvelopes <: ConstraintType end """ Struct to create the Quadratic PWL interpolation constraints that decide square value of the voltage. +In this case x = voltage and y = squared_voltage. 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\\} \\\\ +& x = x_0 + \\sum_{k=1}^K (x_{k} - x_{k-1}) \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& y = y_0 + \\sum_{k=1}^K (x_{k} - x_{k-1}) \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& z_k <= \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ +& z_k >= \\delta_{k+1}, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ \\end{align*} ``` """ struct InterpolationVoltageConstraints <: ConstraintType end + +""" +Struct to create the Quadratic PWL interpolation constraints that decide square value of the current. +In this case x = current and y = squared_current. +For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). +The specified constraints are formulated as: +```math +\\begin{align*} +& x = x_0 + \\sum_{k=1}^K (x_{k} - x_{k-1}) \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& y = y_0 + \\sum_{k=1}^K (x_{k} - x_{k-1}) \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& z_k <= \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ +& z_k >= \\delta_{k+1}, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ +\\end{align*} +``` +""" +struct InterpolationCurrentConstraints <: ConstraintType end + +""" +Struct to create the Quadratic PWL interpolation constraints that decide square value of the bilinear variable γ. +In this case x = γ and y = squared_γ. +For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). +The specified constraints are formulated as: +```math +\\begin{align*} +& x = x_0 + \\sum_{k=1}^K (x_{k} - x_{k-1}) \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& y = y_0 + \\sum_{k=1}^K (x_{k} - x_{k-1}) \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& z_k <= \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ +& z_k >= \\delta_{k+1}, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ +\\end{align*} +``` +""" +struct InterpolationBilinearConstraints <: ConstraintType end From 91786f06f57b10da14e1fad1fab1658a59f1f06c Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Wed, 30 Oct 2024 15:44:26 -0700 Subject: [PATCH 11/34] remove writing of interpolation vars --- src/core/variables.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/core/variables.jl b/src/core/variables.jl index 6d215c754..59ce7906d 100644 --- a/src/core/variables.jl +++ b/src/core/variables.jl @@ -466,6 +466,16 @@ should_write_resulting_value(::Type{PieceWiseLinearCostVariable}) = false should_write_resulting_value(::Type{PieceWiseLinearBlockOffer}) = false should_write_resulting_value(::Type{HVDCPiecewiseLossVariable}) = false should_write_resulting_value(::Type{HVDCPiecewiseBinaryLossVariable}) = false +should_write_resulting_value(::Type{InterpolationSquaredVoltageVariableFrom}) = false +should_write_resulting_value(::Type{InterpolationSquaredVoltageVariableTo}) = false +should_write_resulting_value(::Type{InterpolationBinarySquaredVoltageVariableFrom}) = false +should_write_resulting_value(::Type{InterpolationBinarySquaredVoltageVariableTo}) = false +should_write_resulting_value(::Type{InterpolationSquaredCurrentVariable}) = false +should_write_resulting_value(::Type{InterpolationBinarySquaredCurrentVariable}) = false +should_write_resulting_value(::Type{InterpolationSquaredBilinearVariableFrom}) = false +should_write_resulting_value(::Type{InterpolationSquaredBilinearVariableTo}) = false +should_write_resulting_value(::Type{InterpolationBinarySquaredBilinearVariableFrom}) = false +should_write_resulting_value(::Type{InterpolationBinarySquaredBilinearVariableTo}) = false convert_result_to_natural_units(::Type{ActivePowerVariable}) = true convert_result_to_natural_units(::Type{PowerAboveMinimumVariable}) = true convert_result_to_natural_units(::Type{ActivePowerInVariable}) = true From 1352eb7deb7dfbb00f80480dd008b48c67f2b1aa Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Wed, 30 Oct 2024 15:44:49 -0700 Subject: [PATCH 12/34] add interpolation constraints --- .../device_constructors/branch_constructor.jl | 30 ++- .../devices/TwoTerminalDC_branches.jl | 241 ++++++++++++++++-- 2 files changed, 245 insertions(+), 26 deletions(-) diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index 2b23214ff..c4b991793 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -1012,6 +1012,13 @@ function construct_device!( model, network_model, ) + add_constraints!( + container, + ConverterCurrentBalanceConstraint, + devices, + model, + network_model, + ) add_constraints!( container, ConverterMcCormickEnvelopes, @@ -1019,7 +1026,28 @@ function construct_device!( model, network_model, ) - error("here") + add_constraints!( + container, + InterpolationVoltageConstraints, + devices, + model, + network_model, + ) + add_constraints!( + container, + InterpolationCurrentConstraints, + devices, + model, + network_model, + ) + add_constraints!( + container, + InterpolationBilinearConstraints, + devices, + model, + network_model, + ) + #error("here") add_feedforward_constraints!(container, model, devices) objective_function!(container, devices, model, get_network_formulation(network_model)) diff --git a/src/devices_models/devices/TwoTerminalDC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl index 07e48acb6..80157716c 100644 --- a/src/devices_models/devices/TwoTerminalDC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -262,6 +262,17 @@ function get_default_attributes( return Dict{String, Any}() end +function get_default_attributes( + ::Type{U}, + ::Type{V}, +) where {U <: PSY.TwoTerminalHVDCDetailedLine, V <: HVDCTwoTerminalVSCLoss} + return Dict{String, Any}( + "voltage_segments" => 3, + "current_segments" => 6, + "bilinear_segments" => 10, + ) +end + get_initial_conditions_device_model( ::OperationModel, ::DeviceModel{T, U}, @@ -273,29 +284,31 @@ get_initial_conditions_device_model( function _add_sparse_pwl_interpolation_variables!( container::OptimizationContainer, devices, - ::DeviceModel{D, HVDCTwoTerminalVSCLoss}, + model::DeviceModel{D, HVDCTwoTerminalVSCLoss}, ) where {D <: PSY.TwoTerminalHVDCDetailedLine} # TODO: Implement approach for deciding segment length # Create Variables time_steps = get_time_steps(container) formulation = HVDCTwoTerminalVSCLoss() - len_segments = DEFAULT_INTERPOLATION_LENGTH + v_segments = PSI.get_attribute(model, "voltage_segments") + i_segments = PSI.get_attribute(model, "current_segments") + γ_segments = PSI.get_attribute(model, "bilinear_segments") vars_vector = [ # Voltage v # - InterpolationSquaredVoltageVariableFrom, - InterpolationSquaredVoltageVariableTo, - InterpolationBinarySquaredVoltageVariableFrom, - InterpolationBinarySquaredVoltageVariableTo, + (InterpolationSquaredVoltageVariableFrom, v_segments), + (InterpolationSquaredVoltageVariableTo, v_segments), + (InterpolationBinarySquaredVoltageVariableFrom, v_segments), + (InterpolationBinarySquaredVoltageVariableTo, v_segments), # Current i # - InterpolationSquaredCurrentVariable, - InterpolationBinarySquaredCurrentVariable, + (InterpolationSquaredCurrentVariable, i_segments), + (InterpolationBinarySquaredCurrentVariable, i_segments), # Bilinear γ # - InterpolationSquaredBilinearVariableFrom, - InterpolationSquaredBilinearVariableTo, - InterpolationBinarySquaredBilinearVariableFrom, - InterpolationBinarySquaredBilinearVariableTo, + (InterpolationSquaredBilinearVariableFrom, γ_segments), + (InterpolationSquaredBilinearVariableTo, γ_segments), + (InterpolationBinarySquaredBilinearVariableFrom, γ_segments), + (InterpolationBinarySquaredBilinearVariableTo, γ_segments), ] - for T in vars_vector + for (T, len_segments) in vars_vector var_container = lazy_container_addition!(container, T(), D) binary_flag = get_variable_binary(T(), D, formulation) # Binaries have one less segment than the interpolation continuous variable @@ -1240,7 +1253,7 @@ function _get_breakpoints_for_pwl_function( return x_bkpts, y_bkpts end -function _add_generic_incremental_interpolation_constraint( +function _add_generic_incremental_interpolation_constraint!( container::OptimizationContainer, ::R, # original var : x ::S, # approximated var : y = f(x) @@ -1248,8 +1261,9 @@ function _add_generic_incremental_interpolation_constraint( ::U, # binary interpolation var : z ::V, # constraint devices::IS.FlattenIteratorWrapper{W}, - var_bkpts::Vector{Float64}, - function_bkpts::Vector{Float64}, + dic_var_bkpts::Dict{String, Vector{Float64}}, + dic_function_bkpts::Dict{String, Vector{Float64}}; + meta = IS.Optimization.CONTAINER_KEY_EMPTY_META, ) where { R <: VariableType, S <: VariableType, @@ -1262,11 +1276,10 @@ function _add_generic_incremental_interpolation_constraint( names = [PSY.get_name(d) for d in devices] JuMPmodel = get_jump_model(container) - x_var = get_variable(container, R(), W()) - y_var = get_variable(container, S(), W()) - δ_var = get_variable(container, T(), W()) - z_var = get_variable(container, U(), W()) - num_segments = length(var_bkpts) - 1 + x_var = get_variable(container, R(), W) + y_var = get_variable(container, S(), W) + δ_var = get_variable(container, T(), W) + z_var = get_variable(container, U(), W) const_container_var = add_constraints_container!( container, @@ -1274,7 +1287,7 @@ function _add_generic_incremental_interpolation_constraint( W, names, time_steps; - meta = "pwl_variable", + meta = "$(meta)pwl_variable", ) const_container_function = add_constraints_container!( @@ -1283,11 +1296,14 @@ function _add_generic_incremental_interpolation_constraint( W, names, time_steps; - meta = "pwl_function", + meta = "$(meta)pwl_function", ) for d in devices name = PSY.get_name(d) + var_bkpts = dic_var_bkpts[name] + function_bkpts = dic_function_bkpts[name] + num_segments = length(var_bkpts) - 1 for t in time_steps const_container_var[name, t] = JuMP.@constraint( JuMPmodel, @@ -1319,14 +1335,189 @@ function add_constraints!( container::OptimizationContainer, ::Type{T}, devices::IS.FlattenIteratorWrapper{U}, - ::DeviceModel{U, V}, + model::DeviceModel{U, V}, ::NetworkModel{<:AbstractPTDFModel}, ) where { T <: InterpolationVoltageConstraints, U <: PSY.TwoTerminalHVDCDetailedLine, V <: HVDCTwoTerminalVSCLoss, } + dic_var_bkpts = Dict{String, Vector{Float64}}() + dic_function_bkpts = Dict{String, Vector{Float64}}() + num_segments = get_attribute(model, "voltage_segments") + for d in devices + name = PSY.get_name(d) + vmin, vmax = PSY.get_voltage_limits(d) + var_bkpts, function_bkpts = + _get_breakpoints_for_pwl_function(vmin, vmax, x -> x^2; num_segments) + dic_var_bkpts[name] = var_bkpts + dic_function_bkpts[name] = function_bkpts + end - # TODO + _add_generic_incremental_interpolation_constraint!( + container, + DCVoltageFrom(), + SquaredDCVoltageFrom(), + InterpolationSquaredVoltageVariableFrom(), + InterpolationBinarySquaredVoltageVariableFrom(), + InterpolationVoltageConstraints(), + devices, + dic_var_bkpts, + dic_function_bkpts; + meta = "from_", + ) + _add_generic_incremental_interpolation_constraint!( + container, + DCVoltageTo(), + SquaredDCVoltageTo(), + InterpolationSquaredVoltageVariableTo(), + InterpolationBinarySquaredVoltageVariableTo(), + InterpolationVoltageConstraints(), + devices, + dic_var_bkpts, + dic_function_bkpts; + meta = "to_", + ) + return +end +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + model::DeviceModel{U, V}, + ::NetworkModel{<:AbstractPTDFModel}, +) where { + T <: InterpolationCurrentConstraints, + U <: PSY.TwoTerminalHVDCDetailedLine, + V <: HVDCTwoTerminalVSCLoss, +} + dic_var_bkpts = Dict{String, Vector{Float64}}() + dic_function_bkpts = Dict{String, Vector{Float64}}() + num_segments = get_attribute(model, "current_segments") + for d in devices + name = PSY.get_name(d) + Imax = PSY.get_max_dc_current(d) + Imin = -Imax + var_bkpts, function_bkpts = + _get_breakpoints_for_pwl_function(Imin, Imax, x -> x^2; num_segments) + dic_var_bkpts[name] = var_bkpts + dic_function_bkpts[name] = function_bkpts + end + + _add_generic_incremental_interpolation_constraint!( + container, + ConverterCurrent(), + SquaredConverterCurrent(), + InterpolationSquaredCurrentVariable(), + InterpolationBinarySquaredCurrentVariable(), + InterpolationCurrentConstraints(), + devices, + dic_var_bkpts, + dic_function_bkpts, + ) + return +end + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + model::DeviceModel{U, V}, + ::NetworkModel{<:AbstractPTDFModel}, +) where { + T <: InterpolationBilinearConstraints, + U <: PSY.TwoTerminalHVDCDetailedLine, + V <: HVDCTwoTerminalVSCLoss, +} + dic_var_bkpts = Dict{String, Vector{Float64}}() + dic_function_bkpts = Dict{String, Vector{Float64}}() + num_segments = get_attribute(model, "bilinear_segments") + for d in devices + name = PSY.get_name(d) + vmin, vmax = PSY.get_voltage_limits(d) + Imax = PSY.get_max_dc_current(d) + Imin = -Imax + γ_min = vmin * Imin + γ_max = vmax * Imax + var_bkpts, function_bkpts = + _get_breakpoints_for_pwl_function(γ_min, γ_max, x -> x^2; num_segments) + dic_var_bkpts[name] = var_bkpts + dic_function_bkpts[name] = function_bkpts + end + + _add_generic_incremental_interpolation_constraint!( + container, + AuxBilinearConverterVariableFrom(), + AuxBilinearSquaredConverterVariableFrom(), + InterpolationSquaredBilinearVariableFrom(), + InterpolationBinarySquaredBilinearVariableFrom(), + InterpolationBilinearConstraints(), + devices, + dic_var_bkpts, + dic_function_bkpts; + meta = "from_", + ) + _add_generic_incremental_interpolation_constraint!( + container, + AuxBilinearConverterVariableTo(), + AuxBilinearSquaredConverterVariableTo(), + InterpolationSquaredBilinearVariableTo(), + InterpolationBinarySquaredBilinearVariableTo(), + InterpolationBilinearConstraints(), + devices, + dic_var_bkpts, + dic_function_bkpts; + meta = "to_", + ) + return +end + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:AbstractPTDFModel}, +) where { + T <: ConverterCurrentBalanceConstraint, + U <: PSY.TwoTerminalHVDCDetailedLine, + V <: HVDCTwoTerminalVSCLoss, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + JuMPmodel = get_jump_model(container) + # current vars # + current_var = get_variable(container, ConverterCurrent(), U) # From direction + # voltage vars # + from_voltage_var = get_variable(container, DCVoltageFrom(), U) + to_voltage_var = get_variable(container, DCVoltageTo(), U) + + constraint = add_constraints_container!( + container, + T(), + U, + names, + time_steps, + ) + + for d in devices + name = PSY.get_name(d) + g = PSY.get_g(d) + for t in time_steps + if g != 0.0 + constraint[name, t] = JuMP.@constraint( + JuMPmodel, + current_var[name, t] == + g * (from_voltage_var[name, t] - to_voltage_var[name, t]) + ) + else + constraint[name, t] = JuMP.@constraint( + JuMPmodel, + from_voltage_var[name, t] == to_voltage_var[name, t] + ) + end + end + end + return end From 84b8aa0188ed25ce6b513eff4fae768ea4ba9d1d Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 4 Nov 2024 15:52:28 -0800 Subject: [PATCH 13/34] add converter and losses constraints --- src/core/constraints.jl | 26 ++++ src/core/variables.jl | 6 + .../device_constructors/branch_constructor.jl | 23 ++- .../devices/TwoTerminalDC_branches.jl | 139 ++++++++++++++++++ 4 files changed, 191 insertions(+), 3 deletions(-) diff --git a/src/core/constraints.jl b/src/core/constraints.jl index 5e4ca7dfd..74a575aa3 100644 --- a/src/core/constraints.jl +++ b/src/core/constraints.jl @@ -502,3 +502,29 @@ The specified constraints are formulated as: ``` """ struct InterpolationBilinearConstraints <: ConstraintType end + +""" +Struct to create the constraints that set the absolute value for the current to use in 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} = i_c^+ - i_c^-, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& i_c^+ \\le I_max \\cdot \\nu_c, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& i_c^+ \\le I_max \\cdot (1 - \\nu_c), \\quad \\forall t \\in \\{1,\\dots, T\\} +\\end{align*} +``` +""" +struct CurrentAbsoluteValueConstraint <: ConstraintType end + +""" +Struct to create the constraints that set the losses for the converter to use in 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*} +& p_c^{loss} = a_c + b_c |i_c| + c_c i_c^2, \\quad \\forall t \\in \\{1,\\dots, T\\} +\\end{align*} +``` +""" +struct ConverterLossesCalculationConstraint <: ConstraintType end diff --git a/src/core/variables.jl b/src/core/variables.jl index 59ce7906d..d181b4aa0 100644 --- a/src/core/variables.jl +++ b/src/core/variables.jl @@ -224,6 +224,12 @@ Docs abbreviation: ``i_c^{-,dc}`` """ struct ConverterNegativeCurrent <: VariableType end +""" +Struct to dispatch the creation of DC Converter Absolute Value direction Term Current Variables for DC formulations +Docs abbreviation: ``\\nu_c^`` +""" +struct ConverterCurrentDirection <: VariableType end + """ Struct to dispatch the creation of DC Converter Binary for Absolute Value Current Variables for DC formulations Docs abbreviation: `\\nu_c`` diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index c4b991793..ac6c38dbb 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -925,9 +925,12 @@ function construct_device!( # Add Current Variables: i, δ^i, z^i, i+, i- add_variables!(container, ConverterCurrent, devices, V()) # i add_variables!(container, SquaredConverterCurrent, devices, V()) # i^sq - # TODO: Activate Abs Value method - #add_variables!(container, ConverterPositiveCurrent, devices, V()) # i^+ - #add_variables!(container, ConverterNegativeCurrent, devices, V()) # i^- + # Losses + add_variables!(container, ConverterPositiveCurrent, devices, V()) # i^+ + add_variables!(container, ConverterNegativeCurrent, devices, V()) # i^- + add_variables!(container, ConverterCurrentDirection, devices, V()) + add_variables!(container, HVDCLosses, devices, V()) + add_variables!( container, ConverterBinaryAbsoluteValueCurrent, @@ -1047,6 +1050,20 @@ function construct_device!( model, network_model, ) + add_constraints!( + container, + CurrentAbsoluteValueConstraint, + devices, + model, + network_model, + ) + add_constraints!( + container, + ConverterLossesCalculationConstraint, + devices, + model, + network_model, + ) #error("here") add_feedforward_constraints!(container, model, devices) diff --git a/src/devices_models/devices/TwoTerminalDC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl index 80157716c..366659194 100644 --- a/src/devices_models/devices/TwoTerminalDC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -47,6 +47,11 @@ get_variable_binary( ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, ::HVDCTwoTerminalVSCLoss, ) = true +get_variable_binary( + ::ConverterCurrentDirection, + ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::HVDCTwoTerminalVSCLoss, +) = true get_variable_multiplier(::FlowActivePowerVariable, ::Type{<:PSY.TwoTerminalHVDCLine}, _) = NaN @@ -224,6 +229,12 @@ get_variable_lower_bound( ::HVDCTwoTerminalVSCLoss, ) = 0.0 +get_variable_lower_bound( + ::Union{ConverterPositiveCurrent, ConverterNegativeCurrent}, + d::PSY.TwoTerminalHVDCDetailedLine, + ::HVDCTwoTerminalVSCLoss, +) = 0.0 + get_variable_upper_bound( ::Union{ InterpolationSquaredVoltageVariableFrom, @@ -1521,3 +1532,131 @@ function add_constraints!( end return end + +####### Absolute Value for Current ######### + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:AbstractPTDFModel}, +) where { + T <: CurrentAbsoluteValueConstraint, + U <: PSY.TwoTerminalHVDCDetailedLine, + V <: HVDCTwoTerminalVSCLoss, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + JuMPmodel = get_jump_model(container) + # current vars # + current_var = get_variable(container, ConverterCurrent(), U) # From direction + current_var_pos = get_variable(container, ConverterPositiveCurrent(), U) # From direction + current_var_neg = get_variable(container, ConverterNegativeCurrent(), U) # From direction + current_dir = get_variable(container, ConverterCurrentDirection(), U) + + constraint = + add_constraints_container!( + container, + CurrentAbsoluteValueConstraint(), + U, + names, + time_steps, + ) + constraint_pos_ub = + add_constraints_container!( + container, + CurrentAbsoluteValueConstraint(), + U, + names, + time_steps; + meta = "pos_ub", + ) + constraint_neg_ub = + add_constraints_container!( + container, + CurrentAbsoluteValueConstraint(), + U, + names, + time_steps; + meta = "neg_ub", + ) + + for d in devices + name = PSY.get_name(d) + I_max = PSY.get_max_dc_current(d) + for t in time_steps + constraint[name, t] = JuMP.@constraint( + JuMPmodel, + current_var[name, t] == current_var_pos[name, t] - current_var_neg[name, t] + ) + constraint_pos_ub[name, t] = JuMP.@constraint( + JuMPmodel, + current_var_pos[name, t] <= I_max * current_dir[name, t] + ) + constraint_neg_ub[name, t] = JuMP.@constraint( + JuMPmodel, + current_var_neg[name, t] <= I_max * (1 - current_dir[name, t]) + ) + end + end + return +end + +function _get_converter_loss_terms(loss::PSY.LinearCurve) + a = PSY.get_constant_term(loss) + b = PSY.get_proportional_term(loss) + return (a, b, 0.0) +end + +function _get_converter_loss_terms(loss::PSY.QuadraticCurve) + a = PSY.get_constant_term(loss) + b = PSY.get_proportional_term(loss) + c = PSY.get_quadratic_term(loss) + return (a, b, c) +end + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:AbstractPTDFModel}, +) where { + T <: ConverterLossesCalculationConstraint, + U <: PSY.TwoTerminalHVDCDetailedLine, + V <: HVDCTwoTerminalVSCLoss, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + JuMPmodel = get_jump_model(container) + # current vars # + losses_var = get_variable(container, HVDCLosses(), U) # From direction + current_var_pos = get_variable(container, ConverterPositiveCurrent(), U) # From direction + current_var_neg = get_variable(container, ConverterNegativeCurrent(), U) # From direction + current_sq_var = get_variable(container, SquaredConverterCurrent(), U) + + constraint = + add_constraints_container!( + container, + ConverterLossesCalculationConstraint(), + U, + names, + time_steps, + ) + + for d in devices + name = PSY.get_name(d) + loss = PSY.get_converter_loss(d) + a, b, c = _get_converter_loss_terms(loss) + for t in time_steps + constraint[name, t] = JuMP.@constraint( + JuMPmodel, + losses_var[name, t] == + a + b * (current_var_pos[name, t] + current_var_neg[name, t]) + + c * current_sq_var[name, t] + ) + end + end + return +end From 5dc59d1cd1866ec72db8bdd6b441b8bf26423e6d Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Tue, 5 Nov 2024 09:50:47 -0800 Subject: [PATCH 14/34] update name of variable to DC send --- src/core/variables.jl | 20 +++-- .../device_constructors/branch_constructor.jl | 15 +--- .../devices/TwoTerminalDC_branches.jl | 50 +++++++++--- .../devices/common/add_to_expression.jl | 78 ++++++++++++++++++- 4 files changed, 133 insertions(+), 30 deletions(-) diff --git a/src/core/variables.jl b/src/core/variables.jl index d181b4aa0..0f1400536 100644 --- a/src/core/variables.jl +++ b/src/core/variables.jl @@ -230,12 +230,6 @@ Docs abbreviation: ``\\nu_c^`` """ struct ConverterCurrentDirection <: 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}`` @@ -338,6 +332,20 @@ Docs abbreviation: ``z_c^{\\gamma}`` """ struct InterpolationBinarySquaredBilinearVariableTo <: SparseVariableType end +""" +Struct to dispatch the creation of HVDC Received Flow at From Bus Variables for PWL formulations + +Docs abbreviation: ``x`` +""" +struct HVDCActiveDCPowerSentFromVariable <: VariableType end + +""" +Struct to dispatch the creation of HVDC Received Flow at To Bus Variables for PWL formulations + +Docs abbreviation: ``y`` +""" +struct HVDCActiveDCPowerSentToVariable <: VariableType end + """ Struct to dispatch the creation of bidirectional Active Power Flow Variables diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index ac6c38dbb..617e0237c 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -913,8 +913,8 @@ function construct_device!( ##################### V = HVDCTwoTerminalVSCLoss # Add Power Variable - add_variables!(container, HVDCActivePowerReceivedFromVariable, devices, V()) # p_c^{ac,from} - add_variables!(container, HVDCActivePowerReceivedToVariable, devices, V()) # p_c^{ac,from} + add_variables!(container, HVDCActiveDCPowerSentFromVariable, devices, V()) # p_c^{ac,from} + add_variables!(container, HVDCActiveDCPowerSentToVariable, devices, V()) # p_c^{ac,from} add_variables!(container, ConverterPowerDirection, devices, V()) #κ # Add Voltage Variables: v_dc, v^sq, δ^v, z^v add_variables!(container, DCVoltageFrom, devices, V()) # v_dc^{from} @@ -931,13 +931,6 @@ function construct_device!( add_variables!(container, ConverterCurrentDirection, devices, V()) add_variables!(container, HVDCLosses, devices, V()) - add_variables!( - container, - ConverterBinaryAbsoluteValueCurrent, - devices, - V(), - ) # ν - # Add Bilinear Variables: γ, γ^{sq} add_variables!( container, @@ -973,7 +966,7 @@ function construct_device!( add_to_expression!( container, ActivePowerBalance, - HVDCActivePowerReceivedFromVariable, + HVDCActiveDCPowerSentFromVariable, devices, model, network_model, @@ -982,7 +975,7 @@ function construct_device!( add_to_expression!( container, ActivePowerBalance, - HVDCActivePowerReceivedToVariable, + HVDCActiveDCPowerSentToVariable, devices, model, network_model, diff --git a/src/devices_models/devices/TwoTerminalDC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl index 366659194..3bda3b18d 100644 --- a/src/devices_models/devices/TwoTerminalDC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -18,7 +18,28 @@ get_variable_binary( ) = true get_variable_binary( - _, + ::Union{ + HVDCActiveDCPowerSentFromVariable, + HVDCActiveDCPowerSentToVariable, + DCVoltageFrom, + DCVoltageTo, + SquaredDCVoltageFrom, + SquaredDCVoltageTo, + ConverterCurrent, + SquaredConverterCurrent, + ConverterPositiveCurrent, + ConverterNegativeCurrent, + HVDCLosses, + AuxBilinearConverterVariableFrom, + AuxBilinearSquaredConverterVariableFrom, + AuxBilinearConverterVariableTo, + AuxBilinearSquaredConverterVariableTo, + InterpolationSquaredVoltageVariableFrom, + InterpolationSquaredVoltageVariableTo, + InterpolationSquaredCurrentVariable, + InterpolationSquaredBilinearVariableFrom, + InterpolationSquaredBilinearVariableTo, + }, ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, ::HVDCTwoTerminalVSCLoss, ) = false @@ -32,6 +53,11 @@ get_variable_binary( ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, ::HVDCTwoTerminalVSCLoss, ) = true +get_variable_binary( + ::InterpolationBinarySquaredCurrentVariable, + ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::HVDCTwoTerminalVSCLoss, +) = true get_variable_binary( ::InterpolationBinarySquaredBilinearVariableFrom, ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, @@ -149,25 +175,25 @@ get_variable_lower_bound( ) = PSY.get_active_power_limits_to(d).min get_variable_upper_bound( - ::HVDCActivePowerReceivedFromVariable, + ::Union{HVDCActivePowerReceivedFromVariable, HVDCActiveDCPowerSentFromVariable}, d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalHVDCDetailedLine}, ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_from(d).max get_variable_lower_bound( - ::HVDCActivePowerReceivedFromVariable, + ::Union{HVDCActivePowerReceivedFromVariable, HVDCActiveDCPowerSentFromVariable}, d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalHVDCDetailedLine}, ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_from(d).min get_variable_upper_bound( - ::HVDCActivePowerReceivedToVariable, + ::Union{HVDCActivePowerReceivedToVariable, HVDCActiveDCPowerSentToVariable}, d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalHVDCDetailedLine}, ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_to(d).max get_variable_lower_bound( - ::HVDCActivePowerReceivedToVariable, + ::Union{HVDCActivePowerReceivedToVariable, HVDCActiveDCPowerSentToVariable}, d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalHVDCDetailedLine}, ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_to(d).min @@ -613,6 +639,8 @@ function _add_hvdc_flow_constraints!( FlowActivePowerToFromVariable, HVDCActivePowerReceivedFromVariable, HVDCActivePowerReceivedToVariable, + HVDCActiveDCPowerSentFromVariable, + HVDCActiveDCPowerSentToVariable, }, constraint::Union{FlowRateConstraintFromTo, FlowRateConstraintToFrom}, ) where {T <: PSY.TwoTerminalHVDCLine} @@ -896,8 +924,8 @@ function add_constraints!( time_steps = get_time_steps(container) names = [PSY.get_name(d) for d in devices] # power vars # - from_power_var = get_variable(container, HVDCActivePowerReceivedFromVariable(), U) - to_power_var = get_variable(container, HVDCActivePowerReceivedToVariable(), U) + from_power_var = get_variable(container, HVDCActiveDCPowerSentFromVariable(), U) + to_power_var = get_variable(container, HVDCActiveDCPowerSentToVariable(), U) # voltage vars # from_voltage_var = get_variable(container, DCVoltageFrom(), U) to_voltage_var = get_variable(container, DCVoltageTo(), U) @@ -994,8 +1022,8 @@ function add_constraints!( names = [PSY.get_name(d) for d in devices] JuMPmodel = get_jump_model(container) # power vars # - from_power_var = get_variable(container, HVDCActivePowerReceivedFromVariable(), U) - to_power_var = get_variable(container, HVDCActivePowerReceivedToVariable(), U) + from_power_var = get_variable(container, HVDCActiveDCPowerSentFromVariable(), U) + to_power_var = get_variable(container, HVDCActiveDCPowerSentToVariable(), U) # current vars # current_var = get_variable(container, ConverterCurrent(), U) # From direction direction_var = get_variable(container, ConverterPowerDirection(), U) @@ -1099,8 +1127,8 @@ function add_constraints!( names = [PSY.get_name(d) for d in devices] JuMPmodel = get_jump_model(container) # power vars # - from_power_var = get_variable(container, HVDCActivePowerReceivedFromVariable(), U) - to_power_var = get_variable(container, HVDCActivePowerReceivedToVariable(), U) + from_power_var = get_variable(container, HVDCActiveDCPowerSentFromVariable(), U) + to_power_var = get_variable(container, HVDCActiveDCPowerSentToVariable(), U) # current vars # current_var = get_variable(container, ConverterCurrent(), U) # From direction # voltage vars # diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index 16c1e23ba..d6ad6f3db 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -393,7 +393,7 @@ function add_to_expression!( T <: ActivePowerBalance, U <: HVDCActivePowerReceivedFromVariable, V <: TwoTerminalHVDCTypes, - W <: Union{HVDCTwoTerminalPiecewiseLoss, HVDCTwoTerminalVSCLoss}, + W <: HVDCTwoTerminalPiecewiseLoss, X <: AbstractPTDFModel, } var = get_variable(container, U(), V) @@ -430,7 +430,7 @@ function add_to_expression!( T <: ActivePowerBalance, U <: HVDCActivePowerReceivedToVariable, V <: TwoTerminalHVDCTypes, - W <: Union{HVDCTwoTerminalPiecewiseLoss, HVDCTwoTerminalVSCLoss}, + W <: HVDCTwoTerminalPiecewiseLoss, X <: AbstractPTDFModel, } var = get_variable(container, U(), V) @@ -453,6 +453,80 @@ function add_to_expression!( return end +""" +PWL implementation to add FromTo branch variables to SystemBalanceExpressions +""" +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 <: HVDCActiveDCPowerSentFromVariable, + V <: TwoTerminalHVDCTypes, + W <: HVDCTwoTerminalVSCLoss, + X <: AbstractPTDFModel, +} + var = get_variable(container, U(), V) + nodal_expr = get_expression(container, T(), PSY.ACBus) + sys_expr = get_expression(container, T(), _system_expression_type(X)) + radial_network_reduction = get_radial_network_reduction(network_model) + for d in devices + bus_no_from = + PNM.get_mapped_bus_number(radial_network_reduction, PSY.get_arc(d).from) + ref_bus_to = get_reference_bus(network_model, PSY.get_arc(d).to) + ref_bus_from = get_reference_bus(network_model, PSY.get_arc(d).from) + for t in get_time_steps(container) + flow_variable = var[PSY.get_name(d), t] + _add_to_jump_expression!(nodal_expr[bus_no_from, t], flow_variable, -1.0) + if ref_bus_from != ref_bus_to + _add_to_jump_expression!(sys_expr[ref_bus_from, t], flow_variable, -1.0) + end + end + end + return +end + +""" +PWL implementation to add FromTo branch variables to SystemBalanceExpressions +""" +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 <: HVDCActiveDCPowerSentToVariable, + V <: TwoTerminalHVDCTypes, + W <: HVDCTwoTerminalVSCLoss, + X <: AbstractPTDFModel, +} + var = get_variable(container, U(), V) + nodal_expr = get_expression(container, T(), PSY.ACBus) + sys_expr = get_expression(container, T(), _system_expression_type(X)) + radial_network_reduction = get_radial_network_reduction(network_model) + for d in devices + bus_no_to = + PNM.get_mapped_bus_number(radial_network_reduction, PSY.get_arc(d).to) + ref_bus_to = get_reference_bus(network_model, PSY.get_arc(d).to) + ref_bus_from = get_reference_bus(network_model, PSY.get_arc(d).from) + for t in get_time_steps(container) + flow_variable = var[PSY.get_name(d), t] + _add_to_jump_expression!(nodal_expr[bus_no_to, t], flow_variable, -1.0) + if ref_bus_from != ref_bus_to + _add_to_jump_expression!(sys_expr[ref_bus_to, t], flow_variable, -1.0) + end + end + end + return +end + """ Default implementation to add branch variables to SystemBalanceExpressions """ From 8446e26441f04262eaf2517b75c934025240264e Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Tue, 5 Nov 2024 10:10:46 -0800 Subject: [PATCH 15/34] add exports --- src/PowerSimulations.jl | 18 +++++++++++++++++- .../device_constructors/branch_constructor.jl | 1 - 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/PowerSimulations.jl b/src/PowerSimulations.jl index 0a36addcd..8aaa83166 100644 --- a/src/PowerSimulations.jl +++ b/src/PowerSimulations.jl @@ -233,6 +233,23 @@ export LowerBoundFeedForwardSlack export InterfaceFlowSlackUp export InterfaceFlowSlackDown export PieceWiseLinearCostVariable +export HVDCActiveDCPowerSentFromVariable +export HVDCActiveDCPowerSentToVariable +export ConverterPowerDirection +export DCVoltageFrom +export DCVoltageTo +export SquaredDCVoltageFrom +export SquaredDCVoltageTo +export ConverterCurrent +export SquaredConverterCurrent +export ConverterPositiveCurrent +export ConverterNegativeCurrent +export ConverterCurrentDirection +export HVDCLosses +export AuxBilinearConverterVariableFrom +export AuxBilinearSquaredConverterVariableFrom +export AuxBilinearConverterVariableTo +export AuxBilinearSquaredConverterVariableTo # Auxiliary variables export TimeDurationOn @@ -270,7 +287,6 @@ export FlowReactivePowerFromToConstraint export FlowReactivePowerToFromConstraint export FrequencyResponseConstraint export HVDCPowerBalance -export HVDCLosses export HVDCFlowDirectionVariable export InputActivePowerVariableLimitsConstraint export NetworkFlowConstraint diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index 617e0237c..dee32f0e2 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -1057,7 +1057,6 @@ function construct_device!( model, network_model, ) - #error("here") add_feedforward_constraints!(container, model, devices) objective_function!(container, devices, model, get_network_formulation(network_model)) From c67f721ff9eeef1e076cc71f0877407558b191b0 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Tue, 5 Nov 2024 13:01:21 -0800 Subject: [PATCH 16/34] add tests --- src/PowerSimulations.jl | 1 + test/test_device_branch_constructors.jl | 65 +++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/src/PowerSimulations.jl b/src/PowerSimulations.jl index 8aaa83166..0985a0905 100644 --- a/src/PowerSimulations.jl +++ b/src/PowerSimulations.jl @@ -45,6 +45,7 @@ export HVDCTwoTerminalLossless export HVDCTwoTerminalDispatch export HVDCTwoTerminalUnbounded export PhaseAngleControl +export HVDCTwoTerminalVSCLoss # export VoltageSourceDC ######## HVDC models ######## diff --git a/test/test_device_branch_constructors.jl b/test/test_device_branch_constructors.jl index 289b2915a..8f4cb45cc 100644 --- a/test/test_device_branch_constructors.jl +++ b/test/test_device_branch_constructors.jl @@ -728,3 +728,68 @@ end # some relaxations will find a solution with 0.0 slack @test sum(vars[!, "2"]) >= -1e-6 end + +@testset "HVDC VSC Loss Model" begin + c_sys5 = PSB.build_system(PSISystems, "2Area 5 Bus System") + thermal_names = ["Solitude", "Park City", "Alta", "Brighton"] + for name in thermal_names + thermal = get_component(ThermalStandard, c_sys5, name) + op_cost = get_operation_cost(thermal) + new_opcost = ThermalGenerationCost(; + variable = CostCurve(; + value_curve = PSY.QuadraticCurve( + 0.0, + get_proportional_term(op_cost.variable.value_curve) / 2.0, + 0.0, + ), + power_units = UnitSystem.NATURAL_UNITS, + ), + fixed = op_cost.fixed, + start_up = op_cost.start_up, + shut_down = op_cost.shut_down, + ) + set_operation_cost!(thermal, new_opcost) + end + + hvdc = first(get_components(TwoTerminalHVDCLine, c_sys5)) + + hvdc_new = TwoTerminalHVDCDetailedLine(; + name = get_name(hvdc), + available = get_available(hvdc), + active_power_flow = get_active_power_flow(hvdc), + rating = 2.0, + active_power_limits_from = (min = -2.0, max = 2.0), + active_power_limits_to = (min = -2.0, max = 2.0), + arc = get_arc(hvdc), + converter_loss = QuadraticCurve(0.0001, 0.01, 0.0), + dc_current = 0.0, + max_dc_current = 3.0, + g = 50.0, # r = 0.02 + voltage_limits = (min = 0.9, max = 1.1), + ) + remove_component!(c_sys5, hvdc) + add_component!(c_sys5, hvdc_new) + + template = get_thermal_dispatch_template_network(NetworkModel(PTDFPowerModel)) + dev_model = DeviceModel( + TwoTerminalHVDCDetailedLine, + PSI.HVDCTwoTerminalVSCLoss; + attributes = Dict{String, Any}( + "voltage_segments" => 10, + "current_segments" => 10, + "bilinear_segments" => 10, + ), + ) + set_device_model!(template, dev_model) + ps_model = DecisionModel( + template, + c_sys5; + optimizer = HiGHS_optimizer, + store_variable_names = true, + horizon = Hour(2), + ) + @test build!(ps_model; output_dir = mktempdir(; cleanup = true)) == + PSI.ModelBuildStatus.BUILT + moi_tests(ps_model, 268, 0, 152, 148, 62, true) + @test solve!(ps_model) == PSI.RunStatus.SUCCESSFULLY_FINALIZED +end From b92b65188b908536b8468b14c9a9c37b648bb52e Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Wed, 6 Nov 2024 12:21:49 -0800 Subject: [PATCH 17/34] add losses to power balance --- src/core/definitions.jl | 2 +- .../device_constructors/branch_constructor.jl | 12 +++- .../devices/TwoTerminalDC_branches.jl | 60 +++++++++---------- .../devices/common/add_to_expression.jl | 38 ++++++++++++ test/test_device_branch_constructors.jl | 4 +- 5 files changed, 81 insertions(+), 35 deletions(-) diff --git a/src/core/definitions.jl b/src/core/definitions.jl index e6bc76347..1376e7d94 100644 --- a/src/core/definitions.jl +++ b/src/core/definitions.jl @@ -40,7 +40,7 @@ const JuMPVariableArray = DenseAxisArray{JuMP.VariableRef} const TwoTerminalHVDCTypes = Union{ PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCDCLine, - PSY.TwoTerminalHVDCDetailedLine, + PSY.TwoTerminalVSCLine, } # Settings constants const UNSET_HORIZON = Dates.Millisecond(0) diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index dee32f0e2..6cf32a5c6 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -903,7 +903,7 @@ function construct_device!( container::OptimizationContainer, sys::PSY.System, ::ArgumentConstructStage, - model::DeviceModel{PSY.TwoTerminalHVDCDetailedLine, HVDCTwoTerminalVSCLoss}, + model::DeviceModel{PSY.TwoTerminalVSCLine, HVDCTwoTerminalVSCLoss}, network_model::NetworkModel{<:PM.AbstractActivePowerModel}, ) devices = get_available_components(model, sys) @@ -980,6 +980,14 @@ function construct_device!( model, network_model, ) + add_to_expression!( + container, + ActivePowerBalance, + HVDCLosses, + devices, + model, + network_model, + ) # TODO: Add losses to balance expression to get full AC add_feedforward_arguments!(container, model, devices) return @@ -989,7 +997,7 @@ function construct_device!( container::OptimizationContainer, sys::PSY.System, ::ModelConstructStage, - model::DeviceModel{PSY.TwoTerminalHVDCDetailedLine, HVDCTwoTerminalVSCLoss}, + model::DeviceModel{PSY.TwoTerminalVSCLine, HVDCTwoTerminalVSCLoss}, network_model::NetworkModel{<:PM.AbstractActivePowerModel}, ) devices = get_available_components(model, sys) diff --git a/src/devices_models/devices/TwoTerminalDC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl index 3bda3b18d..e37c81848 100644 --- a/src/devices_models/devices/TwoTerminalDC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -40,42 +40,42 @@ get_variable_binary( InterpolationSquaredBilinearVariableFrom, InterpolationSquaredBilinearVariableTo, }, - ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::Type{<:PSY.TwoTerminalVSCLine}, ::HVDCTwoTerminalVSCLoss, ) = false get_variable_binary( ::InterpolationBinarySquaredVoltageVariableFrom, - ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::Type{<:PSY.TwoTerminalVSCLine}, ::HVDCTwoTerminalVSCLoss, ) = true get_variable_binary( ::InterpolationBinarySquaredVoltageVariableTo, - ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::Type{<:PSY.TwoTerminalVSCLine}, ::HVDCTwoTerminalVSCLoss, ) = true get_variable_binary( ::InterpolationBinarySquaredCurrentVariable, - ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::Type{<:PSY.TwoTerminalVSCLine}, ::HVDCTwoTerminalVSCLoss, ) = true get_variable_binary( ::InterpolationBinarySquaredBilinearVariableFrom, - ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::Type{<:PSY.TwoTerminalVSCLine}, ::HVDCTwoTerminalVSCLoss, ) = true get_variable_binary( ::InterpolationBinarySquaredBilinearVariableTo, - ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::Type{<:PSY.TwoTerminalVSCLine}, ::HVDCTwoTerminalVSCLoss, ) = true get_variable_binary( ::ConverterPowerDirection, - ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::Type{<:PSY.TwoTerminalVSCLine}, ::HVDCTwoTerminalVSCLoss, ) = true get_variable_binary( ::ConverterCurrentDirection, - ::Type{<:PSY.TwoTerminalHVDCDetailedLine}, + ::Type{<:PSY.TwoTerminalVSCLine}, ::HVDCTwoTerminalVSCLoss, ) = true @@ -176,25 +176,25 @@ get_variable_lower_bound( get_variable_upper_bound( ::Union{HVDCActivePowerReceivedFromVariable, HVDCActiveDCPowerSentFromVariable}, - d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalHVDCDetailedLine}, + d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCLine}, ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_from(d).max get_variable_lower_bound( ::Union{HVDCActivePowerReceivedFromVariable, HVDCActiveDCPowerSentFromVariable}, - d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalHVDCDetailedLine}, + d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCLine}, ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_from(d).min get_variable_upper_bound( ::Union{HVDCActivePowerReceivedToVariable, HVDCActiveDCPowerSentToVariable}, - d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalHVDCDetailedLine}, + d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCLine}, ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_to(d).max get_variable_lower_bound( ::Union{HVDCActivePowerReceivedToVariable, HVDCActiveDCPowerSentToVariable}, - d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalHVDCDetailedLine}, + d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCLine}, ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_to(d).min @@ -233,31 +233,31 @@ get_variable_lower_bound( ### Two Terminal Physical Loss ### get_variable_upper_bound( ::Union{DCVoltageFrom, DCVoltageTo}, - d::PSY.TwoTerminalHVDCDetailedLine, + d::PSY.TwoTerminalVSCLine, ::HVDCTwoTerminalVSCLoss, ) = PSY.get_voltage_limits(d).max get_variable_lower_bound( ::Union{DCVoltageFrom, DCVoltageTo}, - d::PSY.TwoTerminalHVDCDetailedLine, + d::PSY.TwoTerminalVSCLine, ::HVDCTwoTerminalVSCLoss, ) = PSY.get_voltage_limits(d).min get_variable_upper_bound( ::Union{SquaredDCVoltageFrom, SquaredDCVoltageTo}, - d::PSY.TwoTerminalHVDCDetailedLine, + d::PSY.TwoTerminalVSCLine, ::HVDCTwoTerminalVSCLoss, ) = PSY.get_voltage_limits(d).max^2 get_variable_lower_bound( ::Union{SquaredDCVoltageFrom, SquaredDCVoltageTo}, - d::PSY.TwoTerminalHVDCDetailedLine, + d::PSY.TwoTerminalVSCLine, ::HVDCTwoTerminalVSCLoss, ) = 0.0 get_variable_lower_bound( ::Union{ConverterPositiveCurrent, ConverterNegativeCurrent}, - d::PSY.TwoTerminalHVDCDetailedLine, + d::PSY.TwoTerminalVSCLine, ::HVDCTwoTerminalVSCLoss, ) = 0.0 @@ -269,7 +269,7 @@ get_variable_upper_bound( InterpolationSquaredBilinearVariableFrom, InterpolationSquaredBilinearVariableTo, }, - d::PSY.TwoTerminalHVDCDetailedLine, + d::PSY.TwoTerminalVSCLine, ::HVDCTwoTerminalVSCLoss, ) = 1.0 @@ -281,7 +281,7 @@ get_variable_lower_bound( InterpolationSquaredBilinearVariableFrom, InterpolationSquaredBilinearVariableTo, }, - d::PSY.TwoTerminalHVDCDetailedLine, + d::PSY.TwoTerminalVSCLine, ::HVDCTwoTerminalVSCLoss, ) = 0.0 @@ -302,7 +302,7 @@ end function get_default_attributes( ::Type{U}, ::Type{V}, -) where {U <: PSY.TwoTerminalHVDCDetailedLine, V <: HVDCTwoTerminalVSCLoss} +) where {U <: PSY.TwoTerminalVSCLine, V <: HVDCTwoTerminalVSCLoss} return Dict{String, Any}( "voltage_segments" => 3, "current_segments" => 6, @@ -322,7 +322,7 @@ function _add_sparse_pwl_interpolation_variables!( container::OptimizationContainer, devices, model::DeviceModel{D, HVDCTwoTerminalVSCLoss}, -) where {D <: PSY.TwoTerminalHVDCDetailedLine} +) where {D <: PSY.TwoTerminalVSCLine} # TODO: Implement approach for deciding segment length # Create Variables time_steps = get_time_steps(container) @@ -918,7 +918,7 @@ function add_constraints!( ::NetworkModel{<:AbstractPTDFModel}, ) where { T <: ConverterPowerCalculationConstraint, - U <: PSY.TwoTerminalHVDCDetailedLine, + U <: PSY.TwoTerminalVSCLine, V <: HVDCTwoTerminalVSCLoss, } time_steps = get_time_steps(container) @@ -1015,7 +1015,7 @@ function add_constraints!( ::NetworkModel{<:AbstractPTDFModel}, ) where { T <: ConverterDirectionConstraint, - U <: PSY.TwoTerminalHVDCDetailedLine, + U <: PSY.TwoTerminalVSCLine, V <: HVDCTwoTerminalVSCLoss, } time_steps = get_time_steps(container) @@ -1120,7 +1120,7 @@ function add_constraints!( ::NetworkModel{<:AbstractPTDFModel}, ) where { T <: ConverterMcCormickEnvelopes, - U <: PSY.TwoTerminalHVDCDetailedLine, + U <: PSY.TwoTerminalVSCLine, V <: HVDCTwoTerminalVSCLoss, } time_steps = get_time_steps(container) @@ -1378,7 +1378,7 @@ function add_constraints!( ::NetworkModel{<:AbstractPTDFModel}, ) where { T <: InterpolationVoltageConstraints, - U <: PSY.TwoTerminalHVDCDetailedLine, + U <: PSY.TwoTerminalVSCLine, V <: HVDCTwoTerminalVSCLoss, } dic_var_bkpts = Dict{String, Vector{Float64}}() @@ -1428,7 +1428,7 @@ function add_constraints!( ::NetworkModel{<:AbstractPTDFModel}, ) where { T <: InterpolationCurrentConstraints, - U <: PSY.TwoTerminalHVDCDetailedLine, + U <: PSY.TwoTerminalVSCLine, V <: HVDCTwoTerminalVSCLoss, } dic_var_bkpts = Dict{String, Vector{Float64}}() @@ -1466,7 +1466,7 @@ function add_constraints!( ::NetworkModel{<:AbstractPTDFModel}, ) where { T <: InterpolationBilinearConstraints, - U <: PSY.TwoTerminalHVDCDetailedLine, + U <: PSY.TwoTerminalVSCLine, V <: HVDCTwoTerminalVSCLoss, } dic_var_bkpts = Dict{String, Vector{Float64}}() @@ -1520,7 +1520,7 @@ function add_constraints!( ::NetworkModel{<:AbstractPTDFModel}, ) where { T <: ConverterCurrentBalanceConstraint, - U <: PSY.TwoTerminalHVDCDetailedLine, + U <: PSY.TwoTerminalVSCLine, V <: HVDCTwoTerminalVSCLoss, } time_steps = get_time_steps(container) @@ -1571,7 +1571,7 @@ function add_constraints!( ::NetworkModel{<:AbstractPTDFModel}, ) where { T <: CurrentAbsoluteValueConstraint, - U <: PSY.TwoTerminalHVDCDetailedLine, + U <: PSY.TwoTerminalVSCLine, V <: HVDCTwoTerminalVSCLoss, } time_steps = get_time_steps(container) @@ -1652,7 +1652,7 @@ function add_constraints!( ::NetworkModel{<:AbstractPTDFModel}, ) where { T <: ConverterLossesCalculationConstraint, - U <: PSY.TwoTerminalHVDCDetailedLine, + U <: PSY.TwoTerminalVSCLine, V <: HVDCTwoTerminalVSCLoss, } time_steps = get_time_steps(container) diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index d6ad6f3db..fd8ef08b8 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -527,6 +527,44 @@ function add_to_expression!( 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 <: HVDCLosses, + V <: TwoTerminalHVDCTypes, + W <: HVDCTwoTerminalVSCLoss, + X <: AbstractPTDFModel, +} + var = get_variable(container, U(), V) + nodal_expr = get_expression(container, T(), PSY.ACBus) + sys_expr = get_expression(container, T(), _system_expression_type(X)) + radial_network_reduction = get_radial_network_reduction(network_model) + for d in devices + bus_no_from = + PNM.get_mapped_bus_number(radial_network_reduction, PSY.get_arc(d).from) + bus_no_to = + PNM.get_mapped_bus_number(radial_network_reduction, PSY.get_arc(d).to) + ref_bus_to = get_reference_bus(network_model, PSY.get_arc(d).to) + ref_bus_from = get_reference_bus(network_model, PSY.get_arc(d).from) + for t in get_time_steps(container) + losses_variable = var[PSY.get_name(d), t] + _add_to_jump_expression!(nodal_expr[bus_no_from, t], losses_variable, -1.0) + _add_to_jump_expression!(nodal_expr[bus_no_to, t], losses_variable, -1.0) + if ref_bus_from != ref_bus_to + _add_to_jump_expression!(sys_expr[ref_bus_from, t], losses_variable, -1.0) + _add_to_jump_expression!(sys_expr[ref_bus_to, t], losses_variable, -1.0) + end + end + end + return +end + """ Default implementation to add branch variables to SystemBalanceExpressions """ diff --git a/test/test_device_branch_constructors.jl b/test/test_device_branch_constructors.jl index 8f4cb45cc..e6128448e 100644 --- a/test/test_device_branch_constructors.jl +++ b/test/test_device_branch_constructors.jl @@ -753,7 +753,7 @@ end hvdc = first(get_components(TwoTerminalHVDCLine, c_sys5)) - hvdc_new = TwoTerminalHVDCDetailedLine(; + hvdc_new = TwoTerminalVSCLine(; name = get_name(hvdc), available = get_available(hvdc), active_power_flow = get_active_power_flow(hvdc), @@ -772,7 +772,7 @@ end template = get_thermal_dispatch_template_network(NetworkModel(PTDFPowerModel)) dev_model = DeviceModel( - TwoTerminalHVDCDetailedLine, + TwoTerminalVSCLine, PSI.HVDCTwoTerminalVSCLoss; attributes = Dict{String, Any}( "voltage_segments" => 10, From 03fac9b239457237962263d6639e9de4f6828bb3 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Wed, 6 Nov 2024 12:39:31 -0800 Subject: [PATCH 18/34] add expressions for AC power --- src/core/expressions.jl | 4 ++ .../device_constructors/branch_constructor.jl | 45 +++++++++++++++++++ .../devices/common/add_to_expression.jl | 30 +++++++++++++ 3 files changed, 79 insertions(+) diff --git a/src/core/expressions.jl b/src/core/expressions.jl index f5ad354a7..5b957cc7b 100644 --- a/src/core/expressions.jl +++ b/src/core/expressions.jl @@ -12,6 +12,8 @@ struct ActivePowerRangeExpressionLB <: RangeConstraintLBExpressions end struct ActivePowerRangeExpressionUB <: RangeConstraintUBExpressions end struct ComponentReserveUpBalanceExpression <: ExpressionType end struct ComponentReserveDownBalanceExpression <: ExpressionType end +struct ReceivedHVDCActivePowerFromExpression <: ExpressionType end +struct ReceivedHVDCActivePowerToExpression <: ExpressionType end struct InterfaceTotalFlow <: ExpressionType end struct PTDFBranchFlow <: ExpressionType end @@ -20,5 +22,7 @@ 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{ReceivedHVDCActivePowerFromExpression}) = true +should_write_resulting_value(::Type{ReceivedHVDCActivePowerToExpression}) = true convert_result_to_natural_units(::Type{InterfaceTotalFlow}) = true diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index 6cf32a5c6..de6b3e9e8 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -961,6 +961,51 @@ function construct_device!( ##################### #### Expressions #### ##################### + add_expressions!( + container, + ReceivedHVDCActivePowerFromExpression, + devices, + model, + ) + add_expressions!( + container, + ReceivedHVDCActivePowerToExpression, + devices, + model, + ) + + add_to_expression!( + container, + ReceivedHVDCActivePowerFromExpression, + HVDCActiveDCPowerSentFromVariable, + devices, + model, + network_model, + ) + add_to_expression!( + container, + ReceivedHVDCActivePowerFromExpression, + HVDCLosses, + devices, + model, + network_model, + ) + add_to_expression!( + container, + ReceivedHVDCActivePowerToExpression, + HVDCActiveDCPowerSentToVariable, + devices, + model, + network_model, + ) + add_to_expression!( + container, + ReceivedHVDCActivePowerToExpression, + HVDCLosses, + devices, + model, + network_model, + ) # HVDCActivePowerReceivedFromVariable: DC Power Received on From Bus add_to_expression!( diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index fd8ef08b8..172abcda0 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -565,6 +565,36 @@ function add_to_expression!( 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 <: Union{ReceivedHVDCActivePowerFromExpression, ReceivedHVDCActivePowerToExpression}, + U <: + Union{HVDCActiveDCPowerSentFromVariable, HVDCActiveDCPowerSentToVariable, HVDCLosses}, + V <: TwoTerminalHVDCTypes, + W <: HVDCTwoTerminalVSCLoss, + X <: AbstractPTDFModel, +} + variable = get_variable(container, U(), V) + expression = get_expression(container, T(), V) + for d in devices + name = PSY.get_name(d) + for t in get_time_steps(container) + _add_to_jump_expression!( + expression[name, t], + variable[name, t], + -1.0, + ) + end + end + return +end + """ Default implementation to add branch variables to SystemBalanceExpressions """ From bf97f1f6b510a48929a8c6e31902281ea4f731a1 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 16 Dec 2024 10:51:43 -0800 Subject: [PATCH 19/34] add Bilinear Formulation --- src/PowerSimulations.jl | 15 +++++++++++++++ src/core/constraints.jl | 41 ++++++++++++++++++++++++++++++++++++++++ src/core/formulations.jl | 4 ++++ src/core/variables.jl | 18 ++++++++++++++++-- 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/PowerSimulations.jl b/src/PowerSimulations.jl index 0985a0905..4b0befd0b 100644 --- a/src/PowerSimulations.jl +++ b/src/PowerSimulations.jl @@ -236,6 +236,8 @@ export InterfaceFlowSlackDown export PieceWiseLinearCostVariable export HVDCActiveDCPowerSentFromVariable export HVDCActiveDCPowerSentToVariable +export HVDCReactivePowerSentFromVariable +export HVDCReactivePowerSentToVariable export ConverterPowerDirection export DCVoltageFrom export DCVoltageTo @@ -289,6 +291,17 @@ export FlowReactivePowerToFromConstraint export FrequencyResponseConstraint export HVDCPowerBalance export HVDCFlowDirectionVariable +export ConverterACPowerCalculationConstraint +export ConverterCurrentBalanceConstraint +export ConverterLossesCalculationConstraint +export FlowApparentPowerLimitConstraint +export ConverterPowerCalculationConstraint +export ConverterDirectionConstraint +export ConverterMcCormickEnvelopes +export InterpolationVoltageConstraints +export InterpolationCurrentConstraints +export InterpolationBilinearConstraints +export CurrentAbsoluteValueConstraint export InputActivePowerVariableLimitsConstraint export NetworkFlowConstraint export NodalBalanceActiveConstraint @@ -342,6 +355,8 @@ export RawACE export ProductionCostExpression export ActivePowerRangeExpressionLB export ActivePowerRangeExpressionUB +export ReceivedHVDCActivePowerFromExpression +export ReceivedHVDCActivePowerToExpression ################################################################################# # Imports diff --git a/src/core/constraints.jl b/src/core/constraints.jl index 74a575aa3..bade81986 100644 --- a/src/core/constraints.jl +++ b/src/core/constraints.jl @@ -336,6 +336,7 @@ struct InterfaceFlowLimit <: ConstraintType end struct HVDCFlowCalculationConstraint <: ConstraintType end abstract type PowerVariableLimitsConstraint <: ConstraintType end + """ Struct to create the constraint to limit active power input expressions. For more information check [Device Formulations](@ref formulation_intro). @@ -402,6 +403,8 @@ struct LineFlowBoundConstraint <: ConstraintType end abstract type EventConstraint <: ConstraintType end struct OutageConstraint <: EventConstraint end +################ HVDC VSC McCormick Model ################## + """ 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). @@ -528,3 +531,41 @@ The specified constraint is formulated as: ``` """ struct ConverterLossesCalculationConstraint <: ConstraintType end + +################ HVDC VSC AC Bilinear Model ################## + +""" +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 = v_c * i_c, \\quad \\forall t \\in \\{1,\\dots, T\\} +\\end{align*} +``` +""" +struct ConverterACPowerCalculationConstraint <: 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*} +& p_c * i_c >= 0.0, \\quad \\forall t \\in \\{1,\\dots, T\\} +\\end{align*} +``` +""" +struct ConverterACDirectionConstraint <: ConstraintType end + +""" +Struct to create the constraints that decide the flow apparent power limits to the VSC Line. +For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). +The specified constraints are formulated as: +```math +\\begin{align*} +& p_c^2 + q_c^2 <= rating^2, \\quad \\forall t \\in \\{1,\\dots, T\\} +\\end{align*} +``` +""" +struct FlowApparentPowerLimitConstraint <: ConstraintType end diff --git a/src/core/formulations.jl b/src/core/formulations.jl index dc4e9d055..f27e5bcf0 100644 --- a/src/core/formulations.jl +++ b/src/core/formulations.jl @@ -142,6 +142,10 @@ struct HVDCTwoTerminalPiecewiseLoss <: AbstractTwoTerminalDCLineFormulation end Branch type to represent physical lossy model on two terminal DC lines """ struct HVDCTwoTerminalVSCLoss <: AbstractTwoTerminalDCLineFormulation end +""" +Branch type to represent physical lossy model using a bilinear model. Only usable with AC Network Models. +""" +struct HVDCTwoTerminalVSCLossBilinear <: AbstractTwoTerminalDCLineFormulation end # Not Implemented # struct VoltageSourceDC <: AbstractTwoTerminalDCLineFormulation end diff --git a/src/core/variables.jl b/src/core/variables.jl index 0f1400536..e8d72e099 100644 --- a/src/core/variables.jl +++ b/src/core/variables.jl @@ -333,19 +333,33 @@ Docs abbreviation: ``z_c^{\\gamma}`` struct InterpolationBinarySquaredBilinearVariableTo <: SparseVariableType end """ -Struct to dispatch the creation of HVDC Received Flow at From Bus Variables for PWL formulations +Struct to dispatch the creation of HVDC Sent Flow at From Bus Variables for PWL and bilinear formulations Docs abbreviation: ``x`` """ struct HVDCActiveDCPowerSentFromVariable <: VariableType end """ -Struct to dispatch the creation of HVDC Received Flow at To Bus Variables for PWL formulations +Struct to dispatch the creation of HVDC Sent Flow at To Bus Variables for PWL and bilinear formulations Docs abbreviation: ``y`` """ struct HVDCActiveDCPowerSentToVariable <: VariableType end +""" +Struct to dispatch the creation of HVDC Sent Reactive Flow at From Bus Variables for bilinear formulations + +Docs abbreviation: ``x`` +""" +struct HVDCReactivePowerSentFromVariable <: VariableType end + +""" +Struct to dispatch the creation of HVDC Sent Reactive Flow at To Bus Variables for bilinear formulations + +Docs abbreviation: ``y`` +""" +struct HVDCReactivePowerSentToVariable <: VariableType end + """ Struct to dispatch the creation of bidirectional Active Power Flow Variables From feadaefcdcafaa4603c64bcc1450d94fb303eba9 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 16 Dec 2024 10:51:52 -0800 Subject: [PATCH 20/34] add constructor for bilinear method --- .../device_constructors/branch_constructor.jl | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index de6b3e9e8..fa7ff5c50 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -1117,6 +1117,179 @@ function construct_device!( return end +#### VSC Bilinear ### +function construct_device!( + container::OptimizationContainer, + sys::PSY.System, + ::ArgumentConstructStage, + model::DeviceModel{PSY.TwoTerminalVSCLine, HVDCTwoTerminalVSCLossBilinear}, + network_model::NetworkModel{<:PM.AbstractPowerModel}, +) + devices = get_available_components(model, sys) + + ##################### + ##### Variables ##### + ##################### + V = HVDCTwoTerminalVSCLossBilinear + # Add Power Variable + add_variables!(container, HVDCActiveDCPowerSentFromVariable, devices, V()) # p_c^{dc,from} + add_variables!(container, HVDCActiveDCPowerSentToVariable, devices, V()) # p_c^{dc,to} + # Add Reactive Power Variable + add_variables!(container, HVDCReactivePowerSentFromVariable, devices, V()) # p_c^{dc,from} + add_variables!(container, HVDCReactivePowerSentToVariable, devices, V()) # p_c^{dc,to} + # Add Voltage Variables: v_dc + add_variables!(container, DCVoltageFrom, devices, V()) # v_dc^{from} + add_variables!(container, DCVoltageTo, devices, V()) # v_dc^{to} + + # Add Current Variables: i + add_variables!(container, ConverterCurrent, devices, V()) # i + # Losses + add_variables!(container, HVDCLosses, devices, V()) + + ##################### + #### Expressions #### + ##################### + add_expressions!( + container, + ReceivedHVDCActivePowerFromExpression, + devices, + model, + ) + add_expressions!( + container, + ReceivedHVDCActivePowerToExpression, + devices, + model, + ) + + add_to_expression!( + container, + ReceivedHVDCActivePowerFromExpression, + HVDCActiveDCPowerSentFromVariable, + devices, + model, + network_model, + ) + add_to_expression!( + container, + ReceivedHVDCActivePowerFromExpression, + HVDCLosses, + devices, + model, + network_model, + ) + add_to_expression!( + container, + ReceivedHVDCActivePowerToExpression, + HVDCActiveDCPowerSentToVariable, + devices, + model, + network_model, + ) + add_to_expression!( + container, + ReceivedHVDCActivePowerToExpression, + HVDCLosses, + devices, + model, + network_model, + ) + + # HVDCActivePowerSentFromVariable: DC Power Received on From Bus + add_to_expression!( + container, + ActivePowerBalance, + HVDCActiveDCPowerSentFromVariable, + devices, + model, + network_model, + ) + # HVDCActivePowerSentToVariable: DC Power Received on To Bus + add_to_expression!( + container, + ActivePowerBalance, + HVDCActiveDCPowerSentToVariable, + devices, + model, + network_model, + ) + add_to_expression!( + container, + ActivePowerBalance, + HVDCLosses, + devices, + model, + network_model, + ) + + # HVDCReactivePowerSentFromVariable: Reactive power sent on From Bus + add_to_expression!( + container, + ReactivePowerBalance, + HVDCReactivePowerSentFromVariable, + devices, + model, + network_model, + ) + # HVDCReactivePowerSentToVariable: Reactive power sent on To Bus + add_to_expression!( + container, + ReactivePowerBalance, + HVDCReactivePowerSentToVariable, + devices, + model, + network_model, + ) + + # TODO: Add losses to balance expression to get full AC + add_feedforward_arguments!(container, model, devices) + return +end + +function construct_device!( + container::OptimizationContainer, + sys::PSY.System, + ::ModelConstructStage, + model::DeviceModel{PSY.TwoTerminalVSCLine, HVDCTwoTerminalVSCLossBilinear}, + network_model::NetworkModel{<:PM.AbstractPowerModel}, +) + devices = get_available_components(model, sys) + # TODO Constraints + add_constraints!( + container, + ConverterACPowerCalculationConstraint, + devices, + model, + network_model, + ) + add_constraints!( + container, + ConverterCurrentBalanceConstraint, + devices, + model, + network_model, + ) + add_constraints!( + container, + ConverterLossesCalculationConstraint, + devices, + model, + network_model, + ) + add_constraints!( + container, + FlowApparentPowerLimitConstraint, + 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) + return +end + ############################# Phase Shifter Transformer Models ############################# function construct_device!( From 5ca5287d72f06ea2ea0a84d78ee4320774600dc3 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 16 Dec 2024 10:52:13 -0800 Subject: [PATCH 21/34] add new constraints and expressions for bilinear --- .../devices/TwoTerminalDC_branches.jl | 274 ++++++++++++++++-- .../devices/common/add_to_expression.jl | 155 +++++++++- 2 files changed, 409 insertions(+), 20 deletions(-) diff --git a/src/devices_models/devices/TwoTerminalDC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl index e37c81848..020149bb3 100644 --- a/src/devices_models/devices/TwoTerminalDC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -21,6 +21,8 @@ get_variable_binary( ::Union{ HVDCActiveDCPowerSentFromVariable, HVDCActiveDCPowerSentToVariable, + HVDCReactivePowerSentFromVariable, + HVDCReactivePowerSentToVariable, DCVoltageFrom, DCVoltageTo, SquaredDCVoltageFrom, @@ -41,42 +43,42 @@ get_variable_binary( InterpolationSquaredBilinearVariableTo, }, ::Type{<:PSY.TwoTerminalVSCLine}, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = false get_variable_binary( ::InterpolationBinarySquaredVoltageVariableFrom, ::Type{<:PSY.TwoTerminalVSCLine}, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = true get_variable_binary( ::InterpolationBinarySquaredVoltageVariableTo, ::Type{<:PSY.TwoTerminalVSCLine}, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = true get_variable_binary( ::InterpolationBinarySquaredCurrentVariable, ::Type{<:PSY.TwoTerminalVSCLine}, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = true get_variable_binary( ::InterpolationBinarySquaredBilinearVariableFrom, ::Type{<:PSY.TwoTerminalVSCLine}, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = true get_variable_binary( ::InterpolationBinarySquaredBilinearVariableTo, ::Type{<:PSY.TwoTerminalVSCLine}, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = true get_variable_binary( ::ConverterPowerDirection, ::Type{<:PSY.TwoTerminalVSCLine}, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = true get_variable_binary( ::ConverterCurrentDirection, ::Type{<:PSY.TwoTerminalVSCLine}, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = true get_variable_multiplier(::FlowActivePowerVariable, ::Type{<:PSY.TwoTerminalHVDCLine}, _) = @@ -186,6 +188,30 @@ get_variable_lower_bound( ::AbstractTwoTerminalDCLineFormulation, ) = PSY.get_active_power_limits_from(d).min +get_variable_upper_bound( + ::HVDCReactivePowerSentFromVariable, + d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCLine}, + ::AbstractTwoTerminalDCLineFormulation, +) = PSY.get_reactive_power_limits_from(d).max + +get_variable_lower_bound( + ::HVDCReactivePowerSentFromVariable, + d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCLine}, + ::AbstractTwoTerminalDCLineFormulation, +) = PSY.get_reactive_power_limits_from(d).min + +get_variable_upper_bound( + ::HVDCReactivePowerSentToVariable, + d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCLine}, + ::AbstractTwoTerminalDCLineFormulation, +) = PSY.get_reactive_power_limits_to(d).max + +get_variable_lower_bound( + ::HVDCReactivePowerSentToVariable, + d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCLine}, + ::AbstractTwoTerminalDCLineFormulation, +) = PSY.get_reactive_power_limits_to(d).min + get_variable_upper_bound( ::Union{HVDCActivePowerReceivedToVariable, HVDCActiveDCPowerSentToVariable}, d::Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCLine}, @@ -234,31 +260,31 @@ get_variable_lower_bound( get_variable_upper_bound( ::Union{DCVoltageFrom, DCVoltageTo}, d::PSY.TwoTerminalVSCLine, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = PSY.get_voltage_limits(d).max get_variable_lower_bound( ::Union{DCVoltageFrom, DCVoltageTo}, d::PSY.TwoTerminalVSCLine, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = PSY.get_voltage_limits(d).min get_variable_upper_bound( ::Union{SquaredDCVoltageFrom, SquaredDCVoltageTo}, d::PSY.TwoTerminalVSCLine, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = PSY.get_voltage_limits(d).max^2 get_variable_lower_bound( ::Union{SquaredDCVoltageFrom, SquaredDCVoltageTo}, d::PSY.TwoTerminalVSCLine, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = 0.0 get_variable_lower_bound( ::Union{ConverterPositiveCurrent, ConverterNegativeCurrent}, d::PSY.TwoTerminalVSCLine, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = 0.0 get_variable_upper_bound( @@ -270,7 +296,7 @@ get_variable_upper_bound( InterpolationSquaredBilinearVariableTo, }, d::PSY.TwoTerminalVSCLine, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = 1.0 get_variable_lower_bound( @@ -282,7 +308,7 @@ get_variable_lower_bound( InterpolationSquaredBilinearVariableTo, }, d::PSY.TwoTerminalVSCLine, - ::HVDCTwoTerminalVSCLoss, + ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, ) = 0.0 function get_default_time_series_names( @@ -310,6 +336,13 @@ function get_default_attributes( ) end +function get_default_attributes( + ::Type{U}, + ::Type{V}, +) where {U <: PSY.TwoTerminalVSCLine, V <: HVDCTwoTerminalVSCLossBilinear} + return Dict{String, Any}() +end + get_initial_conditions_device_model( ::OperationModel, ::DeviceModel{T, U}, @@ -1517,11 +1550,11 @@ function add_constraints!( ::Type{T}, devices::IS.FlattenIteratorWrapper{U}, ::DeviceModel{U, V}, - ::NetworkModel{<:AbstractPTDFModel}, + ::NetworkModel{<:PM.AbstractPowerModel}, ) where { T <: ConverterCurrentBalanceConstraint, U <: PSY.TwoTerminalVSCLine, - V <: HVDCTwoTerminalVSCLoss, + V <: Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, } time_steps = get_time_steps(container) names = [PSY.get_name(d) for d in devices] @@ -1688,3 +1721,210 @@ function add_constraints!( end return end + +###### Bilinear AC Model Constraints ####### + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:PM.AbstractPowerModel}, +) where { + T <: ConverterLossesCalculationConstraint, + U <: PSY.TwoTerminalVSCLine, + V <: HVDCTwoTerminalVSCLossBilinear, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + JuMPmodel = get_jump_model(container) + # current vars # + losses_var = get_variable(container, HVDCLosses(), U) # From direction + current_var = get_variable(container, ConverterCurrent(), U) # From direction + + constraint = + add_constraints_container!( + container, + ConverterLossesCalculationConstraint(), + U, + names, + time_steps, + ) + + for d in devices + name = PSY.get_name(d) + loss = PSY.get_converter_loss(d) + a, b, c = _get_converter_loss_terms(loss) + for t in time_steps + constraint[name, t] = JuMP.@constraint( + JuMPmodel, + losses_var[name, t] == + a + b * abs(current_var[name, t]) + c * current_var[name, t]^2 + ) + end + end + return +end + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:PM.AbstractPowerModel}, +) where { + T <: ConverterACPowerCalculationConstraint, + U <: PSY.TwoTerminalVSCLine, + V <: HVDCTwoTerminalVSCLossBilinear, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + # power vars # + from_power_var = get_variable(container, HVDCActiveDCPowerSentFromVariable(), U) + to_power_var = get_variable(container, HVDCActiveDCPowerSentToVariable(), U) + # voltage vars # + from_voltage_var = get_variable(container, DCVoltageFrom(), U) + to_voltage_var = get_variable(container, DCVoltageTo(), U) + # current vars # + current_var = get_variable(container, ConverterCurrent(), U) # From direction + + constraint_from_calc = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "from_calc", + ) + constraint_to_calc = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "to_calc", + ) + + for d in devices + name = PSY.get_name(d) + for t in get_time_steps(container) + constraint_from_calc[name, t] = JuMP.@constraint( + get_jump_model(container), + from_power_var[name, t] == from_voltage_var[name, t] * current_var[name, t] + ) + constraint_to_calc[name, t] = JuMP.@constraint( + get_jump_model(container), + to_power_var[name, t] == to_voltage_var[name, t] * (-current_var[name, t]) + ) + end + end + return +end + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:PM.AbstractPowerModel}, +) where { + T <: FlowApparentPowerLimitConstraint, + U <: PSY.TwoTerminalVSCLine, + V <: HVDCTwoTerminalVSCLossBilinear, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + # power vars # + from_power_var = get_variable(container, HVDCActiveDCPowerSentFromVariable(), U) + to_power_var = get_variable(container, HVDCActiveDCPowerSentToVariable(), U) + from_reactive_var = get_variable(container, HVDCReactivePowerSentFromVariable(), U) + to_reactive_var = get_variable(container, HVDCReactivePowerSentToVariable(), U) + # voltage vars # + + constraint_from_calc = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "from_calc", + ) + constraint_to_calc = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "to_calc", + ) + + for d in devices + name = PSY.get_name(d) + rating = PSY.get_rating(d) + for t in get_time_steps(container) + constraint_from_calc[name, t] = JuMP.@constraint( + get_jump_model(container), + from_power_var[name, t]^2 + from_reactive_var[name, t]^2 <= rating^2 + ) + constraint_to_calc[name, t] = JuMP.@constraint( + get_jump_model(container), + to_power_var[name, t]^2 + to_reactive_var[name, t]^2 <= rating^2 + ) + end + end + return +end + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:PM.AbstractPowerModel}, +) where { + T <: ConverterACDirectionConstraint, + U <: PSY.TwoTerminalVSCLine, + V <: HVDCTwoTerminalVSCLossBilinear, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + JuMPmodel = get_jump_model(container) + # power vars # + from_power_var = get_variable(container, HVDCActiveDCPowerSentFromVariable(), U) + to_power_var = get_variable(container, HVDCActiveDCPowerSentToVariable(), U) + # current vars # + current_var = get_variable(container, ConverterCurrent(), U) # From direction + + constraint_from_power = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "from_power", + ) + + constraint_to_power = add_constraints_container!( + container, + T(), + U, + names, + time_steps; + meta = "to_power", + ) + + for d in devices + name = PSY.get_name(d) + for t in time_steps + constraint_from_power[name, t] = JuMP.@constraint( + JuMPmodel, + from_power_var[name, t] * current_var[name, t] >= 0.0 + ) + constraint_to_power[name, t] = JuMP.@constraint( + JuMPmodel, + to_power_var[name, t] * (-current_var[name, t]) >= 0.0 + ) + end + end + return +end diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index 172abcda0..1195fbca1 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -454,7 +454,7 @@ function add_to_expression!( end """ -PWL implementation to add FromTo branch variables to SystemBalanceExpressions +PWL implementation to add FromTo HVDC VSC branch variables to SystemBalanceExpressions """ function add_to_expression!( container::OptimizationContainer, @@ -490,6 +490,36 @@ function add_to_expression!( return end +""" +PWL implementation to add FromTo HVDC VSC branch variables to SystemBalanceExpressions +""" +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 <: HVDCActiveDCPowerSentFromVariable, + V <: TwoTerminalHVDCTypes, + W <: HVDCTwoTerminalVSCLossBilinear, + X <: PM.AbstractPowerModel, +} + var = get_variable(container, U(), V) + nodal_expr = get_expression(container, T(), PSY.ACBus) + for d in devices + bus_no_from = PSY.get_number(PSY.get_arc(d).from) + name = PSY.get_name(d) + for t in get_time_steps(container) + flow_variable = var[name, t] + _add_to_jump_expression!(nodal_expr[bus_no_from, t], flow_variable, -1.0) + end + end + return +end + """ PWL implementation to add FromTo branch variables to SystemBalanceExpressions """ @@ -527,6 +557,36 @@ function add_to_expression!( return end +""" +PWL implementation to add FromTo HVDC VSC branch variables to SystemBalanceExpressions +""" +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 <: HVDCActiveDCPowerSentToVariable, + V <: TwoTerminalHVDCTypes, + W <: HVDCTwoTerminalVSCLossBilinear, + X <: PM.AbstractPowerModel, +} + var = get_variable(container, U(), V) + nodal_expr = get_expression(container, T(), PSY.ACBus) + for d in devices + bus_no_to = PSY.get_number(PSY.get_arc(d).to) + name = PSY.get_name(d) + for t in get_time_steps(container) + flow_variable = var[name, t] + _add_to_jump_expression!(nodal_expr[bus_no_to, t], flow_variable, -1.0) + end + end + return +end + function add_to_expression!( container::OptimizationContainer, ::Type{T}, @@ -565,6 +625,95 @@ function add_to_expression!( 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 <: HVDCLosses, + V <: TwoTerminalHVDCTypes, + W <: HVDCTwoTerminalVSCLossBilinear, + X <: PM.AbstractPowerModel, +} + var = get_variable(container, U(), V) + nodal_expr = get_expression(container, T(), PSY.ACBus) + for d in devices + name = PSY.get_name(d) + bus_no_from = PSY.get_number(PSY.get_arc(d).from) + bus_no_to = PSY.get_number(PSY.get_arc(d).to) + for t in get_time_steps(container) + losses_variable = var[name, t] + _add_to_jump_expression!(nodal_expr[bus_no_from, t], losses_variable, -1.0) + _add_to_jump_expression!(nodal_expr[bus_no_to, t], losses_variable, -1.0) + end + end + return +end + +""" +Bilinear implementation to add Reactive Power FromTo HVDC VSC branch variables to SystemBalanceExpressions +""" +function add_to_expression!( + container::OptimizationContainer, + ::Type{T}, + ::Type{U}, + devices::IS.FlattenIteratorWrapper{V}, + ::DeviceModel{V, W}, + network_model::NetworkModel{X}, +) where { + T <: ReactivePowerBalance, + U <: HVDCReactivePowerSentFromVariable, + V <: TwoTerminalHVDCTypes, + W <: HVDCTwoTerminalVSCLossBilinear, + X <: PM.AbstractPowerModel, +} + var = get_variable(container, U(), V) + nodal_expr = get_expression(container, T(), PSY.ACBus) + for d in devices + bus_no_from = PSY.get_number(PSY.get_arc(d).from) + name = PSY.get_name(d) + for t in get_time_steps(container) + flow_variable = var[name, t] + _add_to_jump_expression!(nodal_expr[bus_no_from, t], flow_variable, -1.0) + end + end + return +end + +""" +Bilinear implementation to add Reactive Power FromTo HVDC VSC branch variables to SystemBalanceExpressions +""" +function add_to_expression!( + container::OptimizationContainer, + ::Type{T}, + ::Type{U}, + devices::IS.FlattenIteratorWrapper{V}, + ::DeviceModel{V, W}, + network_model::NetworkModel{X}, +) where { + T <: ReactivePowerBalance, + U <: HVDCReactivePowerSentToVariable, + V <: TwoTerminalHVDCTypes, + W <: HVDCTwoTerminalVSCLossBilinear, + X <: PM.AbstractPowerModel, +} + var = get_variable(container, U(), V) + nodal_expr = get_expression(container, T(), PSY.ACBus) + for d in devices + bus_no_to = PSY.get_number(PSY.get_arc(d).to) + name = PSY.get_name(d) + for t in get_time_steps(container) + flow_variable = var[name, t] + _add_to_jump_expression!(nodal_expr[bus_no_to, t], flow_variable, -1.0) + end + end + return +end + function add_to_expression!( container::OptimizationContainer, ::Type{T}, @@ -577,8 +726,8 @@ function add_to_expression!( U <: Union{HVDCActiveDCPowerSentFromVariable, HVDCActiveDCPowerSentToVariable, HVDCLosses}, V <: TwoTerminalHVDCTypes, - W <: HVDCTwoTerminalVSCLoss, - X <: AbstractPTDFModel, + W <: Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, + X <: PM.AbstractPowerModel, } variable = get_variable(container, U(), V) expression = get_expression(container, T(), V) From 8fb3a8fd12b7aba2519141463ae97d51ed329f78 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 16 Dec 2024 10:52:20 -0800 Subject: [PATCH 22/34] update powermodels translator --- src/network_models/pm_translator.jl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/network_models/pm_translator.jl b/src/network_models/pm_translator.jl index 171297715..e9d18ffa8 100644 --- a/src/network_models/pm_translator.jl +++ b/src/network_models/pm_translator.jl @@ -12,7 +12,7 @@ const PM_BUSTYPES = Dict{PSY.ACBusTypes, Int}( struct PMmap bus::Dict{Int, PSY.ACBus} arcs::Dict{PM_MAP_TUPLE, <:PSY.ACBranch} - arcs_dc::Dict{PM_MAP_TUPLE, PSY.TwoTerminalHVDCLine} + arcs_dc::Dict{PM_MAP_TUPLE, Union{PSY.TwoTerminalHVDCLine, PSY.TwoTerminalVSCLine}} end function get_branch_to_pm( @@ -341,6 +341,15 @@ function get_branch_to_pm( return PM_branch end +function get_branch_to_pm( + ix::Int, + branch::PSY.TwoTerminalVSCLine, + ::Type{HVDCTwoTerminalVSCLossBilinear}, + ::Type{<:PM.AbstractPowerModel}, +) + return Dict{String, Any}() +end + function get_branch_to_pm( ix::Int, branch::PSY.TwoTerminalHVDCLine, @@ -429,6 +438,10 @@ function get_branches_to_pm( for (d, device_model) in branch_template comp_type = get_component_type(device_model) !(comp_type <: T) && continue + if comp_type <: PSY.TwoTerminalVSCLine && + get_formulation(device_model) <: HVDCTwoTerminalVSCLossBilinear + continue + end start_idx += length(PM_branches) for (i, branch) in enumerate(get_available_components(device_model, sys)) ix = i + start_idx From 78584b8d6fde30fc38ef3b52e9891ec38f08fede Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 16 Dec 2024 10:52:26 -0800 Subject: [PATCH 23/34] update bilinear test --- test/test_device_branch_constructors.jl | 62 +++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/test/test_device_branch_constructors.jl b/test/test_device_branch_constructors.jl index e6128448e..f820e6bfd 100644 --- a/test/test_device_branch_constructors.jl +++ b/test/test_device_branch_constructors.jl @@ -793,3 +793,65 @@ end moi_tests(ps_model, 268, 0, 152, 148, 62, true) @test solve!(ps_model) == PSI.RunStatus.SUCCESSFULLY_FINALIZED end + +@testset "HVDC VSC Loss Bilinear AC Model" begin + c_sys5 = PSB.build_system(PSISystems, "2Area 5 Bus System") + thermal_names = ["Solitude", "Park City", "Alta", "Brighton"] + for name in thermal_names + thermal = get_component(ThermalStandard, c_sys5, name) + op_cost = get_operation_cost(thermal) + new_opcost = ThermalGenerationCost(; + variable = CostCurve(; + value_curve = PSY.QuadraticCurve( + 0.0, + get_proportional_term(op_cost.variable.value_curve) / 2.0, + 0.0, + ), + power_units = UnitSystem.NATURAL_UNITS, + ), + fixed = op_cost.fixed, + start_up = op_cost.start_up, + shut_down = op_cost.shut_down, + ) + set_operation_cost!(thermal, new_opcost) + end + + hvdc = first(get_components(TwoTerminalHVDCLine, c_sys5)) + + hvdc_new = TwoTerminalVSCLine(; + name = get_name(hvdc), + available = get_available(hvdc), + active_power_flow = get_active_power_flow(hvdc), + rating = 2.0, + active_power_limits_from = (min = -2.0, max = 2.0), + active_power_limits_to = (min = -2.0, max = 2.0), + arc = get_arc(hvdc), + converter_loss = QuadraticCurve(0.0001, 0.01, 0.0), + dc_current = 0.0, + max_dc_current = 3.0, + g = 50.0, # r = 0.02 + voltage_limits = (min = 0.9, max = 1.1), + reactive_power_limits_from = (min = -1.0, max = 1.0), + reactive_power_limits_to = (min = -1.0, max = 1.0), + ) + remove_component!(c_sys5, hvdc) + add_component!(c_sys5, hvdc_new) + + template = get_thermal_dispatch_template_network(NetworkModel(ACPPowerModel)) + dev_model = DeviceModel( + TwoTerminalVSCLine, + PSI.HVDCTwoTerminalVSCLossBilinear, + ) + set_device_model!(template, dev_model) + ps_model = DecisionModel( + template, + c_sys5; + optimizer = ipopt_optimizer, + store_variable_names = true, + horizon = Hour(2), + ) + @test build!(ps_model; output_dir = mktempdir(; cleanup = true)) == + PSI.ModelBuildStatus.BUILT + moi_tests(ps_model, 192, 24, 40, 40, 46, false) + @test solve!(ps_model) == PSI.RunStatus.SUCCESSFULLY_FINALIZED +end From 3d972aceaec0e19e050dec9bd48d807f7882764e Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 16 Dec 2024 15:13:50 -0800 Subject: [PATCH 24/34] add quadratic formulation --- src/core/formulations.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/core/formulations.jl b/src/core/formulations.jl index f27e5bcf0..8d0136f7a 100644 --- a/src/core/formulations.jl +++ b/src/core/formulations.jl @@ -135,17 +135,21 @@ Branch type to represent lossy power flow on DC lines """ struct HVDCTwoTerminalDispatch <: AbstractTwoTerminalDCLineFormulation end """ -Branch type to represent piecewise lossy power flow on two terminal DC lines +Branch type to represent piecewise lossy power flow (with respect to power) on two terminal DC lines """ struct HVDCTwoTerminalPiecewiseLoss <: AbstractTwoTerminalDCLineFormulation end """ -Branch type to represent physical lossy model on two terminal DC lines +Branch type to represent physical lossy model on two terminal DC lines using interpolation methods for quadratic losses """ struct HVDCTwoTerminalVSCLoss <: AbstractTwoTerminalDCLineFormulation end """ Branch type to represent physical lossy model using a bilinear model. Only usable with AC Network Models. """ struct HVDCTwoTerminalVSCLossBilinear <: AbstractTwoTerminalDCLineFormulation end +""" +Branch type to represent physical lossy model using a quadratic loss model with respect to power. Only usable with AC Network Models. +""" +struct HVDCTwoTerminalVSCLossQuadratic <: AbstractTwoTerminalDCLineFormulation end # Not Implemented # struct VoltageSourceDC <: AbstractTwoTerminalDCLineFormulation end From f66f13845f0ad7675a7fab3e5a84d0b7468a4762 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 16 Dec 2024 15:19:42 -0800 Subject: [PATCH 25/34] add constructor for quadratic model --- src/core/constraints.jl | 19 ++- .../device_constructors/branch_constructor.jl | 139 +++++++++++++++++- 2 files changed, 155 insertions(+), 3 deletions(-) diff --git a/src/core/constraints.jl b/src/core/constraints.jl index bade81986..f85519114 100644 --- a/src/core/constraints.jl +++ b/src/core/constraints.jl @@ -523,11 +523,16 @@ struct CurrentAbsoluteValueConstraint <: ConstraintType end """ Struct to create the constraints that set the losses for the converter to use in losses through a lossy Interconnecting Power Converter. For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). -The specified constraint is formulated as: +The specified constraint for the bilinear model is formulated as: ```math \\begin{align*} & p_c^{loss} = a_c + b_c |i_c| + c_c i_c^2, \\quad \\forall t \\in \\{1,\\dots, T\\} \\end{align*} + +For the quadratic model is formulated as: +\\begin{align*} +& p_c^{loss} = a_c + b_c |p_c^{from}| + c_c (p_c^{from})^2, \\quad \\forall t \\in \\{1,\\dots, T\\} +\\end{align*} ``` """ struct ConverterLossesCalculationConstraint <: ConstraintType end @@ -569,3 +574,15 @@ The specified constraints are formulated as: ``` """ struct FlowApparentPowerLimitConstraint <: ConstraintType end + +""" +Struct to create the constraints that balance the DC Power to the VSC Line. +For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). +The specified constraints are formulated as: +```math +\\begin{align*} +& p_c^{from} = - p_c^{to} - p_c^{loss}, \\quad \\forall t \\in \\{1,\\dots, T\\} +\\end{align*} +``` +""" +struct ConverterPowerBalanceConstraint <: ConstraintType end diff --git a/src/devices_models/device_constructors/branch_constructor.jl b/src/devices_models/device_constructors/branch_constructor.jl index fa7ff5c50..0ef694a75 100644 --- a/src/devices_models/device_constructors/branch_constructor.jl +++ b/src/devices_models/device_constructors/branch_constructor.jl @@ -1135,8 +1135,8 @@ function construct_device!( add_variables!(container, HVDCActiveDCPowerSentFromVariable, devices, V()) # p_c^{dc,from} add_variables!(container, HVDCActiveDCPowerSentToVariable, devices, V()) # p_c^{dc,to} # Add Reactive Power Variable - add_variables!(container, HVDCReactivePowerSentFromVariable, devices, V()) # p_c^{dc,from} - add_variables!(container, HVDCReactivePowerSentToVariable, devices, V()) # p_c^{dc,to} + add_variables!(container, HVDCReactivePowerSentFromVariable, devices, V()) # q_c^{from} + add_variables!(container, HVDCReactivePowerSentToVariable, devices, V()) # q_c^{to} # Add Voltage Variables: v_dc add_variables!(container, DCVoltageFrom, devices, V()) # v_dc^{from} add_variables!(container, DCVoltageTo, devices, V()) # v_dc^{to} @@ -1290,6 +1290,141 @@ function construct_device!( return end +###### VSC Quadratic ####### +function construct_device!( + container::OptimizationContainer, + sys::PSY.System, + ::ArgumentConstructStage, + model::DeviceModel{PSY.TwoTerminalVSCLine, HVDCTwoTerminalVSCLossQuadratic}, + network_model::NetworkModel{<:PM.AbstractPowerModel}, +) + devices = get_available_components(model, sys) + + ##################### + ##### Variables ##### + ##################### + V = HVDCTwoTerminalVSCLossQuadratic + # Add Power Variable + add_variables!(container, HVDCActiveDCPowerSentFromVariable, devices, V()) # p_c^{dc,from} + add_variables!(container, HVDCActiveDCPowerSentToVariable, devices, V()) # p_c^{dc,to} + # Add Reactive Power Variable + add_variables!(container, HVDCReactivePowerSentFromVariable, devices, V()) # q_c^{from} + add_variables!(container, HVDCReactivePowerSentToVariable, devices, V()) # q_c^{to} + # Losses + add_variables!(container, HVDCLosses, devices, V()) + + ##################### + #### Expressions #### + ##################### + add_expressions!( + container, + ReceivedHVDCActivePowerFromExpression, + devices, + model, + ) + add_expressions!( + container, + ReceivedHVDCActivePowerToExpression, + devices, + model, + ) + + add_to_expression!( + container, + ReceivedHVDCActivePowerFromExpression, + HVDCActiveDCPowerSentFromVariable, + devices, + model, + network_model, + ) + add_to_expression!( + container, + ReceivedHVDCActivePowerToExpression, + HVDCActiveDCPowerSentToVariable, + devices, + model, + network_model, + ) + + # HVDCActivePowerSentFromVariable: DC Power Received on From Bus + add_to_expression!( + container, + ActivePowerBalance, + HVDCActiveDCPowerSentFromVariable, + devices, + model, + network_model, + ) + add_to_expression!( + container, + ActivePowerBalance, + HVDCActiveDCPowerSentToVariable, + devices, + model, + network_model, + ) + + # HVDCReactivePowerSentFromVariable: Reactive power sent on From Bus + add_to_expression!( + container, + ReactivePowerBalance, + HVDCReactivePowerSentFromVariable, + devices, + model, + network_model, + ) + # HVDCReactivePowerSentToVariable: Reactive power sent on To Bus + add_to_expression!( + container, + ReactivePowerBalance, + HVDCReactivePowerSentToVariable, + devices, + model, + network_model, + ) + + # TODO: Add losses to balance expression to get full AC + add_feedforward_arguments!(container, model, devices) + return +end + +function construct_device!( + container::OptimizationContainer, + sys::PSY.System, + ::ModelConstructStage, + model::DeviceModel{PSY.TwoTerminalVSCLine, HVDCTwoTerminalVSCLossQuadratic}, + network_model::NetworkModel{<:PM.AbstractPowerModel}, +) + devices = get_available_components(model, sys) + + add_constraints!( + container, + ConverterLossesCalculationConstraint, + devices, + model, + network_model, + ) + add_constraints!( + container, + FlowApparentPowerLimitConstraint, + devices, + model, + network_model, + ) + add_constraints!( + container, + ConverterPowerBalanceConstraint, + 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) + return +end + ############################# Phase Shifter Transformer Models ############################# function construct_device!( From 391a45a12323b44d7fad91a93d48109e87266754 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 16 Dec 2024 15:19:54 -0800 Subject: [PATCH 26/34] add constraints and expressions for quadratic hvdc model --- .../devices/TwoTerminalDC_branches.jl | 93 ++++++++++++++++++- .../devices/common/add_to_expression.jl | 14 ++- 2 files changed, 100 insertions(+), 7 deletions(-) diff --git a/src/devices_models/devices/TwoTerminalDC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl index 020149bb3..fe3db1a7c 100644 --- a/src/devices_models/devices/TwoTerminalDC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -43,7 +43,11 @@ get_variable_binary( InterpolationSquaredBilinearVariableTo, }, ::Type{<:PSY.TwoTerminalVSCLine}, - ::Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, + ::Union{ + HVDCTwoTerminalVSCLoss, + HVDCTwoTerminalVSCLossBilinear, + HVDCTwoTerminalVSCLossQuadratic, + }, ) = false get_variable_binary( ::InterpolationBinarySquaredVoltageVariableFrom, @@ -1830,7 +1834,7 @@ function add_constraints!( ) where { T <: FlowApparentPowerLimitConstraint, U <: PSY.TwoTerminalVSCLine, - V <: HVDCTwoTerminalVSCLossBilinear, + V <: Union{HVDCTwoTerminalVSCLossBilinear, HVDCTwoTerminalVSCLossQuadratic}, } time_steps = get_time_steps(container) names = [PSY.get_name(d) for d in devices] @@ -1875,6 +1879,7 @@ function add_constraints!( return end +### Currently not used but could be used in the future (looks redundant) ### function add_constraints!( container::OptimizationContainer, ::Type{T}, @@ -1928,3 +1933,87 @@ function add_constraints!( end return end + +###### Quadratic Loss AC Model Constraints ####### + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:PM.AbstractPowerModel}, +) where { + T <: ConverterLossesCalculationConstraint, + U <: PSY.TwoTerminalVSCLine, + V <: HVDCTwoTerminalVSCLossQuadratic, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + JuMPmodel = get_jump_model(container) + # current vars # + losses_var = get_variable(container, HVDCLosses(), U) # From direction + power_var = get_variable(container, HVDCActiveDCPowerSentFromVariable(), U) # From direction + + constraint = + add_constraints_container!( + container, + ConverterLossesCalculationConstraint(), + U, + names, + time_steps, + ) + + for d in devices + name = PSY.get_name(d) + loss = PSY.get_converter_loss(d) + a, b, c = _get_converter_loss_terms(loss) + for t in time_steps + constraint[name, t] = JuMP.@constraint( + JuMPmodel, + losses_var[name, t] == + a + b * abs(power_var[name, t]) + c * power_var[name, t]^2 + ) + end + end + return +end + +function add_constraints!( + container::OptimizationContainer, + ::Type{T}, + devices::IS.FlattenIteratorWrapper{U}, + ::DeviceModel{U, V}, + ::NetworkModel{<:PM.AbstractPowerModel}, +) where { + T <: ConverterPowerBalanceConstraint, + U <: PSY.TwoTerminalVSCLine, + V <: HVDCTwoTerminalVSCLossQuadratic, +} + time_steps = get_time_steps(container) + names = [PSY.get_name(d) for d in devices] + JuMPmodel = get_jump_model(container) + # current vars # + losses_var = get_variable(container, HVDCLosses(), U) # From direction + power_from_var = get_variable(container, HVDCActiveDCPowerSentFromVariable(), U) # From direction + power_to_var = get_variable(container, HVDCActiveDCPowerSentToVariable(), U) # To direction + + constraint = + add_constraints_container!( + container, + ConverterPowerBalanceConstraint(), + U, + names, + time_steps, + ) + + for d in devices + name = PSY.get_name(d) + for t in time_steps + constraint[name, t] = JuMP.@constraint( + JuMPmodel, + power_from_var[name, t] == -power_to_var[name, t] - losses_var[name, t] + ) + end + end + return +end diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index 1195fbca1..a237ec7f0 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -504,7 +504,7 @@ function add_to_expression!( T <: ActivePowerBalance, U <: HVDCActiveDCPowerSentFromVariable, V <: TwoTerminalHVDCTypes, - W <: HVDCTwoTerminalVSCLossBilinear, + W <: Union{HVDCTwoTerminalVSCLossBilinear, HVDCTwoTerminalVSCLossQuadratic}, X <: PM.AbstractPowerModel, } var = get_variable(container, U(), V) @@ -571,7 +571,7 @@ function add_to_expression!( T <: ActivePowerBalance, U <: HVDCActiveDCPowerSentToVariable, V <: TwoTerminalHVDCTypes, - W <: HVDCTwoTerminalVSCLossBilinear, + W <: Union{HVDCTwoTerminalVSCLossBilinear, HVDCTwoTerminalVSCLossQuadratic}, X <: PM.AbstractPowerModel, } var = get_variable(container, U(), V) @@ -668,7 +668,7 @@ function add_to_expression!( T <: ReactivePowerBalance, U <: HVDCReactivePowerSentFromVariable, V <: TwoTerminalHVDCTypes, - W <: HVDCTwoTerminalVSCLossBilinear, + W <: Union{HVDCTwoTerminalVSCLossBilinear, HVDCTwoTerminalVSCLossQuadratic}, X <: PM.AbstractPowerModel, } var = get_variable(container, U(), V) @@ -698,7 +698,7 @@ function add_to_expression!( T <: ReactivePowerBalance, U <: HVDCReactivePowerSentToVariable, V <: TwoTerminalHVDCTypes, - W <: HVDCTwoTerminalVSCLossBilinear, + W <: Union{HVDCTwoTerminalVSCLossBilinear, HVDCTwoTerminalVSCLossQuadratic}, X <: PM.AbstractPowerModel, } var = get_variable(container, U(), V) @@ -726,7 +726,11 @@ function add_to_expression!( U <: Union{HVDCActiveDCPowerSentFromVariable, HVDCActiveDCPowerSentToVariable, HVDCLosses}, V <: TwoTerminalHVDCTypes, - W <: Union{HVDCTwoTerminalVSCLoss, HVDCTwoTerminalVSCLossBilinear}, + W <: Union{ + HVDCTwoTerminalVSCLoss, + HVDCTwoTerminalVSCLossBilinear, + HVDCTwoTerminalVSCLossQuadratic, + }, X <: PM.AbstractPowerModel, } variable = get_variable(container, U(), V) From ead0aef962200752b2b6e4e9cbc99b4c5d5cbe9d Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 16 Dec 2024 15:20:09 -0800 Subject: [PATCH 27/34] update power models parser for quadratic vsc --- src/network_models/pm_translator.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/network_models/pm_translator.jl b/src/network_models/pm_translator.jl index e9d18ffa8..d2d0f1b40 100644 --- a/src/network_models/pm_translator.jl +++ b/src/network_models/pm_translator.jl @@ -344,7 +344,7 @@ end function get_branch_to_pm( ix::Int, branch::PSY.TwoTerminalVSCLine, - ::Type{HVDCTwoTerminalVSCLossBilinear}, + ::Union{Type{HVDCTwoTerminalVSCLossBilinear}, Type{HVDCTwoTerminalVSCLossQuadratic}}, ::Type{<:PM.AbstractPowerModel}, ) return Dict{String, Any}() @@ -439,7 +439,8 @@ function get_branches_to_pm( comp_type = get_component_type(device_model) !(comp_type <: T) && continue if comp_type <: PSY.TwoTerminalVSCLine && - get_formulation(device_model) <: HVDCTwoTerminalVSCLossBilinear + get_formulation(device_model) <: + Union{HVDCTwoTerminalVSCLossBilinear, HVDCTwoTerminalVSCLossQuadratic} continue end start_idx += length(PM_branches) From 82682d0c65434f9dc481bb022af64c0e9ad09ea5 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 16 Dec 2024 15:20:41 -0800 Subject: [PATCH 28/34] update tests --- test/test_device_branch_constructors.jl | 64 ++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/test/test_device_branch_constructors.jl b/test/test_device_branch_constructors.jl index f820e6bfd..c20f001c6 100644 --- a/test/test_device_branch_constructors.jl +++ b/test/test_device_branch_constructors.jl @@ -729,7 +729,7 @@ end @test sum(vars[!, "2"]) >= -1e-6 end -@testset "HVDC VSC Loss Model" begin +@testset "HVDC VSC Loss Piecewise Linear Model" begin c_sys5 = PSB.build_system(PSISystems, "2Area 5 Bus System") thermal_names = ["Solitude", "Park City", "Alta", "Brighton"] for name in thermal_names @@ -855,3 +855,65 @@ end moi_tests(ps_model, 192, 24, 40, 40, 46, false) @test solve!(ps_model) == PSI.RunStatus.SUCCESSFULLY_FINALIZED end + +@testset "HVDC VSC Loss Quadratic AC Model" begin + c_sys5 = PSB.build_system(PSISystems, "2Area 5 Bus System") + thermal_names = ["Solitude", "Park City", "Alta", "Brighton"] + for name in thermal_names + thermal = get_component(ThermalStandard, c_sys5, name) + op_cost = get_operation_cost(thermal) + new_opcost = ThermalGenerationCost(; + variable = CostCurve(; + value_curve = PSY.QuadraticCurve( + 0.0, + get_proportional_term(op_cost.variable.value_curve) / 2.0, + 0.0, + ), + power_units = UnitSystem.NATURAL_UNITS, + ), + fixed = op_cost.fixed, + start_up = op_cost.start_up, + shut_down = op_cost.shut_down, + ) + set_operation_cost!(thermal, new_opcost) + end + + hvdc = first(get_components(TwoTerminalHVDCLine, c_sys5)) + + hvdc_new = TwoTerminalVSCLine(; + name = get_name(hvdc), + available = get_available(hvdc), + active_power_flow = get_active_power_flow(hvdc), + rating = 2.0, + active_power_limits_from = (min = -2.0, max = 2.0), + active_power_limits_to = (min = -2.0, max = 2.0), + arc = get_arc(hvdc), + converter_loss = QuadraticCurve(0.0001, 0.01, 0.0), + dc_current = 0.0, + max_dc_current = 3.0, + g = 50.0, # r = 0.02 + voltage_limits = (min = 0.9, max = 1.1), + reactive_power_limits_from = (min = -1.0, max = 1.0), + reactive_power_limits_to = (min = -1.0, max = 1.0), + ) + remove_component!(c_sys5, hvdc) + add_component!(c_sys5, hvdc_new) + + template = get_thermal_dispatch_template_network(NetworkModel(ACPPowerModel)) + dev_model = DeviceModel( + TwoTerminalVSCLine, + PSI.HVDCTwoTerminalVSCLossQuadratic, + ) + set_device_model!(template, dev_model) + ps_model = DecisionModel( + template, + c_sys5; + optimizer = ipopt_optimizer, + store_variable_names = true, + horizon = Hour(2), + ) + @test build!(ps_model; output_dir = mktempdir(; cleanup = true)) == + PSI.ModelBuildStatus.BUILT + moi_tests(ps_model, 186, 24, 40, 40, 46, false) + @test solve!(ps_model) == PSI.RunStatus.SUCCESSFULLY_FINALIZED +end From ed7c2d86a933e0daff9b6f8a524cf64450efb709 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Mon, 16 Dec 2024 15:23:42 -0800 Subject: [PATCH 29/34] update exports --- src/PowerSimulations.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PowerSimulations.jl b/src/PowerSimulations.jl index 4b0befd0b..878b742a7 100644 --- a/src/PowerSimulations.jl +++ b/src/PowerSimulations.jl @@ -45,7 +45,10 @@ export HVDCTwoTerminalLossless export HVDCTwoTerminalDispatch export HVDCTwoTerminalUnbounded export PhaseAngleControl +export HVDCTwoTerminalPiecewiseLoss export HVDCTwoTerminalVSCLoss +export HVDCTwoTerminalVSCLossBilinear +export HVDCTwoTerminalVSCLossQuadratic # export VoltageSourceDC ######## HVDC models ######## @@ -295,6 +298,7 @@ export ConverterACPowerCalculationConstraint export ConverterCurrentBalanceConstraint export ConverterLossesCalculationConstraint export FlowApparentPowerLimitConstraint +export ConverterPowerBalanceConstraint export ConverterPowerCalculationConstraint export ConverterDirectionConstraint export ConverterMcCormickEnvelopes From a9e6fa39a2acec29e3267d719ef4bf401af0c463 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 20 Dec 2024 11:27:39 -0800 Subject: [PATCH 30/34] fix docstrings typos --- src/core/constraints.jl | 64 +++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/src/core/constraints.jl b/src/core/constraints.jl index f85519114..761204993 100644 --- a/src/core/constraints.jl +++ b/src/core/constraints.jl @@ -407,7 +407,7 @@ 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*} @@ -419,11 +419,11 @@ 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\\} \\\\ +& p_c = 0.5 \\cdot (γ^{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*} ``` @@ -432,12 +432,12 @@ 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\\} \\\\ +& I_c^{min} (1 - κ_c) \\le i_c \\le κ_c * I_c^{max}, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& P_c^{min} (1 - κ_c) \\le p_c \\le κ_c * P_c^{max}, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ \\end{align*} ``` """ @@ -445,14 +445,14 @@ 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\\} \\\\ +& p_c \\ge V^{min} i_c + v_c I^{min} - I^{min}V^{min}, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& p_c \\ge V^{max} i_c + v_c I^{max} - I^{max}V^{max}, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& p_c \\le V^{max} i_c + v_c I^{min} - I^{min}V^{max}, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& p_c \\le V^{min} i_c + v_c I^{max} - I^{max}V^{min}, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ \\end{align*} ``` """ @@ -461,14 +461,14 @@ struct ConverterMcCormickEnvelopes <: ConstraintType end """ Struct to create the Quadratic PWL interpolation constraints that decide square value of the voltage. In this case x = voltage and y = squared_voltage. -For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). + The specified constraints are formulated as: ```math \\begin{align*} & x = x_0 + \\sum_{k=1}^K (x_{k} - x_{k-1}) \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ & y = y_0 + \\sum_{k=1}^K (x_{k} - x_{k-1}) \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ -& z_k <= \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ -& z_k >= \\delta_{k+1}, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ +& z_k \\le \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ +& z_k \\ge \\delta_{k+1}, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ \\end{align*} ``` """ @@ -477,14 +477,14 @@ struct InterpolationVoltageConstraints <: ConstraintType end """ Struct to create the Quadratic PWL interpolation constraints that decide square value of the current. In this case x = current and y = squared_current. -For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). + The specified constraints are formulated as: ```math \\begin{align*} & x = x_0 + \\sum_{k=1}^K (x_{k} - x_{k-1}) \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ & y = y_0 + \\sum_{k=1}^K (x_{k} - x_{k-1}) \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ -& z_k <= \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ -& z_k >= \\delta_{k+1}, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ +& z_k \\le \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ +& z_k \\ge \\delta_{k+1}, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ \\end{align*} ``` """ @@ -493,14 +493,14 @@ struct InterpolationCurrentConstraints <: ConstraintType end """ Struct to create the Quadratic PWL interpolation constraints that decide square value of the bilinear variable γ. In this case x = γ and y = squared_γ. -For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). + The specified constraints are formulated as: ```math \\begin{align*} & x = x_0 + \\sum_{k=1}^K (x_{k} - x_{k-1}) \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ & y = y_0 + \\sum_{k=1}^K (x_{k} - x_{k-1}) \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ -& z_k <= \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ -& z_k >= \\delta_{k+1}, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ +& z_k \\le \\delta_k, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ +& z_k \\ge \\delta_{k+1}, \\quad \\forall t \\in \\{1,\\dots, T\\}, \\forall k \\in \\{1,\\dots, K-1\\} \\\\ \\end{align*} ``` """ @@ -508,13 +508,13 @@ struct InterpolationBilinearConstraints <: ConstraintType end """ Struct to create the constraints that set the absolute value for the current to use in 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} = i_c^+ - i_c^-, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ -& i_c^+ \\le I_max \\cdot \\nu_c, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ -& i_c^+ \\le I_max \\cdot (1 - \\nu_c), \\quad \\forall t \\in \\{1,\\dots, T\\} +& i_c^+ \\le I_{max} \\cdot \\nu_c, \\quad \\forall t \\in \\{1,\\dots, T\\} \\\\ +& i_c^+ \\le I_{max} \\cdot (1 - \\nu_c), \\quad \\forall t \\in \\{1,\\dots, T\\} \\end{align*} ``` """ @@ -522,14 +522,16 @@ struct CurrentAbsoluteValueConstraint <: ConstraintType end """ Struct to create the constraints that set the losses for the converter to use in losses through a lossy Interconnecting Power Converter. -For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). + The specified constraint for the bilinear model is formulated as: ```math \\begin{align*} & p_c^{loss} = a_c + b_c |i_c| + c_c i_c^2, \\quad \\forall t \\in \\{1,\\dots, T\\} \\end{align*} +``` For the quadratic model is formulated as: +```math \\begin{align*} & p_c^{loss} = a_c + b_c |p_c^{from}| + c_c (p_c^{from})^2, \\quad \\forall t \\in \\{1,\\dots, T\\} \\end{align*} @@ -541,11 +543,11 @@ struct ConverterLossesCalculationConstraint <: 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 = v_c * i_c, \\quad \\forall t \\in \\{1,\\dots, T\\} +& p_c = v_c \\cdot i_c, \\quad \\forall t \\in \\{1,\\dots, T\\} \\end{align*} ``` """ @@ -553,11 +555,11 @@ struct ConverterACPowerCalculationConstraint <: 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*} -& p_c * i_c >= 0.0, \\quad \\forall t \\in \\{1,\\dots, T\\} +& p_c * i_c \\ge 0.0, \\quad \\forall t \\in \\{1,\\dots, T\\} \\end{align*} ``` """ @@ -565,11 +567,11 @@ struct ConverterACDirectionConstraint <: ConstraintType end """ Struct to create the constraints that decide the flow apparent power limits to the VSC Line. -For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). + The specified constraints are formulated as: ```math \\begin{align*} -& p_c^2 + q_c^2 <= rating^2, \\quad \\forall t \\in \\{1,\\dots, T\\} +& p_c^2 + q_c^2 \\le rating^2, \\quad \\forall t \\in \\{1,\\dots, T\\} \\end{align*} ``` """ @@ -577,7 +579,7 @@ struct FlowApparentPowerLimitConstraint <: ConstraintType end """ Struct to create the constraints that balance the DC Power to the VSC Line. -For more information check [Converter Formulations](@ref PowerSystems.Converter-Formulations). + The specified constraints are formulated as: ```math \\begin{align*} From 789a383bc03f7f073c70059c4edd1e8e59b7d894 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 20 Dec 2024 11:27:52 -0800 Subject: [PATCH 31/34] update converting results of hvdc vars --- src/core/variables.jl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/core/variables.jl b/src/core/variables.jl index e8d72e099..fe5491a3c 100644 --- a/src/core/variables.jl +++ b/src/core/variables.jl @@ -423,21 +423,21 @@ struct HVDCFlowDirectionVariable <: VariableType end """ Struct to dispatch the creation of HVDC Received Flow at From Bus Variables for PWL formulations -Docs abbreviation: ``x`` +Docs abbreviation: ``f^{from}`` """ struct HVDCActivePowerReceivedFromVariable <: VariableType end """ Struct to dispatch the creation of HVDC Received Flow at To Bus Variables for PWL formulations -Docs abbreviation: ``y`` +Docs abbreviation: ``f^{to}`` """ struct HVDCActivePowerReceivedToVariable <: VariableType end """ Struct to dispatch the creation of HVDC Piecewise Loss Variables -Docs abbreviation: ``h`` or ``w`` +Docs abbreviation: ``w`` """ struct HVDCPiecewiseLossVariable <: SparseVariableType end @@ -526,6 +526,10 @@ convert_result_to_natural_units(::Type{FlowActivePowerFromToVariable}) = true convert_result_to_natural_units(::Type{FlowActivePowerToFromVariable}) = true convert_result_to_natural_units(::Type{FlowReactivePowerFromToVariable}) = true convert_result_to_natural_units(::Type{FlowReactivePowerToFromVariable}) = true +convert_result_to_natural_units(::Type{HVDCActiveDCPowerSentFromVariable}) = true +convert_result_to_natural_units(::Type{HVDCActiveDCPowerSentToVariable}) = true +convert_result_to_natural_units(::Type{HVDCReactivePowerSentFromVariable}) = true +convert_result_to_natural_units(::Type{HVDCReactivePowerSentToVariable}) = true convert_result_to_natural_units(::Type{HVDCLosses}) = true convert_result_to_natural_units(::Type{InterfaceFlowSlackUp}) = true convert_result_to_natural_units(::Type{InterfaceFlowSlackDown}) = true From 16385dbd5bf3d4b5db654dfaadd7767dea7d5745 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 20 Dec 2024 11:28:06 -0800 Subject: [PATCH 32/34] update direction of loss balance --- src/devices_models/devices/TwoTerminalDC_branches.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices_models/devices/TwoTerminalDC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl index fe3db1a7c..6f9de2522 100644 --- a/src/devices_models/devices/TwoTerminalDC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -2011,7 +2011,7 @@ function add_constraints!( for t in time_steps constraint[name, t] = JuMP.@constraint( JuMPmodel, - power_from_var[name, t] == -power_to_var[name, t] - losses_var[name, t] + power_from_var[name, t] - losses_var[name, t] == -power_to_var[name, t] ) end end From 4bbd0866c2976794185ff8ef37b72d95c0cb17cd Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 20 Dec 2024 11:38:52 -0800 Subject: [PATCH 33/34] update docs for hvdc formulations --- docs/src/api/PowerSimulations.md | 34 ++ docs/src/formulation_library/Branch.md | 430 ++++++++++++++++++++++++- src/PowerSimulations.jl | 4 + 3 files changed, 466 insertions(+), 2 deletions(-) diff --git a/docs/src/api/PowerSimulations.md b/docs/src/api/PowerSimulations.md index 01b78474e..8a9bdaae0 100644 --- a/docs/src/api/PowerSimulations.md +++ b/docs/src/api/PowerSimulations.md @@ -189,6 +189,28 @@ FlowReactivePowerToFromVariable PhaseShifterAngle HVDCLosses HVDCFlowDirectionVariable +HVDCActivePowerReceivedFromVariable +HVDCActivePowerReceivedToVariable +HVDCPiecewiseLossVariable +HVDCPiecewiseBinaryLossVariable +HVDCActiveDCPowerSentFromVariable +HVDCActiveDCPowerSentToVariable +HVDCReactivePowerSentFromVariable +HVDCReactivePowerSentToVariable +ConverterPowerDirection +DCVoltageFrom +DCVoltageTo +SquaredDCVoltageFrom +SquaredDCVoltageTo +ConverterCurrent +SquaredConverterCurrent +ConverterPositiveCurrent +ConverterNegativeCurrent +ConverterCurrentDirection +AuxBilinearConverterVariableFrom +AuxBilinearSquaredConverterVariableFrom +AuxBilinearConverterVariableTo +AuxBilinearSquaredConverterVariableTo VoltageMagnitude VoltageAngle ``` @@ -281,6 +303,18 @@ FlowRateConstraintFromTo FlowRateConstraintToFrom HVDCPowerBalance NetworkFlowConstraint +ConverterPowerCalculationConstraint +ConverterDirectionConstraint +ConverterCurrentBalanceConstraint +ConverterMcCormickEnvelopes +InterpolationVoltageConstraints +InterpolationCurrentConstraints +InterpolationBilinearConstraints +CurrentAbsoluteValueConstraint +ConverterLossesCalculationConstraint +ConverterPowerBalanceConstraint +ConverterACPowerCalculationConstraint +FlowApparentPowerLimitConstraint RateLimitConstraint PhaseAngleControlLimit ``` diff --git a/docs/src/formulation_library/Branch.md b/docs/src/formulation_library/Branch.md index 5c5def8d3..feca4bfde 100644 --- a/docs/src/formulation_library/Branch.md +++ b/docs/src/formulation_library/Branch.md @@ -12,8 +12,12 @@ 4. [`HVDCTwoTerminalUnbounded`](#HVDCTwoTerminalUnbounded) 5. [`HVDCTwoTerminalLossless`](#HVDCTwoTerminalLossless) 6. [`HVDCTwoTerminalDispatch`](#HVDCTwoTerminalDispatch) - 7. [`PhaseAngleControl`](#PhaseAngleControl) - 8. [Valid configurations](#Valid-configurations) + 7. [`HVDCTwoTerminalPiecewiseLoss`](#HVDCTwoTerminalPiecewiseLoss) + 8. [`HVDCTwoTerminalVSCLoss`](#HVDCTwoTerminalVSCLoss) + 9. [`HVDCTwoTerminalVSCLossBilinear`](#HVDCTwoTerminalVSCLossBilinear) + 10. [`HVDCTwoTerminalVSCLossQuadratic`](#HVDCTwoTerminalVSCLossQuadratic) + 11. [`PhaseAngleControl`](#PhaseAngleControl) + 12. [Valid configurations](#Valid-configurations) ## `StaticBranch` @@ -306,6 +310,428 @@ In addition, the `HVDCLosses` are subtracted to the `from` bus in the `ActivePow * * * + +## `HVDCTwoTerminalPiecewiseLoss` + +Formulation valid for `PTDFPowerModel` Network model + +```@docs +HVDCTwoTerminalPiecewiseLoss +``` + +This formulation creates uses ``S`` segments to define different loss factors (proportional to power flowing through the branch) at pre-determined breakpoints. + +**Variables** + + - [`HVDCActivePowerReceivedFromVariable`](@ref): + + + Bounds: ``[R^\text{from,min}, R^\text{from,max}]`` + + Symbol: ``f^\text{from}`` + - [`HVDCActivePowerReceivedToVariable`](@ref): + + + Bounds: ``[R^\text{to,min}, R^\text{to,max}]`` + + Symbol: ``f^\text{to}`` + - [`HVDCPiecewiseLossVariable`](@ref): + + + Symbol: ``w`` + - [`HVDCPiecewiseBinaryLossVariable`](@ref): + + + Bounds: ``\{0,1\}`` + + Symbol: ``z`` + +**Static Parameters** + + - ``R^\text{from,min}`` = `PowerSystems.get_active_power_limits_from(branch).min` + - ``R^\text{from,max}`` = `PowerSystems.get_active_power_limits_from(branch).max` + - ``R^\text{to,min}`` = `PowerSystems.get_active_power_limits_to(branch).min` + - ``R^\text{to,max}`` = `PowerSystems.get_active_power_limits_to(branch).max` + - ``loss`` = `PowerSystems.get_loss(branch)` + +The `loss` term is a `PowerSystems.PiecewiseIncrementalCurve` that has `S+1` power breakpoints and `S` loss factors for each range. The `PowerSystems.PiecewiseIncrementalCurve` must be defined in system per unit, that is, the power breakpoints normalized by the system base (not in MW), and the `slopes` as a factor of system base power value. Alternatively, a `PowerSystems.LinearCurve` as a way of using a single loss factor. + +**Expressions:** + +Each `HVDCActivePowerReceivedFromVariable` ``f^\text{from}`` and `HVDCActivePowerReceivedToVariable` ``f^\text{to}`` is added to the nodal balance expression `ActivePowerBalance`, by subtracting the received flow to the respective bus. That is, ``f^\text{from}`` subtract the flow to the `from` bus, while ``f^\text{to}`` subtract the flow to the `to` bus. + +**Constraints:** + +Define ``P_{send,s}`` as the HVDC sending end (in pu) for segment `s` and ``lossfactor_s`` as the HVDC proportional loss factor of segment `s`, then the additional auxiliary parameters ``x,y`` are used for a bi-directional two terminal HVDC from bus `i` to bus `j` with each bus can be either sending or receiving end, the MW of the two ends can have the following corresponding segments: + +```math +\begin{align*} + x_1 = -P_{send,S}-P_{send,0}, && y_1= P_{send,S}(1-lossfactor_S) && \\ + \text{...} &&\\ + x_S= -P_{send,1}-P_{send,0}, && y_S= P_{send,1}(1-lossfactor_1) &&\\ + x_{S+1}=-P_{send,0}, && y_{S+1}=0 &&\\ + x_{S+2}=0, && y_{S+2}=-P_{send,0} &&\\ + x_{S+3}= P_{send,1}(1-lossfactor_1), && y_{S+3}= -P_{send,1}-P_{send,0} &&\\ + \text{...} &&\\ + x_{2S+2}= P_{send,S}(1-lossfactor_S), && y_{2S+2} = -P_{send,S}-P_{send,0} && +\end{align*} +``` + +Define ``n=2S+2``, then the following constraints are used to specify the segment: + +```math +\begin{align*} + z_1+z_2+...+z_{n-1} = 1 &&\\ + 0 \le w_i \le z_i \text { for } i=1, ..., n-1 && +\end{align*} +``` +with ``w_{S+1} = 0`` to prevent a solution in the deadband. Then the receiving flows can be computed as: + +```math +\begin{align*} + f^{from}=x_1z_1+(x_2-x_1)w_1+ x_2z_2+(x_3-x_2)w_2 + ... +x_{n-1}z_{n-1}+ (x_n-x_{n-1})w_{n-1} &&\\ + f^{to}=y_1z_1+(y_2-y_1)w_1+ y_2z_2+(y_3-y_2)w_2 + ... +y_{n-1}z_{n-1}+ (y_n-y_{n-1})w_{n-1} && +\end{align*} +``` + +* * * + +## `HVDCTwoTerminalVSCLoss` + +Formulation valid for `PTDFPowerModel` Network model + +```@docs +HVDCTwoTerminalVSCLoss +``` + +**Variables** + + - [`HVDCActiveDCPowerSentFromVariable`](@ref): + + + Bounds: ``[P^\text{from,min}, P^\text{from,max}]`` + + Symbol: ``p_c^\text{from}`` + - [`HVDCActiveDCPowerSentToVariable`](@ref): + + + Bounds: ``[P^\text{to,min}, P^\text{to,max}]`` + + Symbol: ``p_c^\text{to}`` + - [`ConverterPowerDirection`](@ref): + + + Bounds: ``\{0,1\}`` + + Symbol: ``\kappa^p`` + - [`DCVoltageFrom`](@ref): + + + Bounds: ``[V^\text{min}, V^\text{max}]`` + + Symbol: ``v_{dc}^\text{from}`` + - [`DCVoltageTo`](@ref): + + + Bounds: ``[V^\text{min}, V^\text{max}]`` + + Symbol: ``v_{dc}^\text{to}`` + - [`SquaredDCVoltageFrom`](@ref): + + + Bounds: ``[(V^\text{min})^2, (V^\text{max})^2]`` + + Symbol: ``v_{dc}^\text{sq,from}`` + - [`SquaredDCVoltageTo`](@ref): + + + Bounds: ``[(V^\text{min})^2, (V^\text{max})^2]`` + + Symbol: ``v_{dc}^\text{sq,to}`` + - [`ConverterCurrent`](@ref): + + + Bounds: ``[-I^\text{max}, I^\text{max}]`` + + Symbol: ``i`` + - [`SquaredConverterCurrent`](@ref): + + + Bounds: ``[0, (I^\text{max})^2]`` + + Symbol: ``i^\text{sq}`` + - [`ConverterPositiveCurrent`](@ref): + + + Bounds: ``[0, I^\text{max}]`` + + Symbol: ``i^+`` + - [`ConverterNegativeCurrent`](@ref): + + + Bounds: ``[0, I^\text{max}]`` + + Symbol: ``i^-`` + - [`ConverterCurrentDirection`](@ref): + + + Bounds: ``\{0,1\}`` + + Symbol: ``\kappa^i`` + - [`HVDCLosses`](@ref): + + + Symbol: ``p_c^{loss}`` + - [`AuxBilinearConverterVariableFrom`](@ref): + + + Bounds: ``[-I^\text{max}V^\text{min}, I^\text{max}V^\text{max}]`` + + Symbol: ``γ^\text{from}`` + - [`AuxBilinearConverterVariableTo`](@ref): + + + Bounds: ``[-I^\text{max}V^\text{min}, I^\text{max}V^\text{max}]`` + + Symbol: ``γ^\text{to}`` + - [`AuxBilinearSquaredConverterVariableFrom`](@ref): + + + Bounds: ``[0, (I^\text{max})^2(V^\text{max})^2]`` + + Symbol: ``γ^\text{sq,from}`` + - [`AuxBilinearSquaredConverterVariableFrom`](@ref): + + + Bounds: ``[(V^\text{min})^2, (V^\text{max})^2]`` + + Symbol: ``v_{dc}^\text{sq,to}`` + +And the additional continuous interpolation variables for voltage, current and bilinear auxiliary variable, denoted as ``\delta^v, \delta^i, \delta^\gamma``, and additional binary interpolation variables for voltage current and bilinear auxiliary variable, denoted as ``z^v, z^i, z^\gamma`` . + +**Static Parameters** + + - ``P^\text{from,min}`` = `PowerSystems.get_active_power_limits_from(branch).min` + - ``P^\text{from,max}`` = `PowerSystems.get_active_power_limits_from(branch).max` + - ``P^\text{to,min}`` = `PowerSystems.get_active_power_limits_to(branch).min` + - ``P^\text{to,max}`` = `PowerSystems.get_active_power_limits_to(branch).max` + - ``V^\text{min}`` = `PowerSystems.get_voltage_limits(branch).min` + - ``V^\text{max}`` = `PowerSystems.get_voltage_limits(branch).max` + - ``I^{max}`` = `PowerSystems.max_dc_current(branch)` + - ``loss`` = `PowerSystems.get_loss(branch)` + - ``g`` = `PowerSystems.get_g(branch)` + +The `loss` term is a `PowerSystems.QuadraticCurve` that has the quadratic term ``a``, proportional term ``b`` and constant term ``c``. In addition, the interpolation is done by specifying the number of segments for voltage, current and bilinear term independently as attributes of the `DeviceModel`. The breakpoints are done by evenly splitting the available range for each variable. By default 3 voltage segments, 6 current segments and 10 bilinear segments are used. + +**Expressions:** + +Each `HVDCActiveDCPowerSentFromVariable` ``f^\text{from}`` and `HVDCActiveDCPowerSentToVariable` ``p^\text{to}`` is added to the nodal balance expression `ActivePowerBalance`, by subtracting the received flow to the respective bus. That is, ``p^\text{from}`` subtract the flow to the `from` bus, while ``p^\text{to}`` subtract the flow to the `to` bus. In addition, the losses are ``p^{loss}`` are subtracted to both sending and receiving bus, as it is assumed that converter losses occurs in both ends. + +**Constraints:** + +```math +\begin{align*} +\gamma_{c, t}^\text{from} &= v_{c, t}^\text{from} + i_{c, t} & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + p_{c, t}^\text{from} &= \frac{1}{2}\left(\gamma^\text{sq,from}_{c, t} - v^\text{sq,from}_{c, t} - i^\text{sq}_{c, t} \right) & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + \gamma_{c, t}^\text{to} &= v_{c, t}^\text{to} - i_{c, t} & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + p_{c, t}^\text{to} &= \frac{1}{2}\left(\gamma^\text{sq,to}_{c, t} - v^\text{sq,to}_{c, t} - i^\text{sq}_{c, t} \right) & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} +\end{align*} +``` + +```math +\begin{align*} + (-I^{max}_c) \left(1 - \kappa_{c, t}\right) &\le i_{c, t} \le I^{max}_c \kappa_{c, t}\\ + P^\text{min,from}_c \left(1 - \kappa_{c, t} \right) &\le p_{b, t} \le P^\text{max,from}_c \kappa_{c, t}\\ + P^\text{min,to}_c \kappa_{c, t} &\le p_{b, t} \le P^\text{max,to}_c (1 - \kappa_{c, t}) +\end{align*} +``` + +```math +\begin{align*} + i_{c, t} &= \frac{1}{r_\ell} (v_{c,t}^\text{from} - v_{c,t}^\text{to}) & \forall \ell \in \mathcal{L}, \ \forall t \in \mathcal{T} +\end{align*} +``` + +```math +\begin{align*} + p_{c, t}^\text{from} &\ge V^{min} i_{c, t} + v_{c, t}^\text{from} (-I^{max}_{c}) - (-I^{max}_{c}V^{min})& \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + p_{c, t}^\text{from} &\ge V^{max} i_{c, t} + v_{c, t}^\text{from}(I^{max}_{c}) - (I^{max}_{c}V^{max})& \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + p_{c, t}^\text{from} &\le V^{max} i_{c, t} + v_{c, t}^\text{from}(-I^{max}_{c}) - (-I^{max}_{c}V^{max}) & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + p_{c, t}^\text{from} &\leq V^{min} i_{c, t} + v_{c, t}^\text{from}(I^{max}_{c}) - (I^{max}_{c}V^{min})& \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} \\ + p_{c, t}^\text{to} &\ge V^{min} (-i_{c, t}) + v_{c, t}^\text{to} (-I^{max}_{c}) - (-I^{max}_{c}V^{min})& \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + p_{c, t}^\text{to} &\ge V^{max} (-i_{c, t}) + v_{c, t}^\text{to}(I^{max}_{c}) - (I^{max}_{c}V^{max})& \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + p_{c, t}^\text{to} &\le V^{max} (-i_{c, t}) + v_{c, t}^\text{to}(-I^{max}_{c}) - (-I^{max}_{c}V^{max}) & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + p_{c, t}^\text{to} &\leq V^{min} (-i_{c, t}) + v_{c, t}^\text{to}(I^{max}_{c}) - (I^{max}_{c}V^{min})& \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} +\end{align*} +``` + +```math +\begin{align*} + v_{c, t}^\text{from} &= V^{min} + \sum_{k \in \mathcal{K}_v} \left(V_{c, k} - V_{c, {k-1}}\right) \delta^\text{v,from}_{c, k, t}\\ + v^\text{sq,from}_{c, t} &= {V^{min}}^2 + \sum_{k \in \mathcal{K}_\gamma} \left(V^{sq}_{c, k} - V^{sq}_{c, {k-1}}\right) \delta^\text{v,from}_{c, k, t}& \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + 0 &\le \delta^\text{v,from}_{c, k, t} \le 1 & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^\text{v,from}_{k, c, t} &\ge \delta^\text{v,from}_{c, {k + 1}, t} & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^\text{v,from}_{k, c, t} &\le \delta^\text{v,from}_{c, k, t} & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^\text{v,from}_{k, c, t} &\in \left\{ 0, 1 \right\} & \forall k \in \mathcal{K}^v, \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} \\ + v_{c, t}^\text{to} &= V^{min} + \sum_{k \in \mathcal{K}_\gamma} \left(V_{c, k} - V_{c, {k-1}}\right) \delta^\text{v,to}_{c, k, t}\\ + v^\text{sq,to}_{c, t} &= {V^{min}}^2 + \sum_{k \in \mathcal{K}_v} \left(V^{sq}_{c, k} - V^{sq}_{c, {k-1}}\right) \delta^\text{v,to}_{c, k, t}& \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + 0 &\le \delta^\text{v,to}_{c, k, t} \le 1 & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^\text{v,to}_{k, c, t} &\ge \delta^\text{v,to}_{c, {k + 1}, t} & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^\text{v,to}_{k, c, t} &\le \delta^\text{v,to}_{c, k, t} & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^\text{v,to}_{k, c, t} &\in \left\{ 0, 1 \right\} & \forall k \in \mathcal{K}_v, \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} +\end{align*} +``` + +```math +\begin{align*} + i_{c, t} &= I^{min} + \sum_{k \in \mathcal{K}_i} \left(I_{c, k} - I_{c, {k-1}}\right) \delta^\text{i,from}_{c, k, t}\\ + i^\text{sq,from}_{c, t} &= {I^{min}}^2 + \sum_{k \in \mathcal{K}_i} \left(I^{sq}_{c, k} - I^{sq}_{c, {k-1}}\right) \delta^\text{i,from}_{c, k, t}& \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + 0 &\le \delta^\text{i,from}_{c, k, t} \le 1 & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^\text{i}_{k, c, t} &\ge \delta^\text{i}_{c, {k + 1}, t} & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^\text{i}_{k, c, t} &\le \delta^\text{i}_{c, k, t} & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^\text{i}_{k, c, t} &\in \left\{ 0, 1 \right\} & \forall k \in \mathcal{K}_i, \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} +\end{align*} +``` + +```math +\begin{align*} + \gamma_{c, t}^\text{from} &= \Gamma^\text{min} + \sum_{k \in \mathcal{K}_\gamma} \left(\Gamma_{c, k} - \Gamma_{c, {k-1}}\right) \delta^{\gamma\text{,from}}_{c, k, t}\\ + \gamma^\text{sq,from}_{c, t} &= {\Gamma^\text{min}}^2 + \sum_{k \in \mathcal{K}_v} \left(\Gamma^{sq}_{c, k} - \Gamma^{sq}_{c, {k-1}}\right) \delta^{\gamma\text{,from}}_{c, k, t}& \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + 0 &\le \delta^{\gamma\text{,from}}_{c, k, t} \le 1 & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^{\gamma\text{,from}}_{k, c, t} &\ge \delta^{\gamma\text{,from}}_{c, {k + 1}, t} & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^{\gamma\text{,from}}_{k, c, t} &\le \delta^{\gamma\text{,from}}_{c, k, t} & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^{\gamma\text{,from}}_{k, c, t} &\in \left\{ 0, 1 \right\} & \forall k \in \mathcal{K}_\gamma, \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} \\ + \gamma_{c, t}^\text{to} &= \Gamma^\text{min} + \sum_{k \in \mathcal{K}_\gamma} \left(\Gamma_{c, k} - \Gamma_{c, {k-1}}\right) \delta^{\gamma\text{,to}}_{c, k, t}\\ + \gamma^\text{sq,to}_{c, t} &= {\Gamma^\text{min}}^2 + \sum_{k \in \mathcal{K}_v} \left(\Gamma^{sq}_{c, k} - \Gamma^{sq}_{c, {k-1}}\right) \delta^{\gamma\text{,to}}_{c, k, t}& \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + 0 &\le \delta^{\gamma\text{,to}}_{c, k, t} \le 1 & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^{\gamma\text{,to}}_{k, c, t} &\ge \delta^{\gamma\text{,to}}_{c, {k + 1}, t} & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^{\gamma\text{,to}}_{k, c, t} &\le \delta^{\gamma\text{,to}}_{c, k, t} & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + z^{\gamma\text{,to}}_{k, c, t} &\in \left\{ 0, 1 \right\} & \forall k \in \mathcal{K}_\gamma, \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} +\end{align*} +``` + +```math +\begin{align*} + i_{c,t} &= i_{c,t}^+ - i_{c,t}^-, & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + i_{c,t}^+ &\le I_c^{max} \nu_{c,t} , & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T}\\ + i_{c,t}^- &\le I_c^{max}(1 - \nu_{c,t}), & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} +\end{align*} +``` + +```math +\begin{align*} + p_{c,t}^\text{loss} = a_c + b_c (i_{c,t}^+ + i_{c,t}^-) + c_c i_{c,t}^\text{sq}, & \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} +\end{align*} +``` + + +* * * + +## `HVDCTwoTerminalVSCLossBilinear` + +Formulation valid for `ACPowerModel` Network model + +```@docs +HVDCTwoTerminalVSCLossBilinear +``` + +**Variables** + + - [`HVDCActiveDCPowerSentFromVariable`](@ref): + + + Bounds: ``[P^\text{from,min}, P^\text{from,max}]`` + + Symbol: ``p_c^\text{from}`` + - [`HVDCActiveDCPowerSentToVariable`](@ref): + + + Bounds: ``[P^\text{to,min}, P^\text{to,max}]`` + + Symbol: ``p_c^\text{to}`` + - [`HVDCReactivePowerSentFromVariable`](@ref): + + + Bounds: ``[Q^\text{from,min}, Q^\text{from,max}]`` + + Symbol: ``q_c^\text{from}`` + - [`HVDCReactivePowerSentToVariable`](@ref): + + + Bounds: ``[Q^\text{to,min}, Q^\text{to,max}]`` + + Symbol: ``q_c^\text{to}`` + - [`DCVoltageFrom`](@ref): + + + Bounds: ``[V^\text{min}, V^\text{max}]`` + + Symbol: ``v_{dc}^\text{from}`` + - [`DCVoltageTo`](@ref): + + + Bounds: ``[V^\text{min}, V^\text{max}]`` + + Symbol: ``v_{dc}^\text{to}`` + - [`ConverterCurrent`](@ref): + + + Bounds: ``[-I^\text{max}, I^\text{max}]`` + + Symbol: ``i`` + - [`HVDCLosses`](@ref): + + + Symbol: ``p_c^{loss}`` + + +**Static Parameters** + + - ``P^\text{from,min}`` = `PowerSystems.get_active_power_limits_from(branch).min` + - ``P^\text{from,max}`` = `PowerSystems.get_active_power_limits_from(branch).max` + - ``P^\text{to,min}`` = `PowerSystems.get_active_power_limits_to(branch).min` + - ``P^\text{to,max}`` = `PowerSystems.get_active_power_limits_to(branch).max` + - ``Q^\text{from,min}`` = `PowerSystems.get_reactive_power_limits_from(branch).min` + - ``Q^\text{from,max}`` = `PowerSystems.get_reactive_power_limits_from(branch).max` + - ``Q^\text{to,min}`` = `PowerSystems.get_reactive_power_limits_to(branch).min` + - ``Q^\text{to,max}`` = `PowerSystems.get_reactive_power_limits_to(branch).max` + - ``V^\text{min}`` = `PowerSystems.get_voltage_limits(branch).min` + - ``V^\text{max}`` = `PowerSystems.get_voltage_limits(branch).max` + - ``I^{max}`` = `PowerSystems.max_dc_current(branch)` + - ``loss`` = `PowerSystems.get_loss(branch)` + - ``g`` = `PowerSystems.get_g(branch)` + +The `loss` term is a `PowerSystems.QuadraticCurve` that has the quadratic term ``a``, proportional term ``b`` and constant term ``c``. + +**Expressions:** + +Each `HVDCActiveDCPowerSentFromVariable` ``p^\text{from}`` and `HVDCActiveDCPowerSentToVariable` ``p^\text{to}`` is added to the nodal balance expression `ActivePowerBalance`, by subtracting the received flow to the respective bus. That is, ``p^\text{from}`` subtract the flow to the `from` bus, while ``p^\text{to}`` subtract the flow to the `to` bus. Similarly for the reactive power variables. In addition, the losses are ``p^{loss}`` are subtracted to both sending and receiving bus, as it is assumed that converter losses occurs in both ends. + +**Constraints:** + +```math +\begin{align*} + p_{c,t}^{from} = v_{c,t}^{from} \cdot i_{c,t}, & \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} \\ + p_{c,t}^{to} = v_{c,t}^{from} \cdot (-i_{c,t}), & \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} \\ + i_{c, t} = \frac{1}{r_\ell} (v_{c,t}^\text{from} - v_{c,t}^\text{to}), & \ \forall \ell \in \mathcal{L}_c, \ \forall t \in \mathcal{T} \\ + p_{c,t}^\text{loss} = a_c + b_c |i_{c,t}| + c_c i_{c,t}^2, & \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} \\ + (p_{c,t}^{from})^2 + (q_{c,t}^{from})^2 \le \text{rating}^2, & \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} \\ + (p_{c,t}^{to})^2 + (q_{c,t}^{to})^2 \le \text{rating}^2, & \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} +\end{align*} + +``` + +* * * + +## `HVDCTwoTerminalVSCLossQuadratic` + +Formulation valid for `ACPowerModel` Network model + +```@docs +HVDCTwoTerminalVSCLossQuadratic +``` + +**Variables** + + - [`HVDCActiveDCPowerSentFromVariable`](@ref): + + + Bounds: ``[P^\text{from,min}, P^\text{from,max}]`` + + Symbol: ``p_c^\text{from}`` + - [`HVDCActiveDCPowerSentToVariable`](@ref): + + + Bounds: ``[P^\text{to,min}, P^\text{to,max}]`` + + Symbol: ``p_c^\text{to}`` + - [`HVDCReactivePowerSentFromVariable`](@ref): + + + Bounds: ``[Q^\text{from,min}, Q^\text{from,max}]`` + + Symbol: ``q_c^\text{from}`` + - [`HVDCReactivePowerSentToVariable`](@ref): + + + Bounds: ``[Q^\text{to,min}, Q^\text{to,max}]`` + + Symbol: ``q_c^\text{to}`` + - [`HVDCLosses`](@ref): + + + Symbol: ``p_c^{loss}`` + +**Static Parameters** + + - ``P^\text{from,min}`` = `PowerSystems.get_active_power_limits_from(branch).min` + - ``P^\text{from,max}`` = `PowerSystems.get_active_power_limits_from(branch).max` + - ``P^\text{to,min}`` = `PowerSystems.get_active_power_limits_to(branch).min` + - ``P^\text{to,max}`` = `PowerSystems.get_active_power_limits_to(branch).max` + - ``Q^\text{from,min}`` = `PowerSystems.get_reactive_power_limits_from(branch).min` + - ``Q^\text{from,max}`` = `PowerSystems.get_reactive_power_limits_from(branch).max` + - ``Q^\text{to,min}`` = `PowerSystems.get_reactive_power_limits_to(branch).min` + - ``Q^\text{to,max}`` = `PowerSystems.get_reactive_power_limits_to(branch).max` + - ``loss`` = `PowerSystems.get_loss(branch)` + +The `loss` term is a `PowerSystems.QuadraticCurve` that has the quadratic term ``a``, proportional term ``b`` and constant term ``c``. + +**Expressions:** + +Each `HVDCActiveDCPowerSentFromVariable` ``p^\text{from}`` and `HVDCActiveDCPowerSentToVariable` ``p^\text{to}`` is added to the nodal balance expression `ActivePowerBalance`, by subtracting the received flow to the respective bus. That is, ``p^\text{from}`` subtract the flow to the `from` bus, while ``p^\text{to}`` subtract the flow to the `to` bus. Similarly for the reactive power variables. + +**Constraints:** + +The quadratic model only approximates losses in the `from` side of the line, proportional to the `from` power sent or received. + +```math +\begin{align*} + p_{c,t}^{from} - p_{c,t}^{loss} = - p_{c,t}^{to}, & \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} \\ + p_{c,t}^\text{loss} = a_c + b_c |p_{c,t}^{from}| + c_c (p_{c,t}^{from})^2 & \forall c \in \mathcal{C}, & \ \forall t \in \mathcal{T} \\ + (p_{c,t}^{from})^2 + (q_{c,t}^{from})^2 \le \text{rating}^2, & \ \forall c \in \mathcal{C}, & \ \forall t \in \mathcal{T} \\ + (p_{c,t}^{to})^2 + (q_{c,t}^{to})^2 \le \text{rating}^2, & \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} +\end{align*} + +``` + +* * * + ## `PhaseAngleControl` Formulation valid for `PTDFPowerModel` Network model diff --git a/src/PowerSimulations.jl b/src/PowerSimulations.jl index 878b742a7..0edb7256e 100644 --- a/src/PowerSimulations.jl +++ b/src/PowerSimulations.jl @@ -237,6 +237,10 @@ export LowerBoundFeedForwardSlack export InterfaceFlowSlackUp export InterfaceFlowSlackDown export PieceWiseLinearCostVariable +export HVDCActivePowerReceivedFromVariable +export HVDCActivePowerReceivedToVariable +export HVDCPiecewiseLossVariable +export HVDCPiecewiseBinaryLossVariable export HVDCActiveDCPowerSentFromVariable export HVDCActiveDCPowerSentToVariable export HVDCReactivePowerSentFromVariable From 63fbdf67c2ebbe78af947d79f1da45a645eb9c14 Mon Sep 17 00:00:00 2001 From: rodrigomha Date: Fri, 20 Dec 2024 11:42:53 -0800 Subject: [PATCH 34/34] formatter --- docs/src/formulation_library/Branch.md | 20 +++++++++---------- .../devices/TwoTerminalDC_branches.jl | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/src/formulation_library/Branch.md b/docs/src/formulation_library/Branch.md index feca4bfde..73f8a6c43 100644 --- a/docs/src/formulation_library/Branch.md +++ b/docs/src/formulation_library/Branch.md @@ -15,9 +15,9 @@ 7. [`HVDCTwoTerminalPiecewiseLoss`](#HVDCTwoTerminalPiecewiseLoss) 8. [`HVDCTwoTerminalVSCLoss`](#HVDCTwoTerminalVSCLoss) 9. [`HVDCTwoTerminalVSCLossBilinear`](#HVDCTwoTerminalVSCLossBilinear) - 10. [`HVDCTwoTerminalVSCLossQuadratic`](#HVDCTwoTerminalVSCLossQuadratic) - 11. [`PhaseAngleControl`](#PhaseAngleControl) - 12. [Valid configurations](#Valid-configurations) +10. [`HVDCTwoTerminalVSCLossQuadratic`](#HVDCTwoTerminalVSCLossQuadratic) +11. [`PhaseAngleControl`](#PhaseAngleControl) +12. [Valid configurations](#Valid-configurations) ## `StaticBranch` @@ -310,7 +310,6 @@ In addition, the `HVDCLosses` are subtracted to the `from` bus in the `ActivePow * * * - ## `HVDCTwoTerminalPiecewiseLoss` Formulation valid for `PTDFPowerModel` Network model @@ -327,6 +326,7 @@ This formulation creates uses ``S`` segments to define different loss factors (p + Bounds: ``[R^\text{from,min}, R^\text{from,max}]`` + Symbol: ``f^\text{from}`` + - [`HVDCActivePowerReceivedToVariable`](@ref): + Bounds: ``[R^\text{to,min}, R^\text{to,max}]`` @@ -378,6 +378,7 @@ Define ``n=2S+2``, then the following constraints are used to specify the segmen 0 \le w_i \le z_i \text { for } i=1, ..., n-1 && \end{align*} ``` + with ``w_{S+1} = 0`` to prevent a solution in the deadband. Then the receiving flows can be computed as: ```math @@ -403,6 +404,7 @@ HVDCTwoTerminalVSCLoss + Bounds: ``[P^\text{from,min}, P^\text{from,max}]`` + Symbol: ``p_c^\text{from}`` + - [`HVDCActiveDCPowerSentToVariable`](@ref): + Bounds: ``[P^\text{to,min}, P^\text{to,max}]`` @@ -584,7 +586,6 @@ Each `HVDCActiveDCPowerSentFromVariable` ``f^\text{from}`` and `HVDCActiveDCPowe \end{align*} ``` - * * * ## `HVDCTwoTerminalVSCLossBilinear` @@ -601,6 +602,7 @@ HVDCTwoTerminalVSCLossBilinear + Bounds: ``[P^\text{from,min}, P^\text{from,max}]`` + Symbol: ``p_c^\text{from}`` + - [`HVDCActiveDCPowerSentToVariable`](@ref): + Bounds: ``[P^\text{to,min}, P^\text{to,max}]`` @@ -629,7 +631,6 @@ HVDCTwoTerminalVSCLossBilinear + Symbol: ``p_c^{loss}`` - **Static Parameters** - ``P^\text{from,min}`` = `PowerSystems.get_active_power_limits_from(branch).min` @@ -663,7 +664,6 @@ Each `HVDCActiveDCPowerSentFromVariable` ``p^\text{from}`` and `HVDCActiveDCPowe (p_{c,t}^{from})^2 + (q_{c,t}^{from})^2 \le \text{rating}^2, & \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} \\ (p_{c,t}^{to})^2 + (q_{c,t}^{to})^2 \le \text{rating}^2, & \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} \end{align*} - ``` * * * @@ -682,6 +682,7 @@ HVDCTwoTerminalVSCLossQuadratic + Bounds: ``[P^\text{from,min}, P^\text{from,max}]`` + Symbol: ``p_c^\text{from}`` + - [`HVDCActiveDCPowerSentToVariable`](@ref): + Bounds: ``[P^\text{to,min}, P^\text{to,max}]`` @@ -714,11 +715,11 @@ The `loss` term is a `PowerSystems.QuadraticCurve` that has the quadratic term ` **Expressions:** -Each `HVDCActiveDCPowerSentFromVariable` ``p^\text{from}`` and `HVDCActiveDCPowerSentToVariable` ``p^\text{to}`` is added to the nodal balance expression `ActivePowerBalance`, by subtracting the received flow to the respective bus. That is, ``p^\text{from}`` subtract the flow to the `from` bus, while ``p^\text{to}`` subtract the flow to the `to` bus. Similarly for the reactive power variables. +Each `HVDCActiveDCPowerSentFromVariable` ``p^\text{from}`` and `HVDCActiveDCPowerSentToVariable` ``p^\text{to}`` is added to the nodal balance expression `ActivePowerBalance`, by subtracting the received flow to the respective bus. That is, ``p^\text{from}`` subtract the flow to the `from` bus, while ``p^\text{to}`` subtract the flow to the `to` bus. Similarly for the reactive power variables. **Constraints:** -The quadratic model only approximates losses in the `from` side of the line, proportional to the `from` power sent or received. +The quadratic model only approximates losses in the `from` side of the line, proportional to the `from` power sent or received. ```math \begin{align*} @@ -727,7 +728,6 @@ The quadratic model only approximates losses in the `from` side of the line, pro (p_{c,t}^{from})^2 + (q_{c,t}^{from})^2 \le \text{rating}^2, & \ \forall c \in \mathcal{C}, & \ \forall t \in \mathcal{T} \\ (p_{c,t}^{to})^2 + (q_{c,t}^{to})^2 \le \text{rating}^2, & \ \forall c \in \mathcal{C}, \ \forall t \in \mathcal{T} \end{align*} - ``` * * * diff --git a/src/devices_models/devices/TwoTerminalDC_branches.jl b/src/devices_models/devices/TwoTerminalDC_branches.jl index 6f9de2522..c560e042e 100644 --- a/src/devices_models/devices/TwoTerminalDC_branches.jl +++ b/src/devices_models/devices/TwoTerminalDC_branches.jl @@ -2011,7 +2011,7 @@ function add_constraints!( for t in time_steps constraint[name, t] = JuMP.@constraint( JuMPmodel, - power_from_var[name, t] - losses_var[name, t] == -power_to_var[name, t] + power_from_var[name, t] - losses_var[name, t] == -power_to_var[name, t] ) end end