From af19c4093edff65ecccb692835b02865c7d1e5ec Mon Sep 17 00:00:00 2001 From: Youssef Miftah Date: Wed, 1 Jan 2025 21:38:51 +1100 Subject: [PATCH 1/9] 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/9] 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/9] 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/9] 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 From 82835157156275b6119660f4ca27bc9875f71832 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sat, 4 Jan 2025 18:25:37 -0700 Subject: [PATCH 5/9] add debug code --- .../devices/common/add_to_expression.jl | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index a7fcd73f8..91a666e8b 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -236,14 +236,18 @@ function add_to_expression!( variable = get_variable(container, U(), V) expression = get_expression(container, T(), PSY.ACBus) radial_network_reduction = get_radial_network_reduction(network_model) - for d in devices, t in get_time_steps(container) + for d in devices name = PSY.get_name(d) + @show PSY.get_bus(d) bus_no = PNM.get_mapped_bus_number(radial_network_reduction, PSY.get_bus(d)) - _add_to_jump_expression!( - expression[bus_no, t], - variable[name, t], - get_variable_multiplier(U(), V, W()), - ) + @show bus_no + for t in get_time_steps(container) + _add_to_jump_expression!( + expression[bus_no, t], + variable[name, t], + get_variable_multiplier(U(), V, W()), + ) + end end return end From 8aa3bba1cc7e65430bc3060ce4002e4a33c3a943 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sat, 4 Jan 2025 18:38:17 -0700 Subject: [PATCH 6/9] add assertion call --- src/devices_models/devices/common/add_to_expression.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index 91a666e8b..7a7af400c 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -236,6 +236,7 @@ function add_to_expression!( variable = get_variable(container, U(), V) expression = get_expression(container, T(), PSY.ACBus) radial_network_reduction = get_radial_network_reduction(network_model) + @assert !isempty(radial_network_reduction) for d in devices name = PSY.get_name(d) @show PSY.get_bus(d) From e173a0faea8f8f6e7c34124937156746cb12c760 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 5 Jan 2025 13:22:42 -0700 Subject: [PATCH 7/9] add error message --- src/core/network_model.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/core/network_model.jl b/src/core/network_model.jl index eaaa0154f..ceec7155d 100644 --- a/src/core/network_model.jl +++ b/src/core/network_model.jl @@ -129,6 +129,16 @@ function instantiate_network_model( model.PTDF_matrix = PNM.PTDF(sys; reduce_radial_branches = model.reduce_radial_branches) end + + if !model.reduce_radial_branches && !isempty(model.PTDF_matrix.radial_network_reduction) + throw( + IS.ConflictingInputsError( + "The provided PTDF Matrix has reduced radial branches and mismatches the network \\ + model specification radial_network_reduction = false. Set the keyword argument \\ + radial_network_reduction = true in your network model" ) + ) + end + if model.reduce_radial_branches @assert !isempty(model.PTDF_matrix.radial_network_reduction) model.radial_network_reduction = model.PTDF_matrix.radial_network_reduction From fdd06999775e01d67c7dd4d2c9e67a304f32541d Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 5 Jan 2025 15:19:49 -0700 Subject: [PATCH 8/9] remove debugging code --- src/core/network_model.jl | 3 ++- src/devices_models/devices/common/add_to_expression.jl | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/core/network_model.jl b/src/core/network_model.jl index ceec7155d..33f3e1db7 100644 --- a/src/core/network_model.jl +++ b/src/core/network_model.jl @@ -135,7 +135,7 @@ function instantiate_network_model( IS.ConflictingInputsError( "The provided PTDF Matrix has reduced radial branches and mismatches the network \\ model specification radial_network_reduction = false. Set the keyword argument \\ - radial_network_reduction = true in your network model" ) + radial_network_reduction = true in your network model"), ) end @@ -143,6 +143,7 @@ function instantiate_network_model( @assert !isempty(model.PTDF_matrix.radial_network_reduction) model.radial_network_reduction = model.PTDF_matrix.radial_network_reduction end + get_PTDF_matrix(model).subnetworks model.subnetworks = deepcopy(get_PTDF_matrix(model).subnetworks) if length(model.subnetworks) > 1 diff --git a/src/devices_models/devices/common/add_to_expression.jl b/src/devices_models/devices/common/add_to_expression.jl index 7a7af400c..c46cf352c 100644 --- a/src/devices_models/devices/common/add_to_expression.jl +++ b/src/devices_models/devices/common/add_to_expression.jl @@ -236,12 +236,9 @@ function add_to_expression!( variable = get_variable(container, U(), V) expression = get_expression(container, T(), PSY.ACBus) radial_network_reduction = get_radial_network_reduction(network_model) - @assert !isempty(radial_network_reduction) for d in devices name = PSY.get_name(d) - @show PSY.get_bus(d) bus_no = PNM.get_mapped_bus_number(radial_network_reduction, PSY.get_bus(d)) - @show bus_no for t in get_time_steps(container) _add_to_jump_expression!( expression[bus_no, t], From 4e2dfae59f99e590e7d28c121ace6b7dbb9f4e81 Mon Sep 17 00:00:00 2001 From: Jose Daniel Lara Date: Sun, 5 Jan 2025 15:30:24 -0700 Subject: [PATCH 9/9] formatter --- test/test_network_constructors.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_network_constructors.jl b/test/test_network_constructors.jl index e16df3748..31c350164 100644 --- a/test/test_network_constructors.jl +++ b/test/test_network_constructors.jl @@ -727,7 +727,7 @@ end end template = get_thermal_dispatch_template_network( - NetworkModel(AreaBalancePowerModel, use_slacks=true) + NetworkModel(AreaBalancePowerModel; use_slacks = true), ) ps_model = DecisionModel(template, c_sys; optimizer = HiGHS_optimizer) @@ -742,8 +742,8 @@ end 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.) + @test all(slacks_up[!, "Area_1"] .> 0.0) + @test all(slacks_up[!, "Area_2"] .≈ 0.0) end @testset "2 Areas AreaBalance PowerModel" begin