From af19c4093edff65ecccb692835b02865c7d1e5ec Mon Sep 17 00:00:00 2001 From: Youssef Miftah Date: Wed, 1 Jan 2025 21:38:51 +1100 Subject: [PATCH 1/4] extend slack definition for AreaBalance equations + test --- .../devices/common/add_to_expression.jl | 25 +++++++++++++ test/test_network_constructors.jl | 35 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index a7fcd73f8..d680bc6bd 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -1462,6 +1462,31 @@ function add_to_expression!( return end +function add_to_expression!( + container::OptimizationContainer, + ::Type{T}, + ::Type{U}, + sys::PSY.System, + ::NetworkModel{W}, +) where { + T <: ActivePowerBalance, + U <: Union{SystemBalanceSlackUp, SystemBalanceSlackDown}, + W <: AreaBalancePowerModel, +} + variable = get_variable(container, U(), PSY.Area) + expression = get_expression(container, T(), PSY.Area) + @assert_op length(axes(variable, 1)) == length(axes(expression, 1)) + # We uses axis here to avoid double addition of the slacks to the aggregated buses + for t in get_time_steps(container), n in axes(expression, 1) + _add_to_jump_expression!( + expression[n, t], + variable[n, t], + get_variable_multiplier(U(), PSY.Area, W), + ) + end + return +end + function add_to_expression!( container::OptimizationContainer, ::Type{T}, diff --git a/test/test_network_constructors.jl b/test/test_network_constructors.jl index 70393c13c..21a4e5907 100644 --- a/test/test_network_constructors.jl +++ b/test/test_network_constructors.jl @@ -712,6 +712,41 @@ end end end +@testset "2 Areas AreaBalance PowerModel - with slacks" begin + sys = build_system(PSITestSystems, "c_sys5_uc") + + # Extend the system with two areas + areas = [Area("Area_1", 0, 0, 0), Area("Area_2", 0, 0, 0)] + add_components!(sys, areas) + for (i, comp) in enumerate(get_components(ACBus, sys)) + (i < 3) ? set_area!(comp, areas[1]) : set_area!(comp, areas[2]) + end + # Deactivate generators on Area 1. As there is no area interchange defined, + # Slacks will be required for fesibility + for gen in get_components(x -> (get_area(get_bus(x)) == areas[1]), Generator, sys) + set_available!(gen, false) + end + + template = get_thermal_dispatch_template_network( + NetworkModel(AreaBalancePowerModel, use_slacks=true) + ) + ps_model = DecisionModel(template, c_sys; optimizer = HiGHS_optimizer) + + @test build!(ps_model; output_dir = mktempdir(; cleanup = true)) == + PSI.ModelBuildStatus.BUILT + @test solve!(ps_model) == PSI.RunStatus.SUCCESSFULLY_FINALIZED + + opt_container = PSI.get_optimization_container(ps_model) + copper_plate_constraints = + PSI.get_constraint(opt_container, CopperPlateBalanceConstraint(), PSY.Area) + @test size(copper_plate_constraints) == (2, 24) + + results = OptimizationProblemResults(ps_model) + slacks_up = read_variable(results, "SystemBalanceSlackUp__Area") + @test all(slacks_up[!, "Area_1"] .> 0.) + @test all(slacks_up[!, "Area_2"] .≈ 0.) +end + @testset "2 Areas AreaBalance PowerModel" begin c_sys = PSB.build_system(PSISystems, "two_area_pjm_DA") transform_single_time_series!(c_sys, Hour(24), Hour(1)) From 56acd3a4151d1e83b4f2a000d993d1757979f9da Mon Sep 17 00:00:00 2001 From: Youssef Miftah Date: Wed, 1 Jan 2025 21:47:28 +1100 Subject: [PATCH 2/4] remove unrelated comment --- src/devices_models/devices/common/add_to_expression.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index d680bc6bd..3b915f9fb 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -1476,7 +1476,6 @@ function add_to_expression!( variable = get_variable(container, U(), PSY.Area) expression = get_expression(container, T(), PSY.Area) @assert_op length(axes(variable, 1)) == length(axes(expression, 1)) - # We uses axis here to avoid double addition of the slacks to the aggregated buses for t in get_time_steps(container), n in axes(expression, 1) _add_to_jump_expression!( expression[n, t], From c5d19a5552a8650aa87d16d49aa8449692b32529 Mon Sep 17 00:00:00 2001 From: Youssef Miftah Date: Thu, 2 Jan 2025 21:13:31 +1100 Subject: [PATCH 3/4] typo test --- test/test_network_constructors.jl | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test/test_network_constructors.jl b/test/test_network_constructors.jl index 21a4e5907..71abe969b 100644 --- a/test/test_network_constructors.jl +++ b/test/test_network_constructors.jl @@ -713,17 +713,16 @@ end end @testset "2 Areas AreaBalance PowerModel - with slacks" begin - sys = build_system(PSITestSystems, "c_sys5_uc") - + c_sys = build_system(PSITestSystems, "c_sys5_uc") # Extend the system with two areas areas = [Area("Area_1", 0, 0, 0), Area("Area_2", 0, 0, 0)] - add_components!(sys, areas) - for (i, comp) in enumerate(get_components(ACBus, sys)) + add_components!(c_sys, areas) + for (i, comp) in enumerate(get_components(ACBus, c_sys)) (i < 3) ? set_area!(comp, areas[1]) : set_area!(comp, areas[2]) end - # Deactivate generators on Area 1. As there is no area interchange defined, - # Slacks will be required for fesibility - for gen in get_components(x -> (get_area(get_bus(x)) == areas[1]), Generator, sys) + # Deactivate generators on Area 1: as there is no area interchange defined, + # slacks will be required for fesibility + for gen in get_components(x -> (get_area(get_bus(x)) == areas[1]), Generator, c_sys) set_available!(gen, false) end From 3e48499698d6e6baa3f85a0fe4294ed2e0f97b35 Mon Sep 17 00:00:00 2001 From: Youssef Miftah Date: Thu, 2 Jan 2025 21:57:57 +1100 Subject: [PATCH 4/4] typo --- test/test_network_constructors.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_network_constructors.jl b/test/test_network_constructors.jl index 71abe969b..e16df3748 100644 --- a/test/test_network_constructors.jl +++ b/test/test_network_constructors.jl @@ -721,7 +721,7 @@ end (i < 3) ? set_area!(comp, areas[1]) : set_area!(comp, areas[2]) end # Deactivate generators on Area 1: as there is no area interchange defined, - # slacks will be required for fesibility + # slacks will be required for feasibility for gen in get_components(x -> (get_area(get_bus(x)) == areas[1]), Generator, c_sys) set_available!(gen, false) end