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