From 53052ec8950d528bf5c6efc7a47fe9c9d2a1faf5 Mon Sep 17 00:00:00 2001 From: Jun He Date: Sat, 27 May 2023 15:43:39 -0400 Subject: [PATCH] standalone test integration --- test/instance/read_test.jl | 167 ------------------ test/runtests.jl | 53 ------ .../TimeDecomposition/initial_status_test.jl | 151 ---------------- .../TimeDecomposition/optimize_test.jl | 52 ------ .../TimeDecomposition/update_solution_test.jl | 49 ----- test/src/UnitCommitmentT.jl | 6 + test/src/instance/read_test.jl | 1 + .../TimeDecomposition/initial_status_test.jl | 159 +++++++++++++++++ .../TimeDecomposition/optimize_test.jl | 60 +++++++ .../TimeDecomposition/update_solution_test.jl | 55 ++++++ 10 files changed, 281 insertions(+), 472 deletions(-) delete mode 100644 test/instance/read_test.jl delete mode 100644 test/runtests.jl delete mode 100644 test/solution/methods/TimeDecomposition/initial_status_test.jl delete mode 100644 test/solution/methods/TimeDecomposition/optimize_test.jl delete mode 100644 test/solution/methods/TimeDecomposition/update_solution_test.jl create mode 100644 test/src/solution/methods/TimeDecomposition/initial_status_test.jl create mode 100644 test/src/solution/methods/TimeDecomposition/optimize_test.jl create mode 100644 test/src/solution/methods/TimeDecomposition/update_solution_test.jl diff --git a/test/instance/read_test.jl b/test/instance/read_test.jl deleted file mode 100644 index 5adb774..0000000 --- a/test/instance/read_test.jl +++ /dev/null @@ -1,167 +0,0 @@ -# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment -# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. -# Released under the modified BSD license. See COPYING.md for more details. - -using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip - -@testset "read_benchmark" begin - instance = UnitCommitment.read("$FIXTURES/case14.json.gz") - - @test repr(instance) == ( - "UnitCommitmentInstance(1 scenarios, 6 thermal units, 0 profiled units, 14 buses, " * - "20 lines, 19 contingencies, 1 price sensitive loads, 4 time steps)" - ) - - @test length(instance.scenarios) == 1 - sc = instance.scenarios[1] - @test length(sc.lines) == 20 - @test length(sc.buses) == 14 - @test length(sc.thermal_units) == 6 - @test length(sc.contingencies) == 19 - @test length(sc.price_sensitive_loads) == 1 - @test instance.time == 4 - @test sc.time_step == 60 - - @test sc.lines[5].name == "l5" - @test sc.lines[5].source.name == "b2" - @test sc.lines[5].target.name == "b5" - @test sc.lines[5].reactance ≈ 0.17388 - @test sc.lines[5].susceptance ≈ 10.037550333 - @test sc.lines[5].normal_flow_limit == [1e8 for t in 1:4] - @test sc.lines[5].emergency_flow_limit == [1e8 for t in 1:4] - @test sc.lines[5].flow_limit_penalty == [5e3 for t in 1:4] - @test sc.lines_by_name["l5"].name == "l5" - - @test sc.lines[1].name == "l1" - @test sc.lines[1].source.name == "b1" - @test sc.lines[1].target.name == "b2" - @test sc.lines[1].reactance ≈ 0.059170 - @test sc.lines[1].susceptance ≈ 29.496860773945 - @test sc.lines[1].normal_flow_limit == [300.0 for t in 1:4] - @test sc.lines[1].emergency_flow_limit == [400.0 for t in 1:4] - @test sc.lines[1].flow_limit_penalty == [1e3 for t in 1:4] - - @test sc.buses[9].name == "b9" - @test sc.buses[9].load == [35.36638, 33.25495, 31.67138, 31.14353] - @test sc.buses_by_name["b9"].name == "b9" - - @test sc.reserves[1].name == "r1" - @test sc.reserves[1].type == "spinning" - @test sc.reserves[1].amount == [100.0, 100.0, 100.0, 100.0] - @test sc.reserves_by_name["r1"].name == "r1" - - unit = sc.thermal_units[1] - @test unit.name == "g1" - @test unit.bus.name == "b1" - @test unit.ramp_up_limit == 1e6 - @test unit.ramp_down_limit == 1e6 - @test unit.startup_limit == 1e6 - @test unit.shutdown_limit == 1e6 - @test unit.must_run == [false for t in 1:4] - @test unit.min_power_cost == [1400.0 for t in 1:4] - @test unit.min_uptime == 1 - @test unit.min_downtime == 1 - for t in 1:1 - @test unit.cost_segments[1].mw[t] == 10.0 - @test unit.cost_segments[2].mw[t] == 20.0 - @test unit.cost_segments[3].mw[t] == 5.0 - @test unit.cost_segments[1].cost[t] ≈ 20.0 - @test unit.cost_segments[2].cost[t] ≈ 30.0 - @test unit.cost_segments[3].cost[t] ≈ 40.0 - end - @test length(unit.startup_categories) == 3 - @test unit.startup_categories[1].delay == 1 - @test unit.startup_categories[2].delay == 2 - @test unit.startup_categories[3].delay == 3 - @test unit.startup_categories[1].cost == 1000.0 - @test unit.startup_categories[2].cost == 1500.0 - @test unit.startup_categories[3].cost == 2000.0 - @test length(unit.reserves) == 0 - @test sc.thermal_units_by_name["g1"].name == "g1" - - unit = sc.thermal_units[2] - @test unit.name == "g2" - @test unit.must_run == [false for t in 1:4] - @test length(unit.reserves) == 1 - - unit = sc.thermal_units[3] - @test unit.name == "g3" - @test unit.bus.name == "b3" - @test unit.ramp_up_limit == 70.0 - @test unit.ramp_down_limit == 70.0 - @test unit.startup_limit == 70.0 - @test unit.shutdown_limit == 70.0 - @test unit.must_run == [true for t in 1:4] - @test unit.min_power_cost == [0.0 for t in 1:4] - @test unit.min_uptime == 1 - @test unit.min_downtime == 1 - for t in 1:4 - @test unit.cost_segments[1].mw[t] ≈ 33 - @test unit.cost_segments[2].mw[t] ≈ 33 - @test unit.cost_segments[3].mw[t] ≈ 34 - @test unit.cost_segments[1].cost[t] ≈ 33.75 - @test unit.cost_segments[2].cost[t] ≈ 38.04 - @test unit.cost_segments[3].cost[t] ≈ 44.77853 - end - @test length(unit.reserves) == 1 - @test unit.reserves[1].name == "r1" - - @test sc.contingencies[1].lines == [sc.lines[1]] - @test sc.contingencies[1].thermal_units == [] - @test sc.contingencies[1].name == "c1" - @test sc.contingencies_by_name["c1"].name == "c1" - - load = sc.price_sensitive_loads[1] - @test load.name == "ps1" - @test load.bus.name == "b3" - @test load.revenue == [100.0 for t in 1:4] - @test load.demand == [50.0 for t in 1:4] - @test sc.price_sensitive_loads_by_name["ps1"].name == "ps1" -end - -@testset "read_benchmark sub-hourly" begin - instance = UnitCommitment.read("$FIXTURES/case14-sub-hourly.json.gz") - @test instance.time == 4 - unit = instance.scenarios[1].thermal_units[1] - @test unit.name == "g1" - @test unit.min_uptime == 2 - @test unit.min_downtime == 2 - @test length(unit.startup_categories) == 3 - @test unit.startup_categories[1].delay == 2 - @test unit.startup_categories[2].delay == 4 - @test unit.startup_categories[3].delay == 6 - @test unit.initial_status == -200 -end - -@testset "read_benchmark profiled-units" begin - instance = UnitCommitment.read("$FIXTURES/case14-profiled.json.gz") - sc = instance.scenarios[1] - @test length(sc.profiled_units) == 2 - - first_pu = sc.profiled_units[1] - @test first_pu.name == "g7" - @test first_pu.bus.name == "b4" - @test first_pu.cost == [100.0 for t in 1:4] - @test first_pu.min_power == [60.0 for t in 1:4] - @test first_pu.max_power == [100.0 for t in 1:4] - @test sc.profiled_units_by_name["g7"].name == "g7" - - second_pu = sc.profiled_units[2] - @test second_pu.name == "g8" - @test second_pu.bus.name == "b5" - @test second_pu.cost == [50.0 for t in 1:4] - @test second_pu.min_power == [0.0 for t in 1:4] - @test second_pu.max_power == [120.0 for t in 1:4] - @test sc.profiled_units_by_name["g8"].name == "g8" -end - -@testset "read_benchmark commitmemt-status" begin - instance = UnitCommitment.read("$FIXTURES/case14-fixed-status.json.gz") - sc = instance.scenarios[1] - - @test sc.thermal_units[1].commitment_status == [nothing for t in 1:4] - @test sc.thermal_units[2].commitment_status == [true for t in 1:4] - @test sc.thermal_units[4].commitment_status == [false for t in 1:4] - @test sc.thermal_units[6].commitment_status == - [false, nothing, true, nothing] -end diff --git a/test/runtests.jl b/test/runtests.jl deleted file mode 100644 index a98fa79..0000000 --- a/test/runtests.jl +++ /dev/null @@ -1,53 +0,0 @@ -# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment -# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. -# Released under the modified BSD license. See COPYING.md for more details. - -using Test -using UnitCommitment - -push!(Base.LOAD_PATH, @__DIR__) -UnitCommitment._setup_logger(level = Base.CoreLogging.Error) - -FIXTURES = "$(@__DIR__)/fixtures" - -@testset "UnitCommitment" begin - include("usage.jl") - @testset "import" begin - include("import/egret_test.jl") - end - @testset "instance" begin - include("instance/read_test.jl") - include("instance/migrate_test.jl") - end - @testset "model" begin - include("model/formulations_test.jl") - end - @testset "solution" begin - @testset "XavQiuWanThi19" begin - include("solution/methods/XavQiuWanThi19/filter_test.jl") - include("solution/methods/XavQiuWanThi19/find_test.jl") - include("solution/methods/XavQiuWanThi19/sensitivity_test.jl") - end - @testset "TimeDecomposition" begin - include("solution/methods/TimeDecomposition/initial_status_test.jl") - include( - "solution/methods/TimeDecomposition/update_solution_test.jl", - ) - include("solution/methods/TimeDecomposition/optimize_test.jl") - end - end - @testset "transform" begin - include("transform/initcond_test.jl") - include("transform/slice_test.jl") - @testset "randomize" begin - include("transform/randomize/XavQiuAhm2021_test.jl") - end - end - @testset "validation" begin - include("validation/repair_test.jl") - end - @testset "lmp" begin - include("lmp/conventional_test.jl") - include("lmp/aelmp_test.jl") - end -end diff --git a/test/solution/methods/TimeDecomposition/initial_status_test.jl b/test/solution/methods/TimeDecomposition/initial_status_test.jl deleted file mode 100644 index 1e0f17f..0000000 --- a/test/solution/methods/TimeDecomposition/initial_status_test.jl +++ /dev/null @@ -1,151 +0,0 @@ -# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment -# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. -# Released under the modified BSD license. See COPYING.md for more details. - -using UnitCommitment, DataStructures - -@testset "determine_initial_status" begin - hot_start = 100 - cold_start = -100 - - # all on throughout - stat_seq = ones(36) - # hot start - new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq) - @test new_stat == 136 - # cold start - new_stat = UnitCommitment._determine_initial_status(cold_start, stat_seq) - @test new_stat == 36 - - # off in the last 12 periods - stat_seq = ones(36) - stat_seq[25:end] .= 0 - # hot start - new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq) - @test new_stat == -12 - # cold start - new_stat = UnitCommitment._determine_initial_status(cold_start, stat_seq) - @test new_stat == -12 - - # off in one period - stat_seq = ones(36) - stat_seq[10] = 0 - # hot start - new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq) - @test new_stat == 26 - # cold start - new_stat = UnitCommitment._determine_initial_status(cold_start, stat_seq) - @test new_stat == 26 - - # off in several of the first 24 periods - stat_seq = ones(36) - stat_seq[[10, 11, 20]] .= 0 - # hot start - new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq) - @test new_stat == 16 - # cold start - new_stat = UnitCommitment._determine_initial_status(cold_start, stat_seq) - @test new_stat == 16 - - # all off throughout - stat_seq = zeros(36) - # hot start - new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq) - @test new_stat == -36 - # cold start - new_stat = UnitCommitment._determine_initial_status(cold_start, stat_seq) - @test new_stat == -136 - - # on in the last 12 periods - stat_seq = zeros(36) - stat_seq[25:end] .= 1 - # hot start - new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq) - @test new_stat == 12 - # cold start - new_stat = UnitCommitment._determine_initial_status(cold_start, stat_seq) - @test new_stat == 12 -end - -@testset "set_initial_status" begin - # read one scenario - instance = UnitCommitment.read("$FIXTURES/case14.json.gz") - psuedo_solution = OrderedDict( - "Thermal production (MW)" => OrderedDict( - "g1" => [0.0, 112.0, 114.0, 116.0], - "g2" => [0.0, 102.0, 0.0, 0.0], - "g3" => [0.0, 0.0, 0.0, 0.0], - "g4" => [0.0, 34.0, 66.0, 99.0], - "g5" => [0.0, 34.0, 66.0, 99.0], - "g6" => [0.0, 100.0, 100.0, 100.0], - ), - "Is on" => OrderedDict( - "g1" => [0.0, 1.0, 1.0, 1.0], - "g2" => [0.0, 1.0, 0.0, 0.0], - "g3" => [0.0, 0.0, 0.0, 0.0], - "g4" => [0.0, 1.0, 1.0, 1.0], - "g5" => [0.0, 1.0, 1.0, 1.0], - "g6" => [0.0, 1.0, 1.0, 1.0], - ), - ) - UnitCommitment._set_initial_status!(instance, psuedo_solution, 3) - thermal_units = instance.scenarios[1].thermal_units - @test thermal_units[1].initial_power == 116.0 - @test thermal_units[1].initial_status == 3.0 - @test thermal_units[2].initial_power == 0.0 - @test thermal_units[2].initial_status == -2.0 - @test thermal_units[3].initial_power == 0.0 - @test thermal_units[3].initial_status == -9.0 - - # read multiple scenarios - instance = UnitCommitment.read([ - "$FIXTURES/case14.json.gz", - "$FIXTURES/case14-profiled.json.gz", - ]) - psuedo_solution = OrderedDict( - "case14" => OrderedDict( - "Thermal production (MW)" => OrderedDict( - "g1" => [0.0, 112.0, 114.0, 116.0], - "g2" => [0.0, 102.0, 0.0, 0.0], - "g3" => [0.0, 0.0, 0.0, 0.0], - "g4" => [0.0, 34.0, 66.0, 99.0], - "g5" => [0.0, 34.0, 66.0, 99.0], - "g6" => [0.0, 100.0, 100.0, 100.0], - ), - "Is on" => OrderedDict( - "g1" => [0.0, 1.0, 1.0, 1.0], - "g2" => [0.0, 1.0, 0.0, 0.0], - "g3" => [0.0, 0.0, 0.0, 0.0], - "g4" => [0.0, 1.0, 1.0, 1.0], - "g5" => [0.0, 1.0, 1.0, 1.0], - "g6" => [0.0, 1.0, 1.0, 1.0], - ), - ), - "case14-profiled" => OrderedDict( - "Thermal production (MW)" => OrderedDict( - "g1" => [0.0, 113.0, 116.0, 115.0], - "g2" => [0.0, 0.0, 0.0, 0.0], - "g3" => [0.0, 0.0, 0.0, 20.0], - "g4" => [0.0, 34.0, 66.0, 98.0], - "g5" => [0.0, 34.0, 66.0, 97.0], - "g6" => [0.0, 100.0, 100.0, 100.0], - ), - "Is on" => OrderedDict( - "g1" => [0.0, 1.0, 1.0, 1.0], - "g2" => [0.0, 0.0, 0.0, 0.0], - "g3" => [0.0, 0.0, 0.0, 1.0], - "g4" => [0.0, 1.0, 1.0, 1.0], - "g5" => [0.0, 1.0, 1.0, 1.0], - "g6" => [0.0, 1.0, 1.0, 1.0], - ), - ), - ) - UnitCommitment._set_initial_status!(instance, psuedo_solution, 3) - thermal_units_sc2 = instance.scenarios[2].thermal_units - @test thermal_units_sc2[1].initial_power == 115.0 - @test thermal_units_sc2[1].initial_status == 3.0 - @test thermal_units_sc2[2].initial_power == 0.0 - @test thermal_units_sc2[2].initial_status == -11.0 - @test thermal_units_sc2[3].initial_power == 20.0 - @test thermal_units_sc2[3].initial_status == 1.0 -end diff --git a/test/solution/methods/TimeDecomposition/optimize_test.jl b/test/solution/methods/TimeDecomposition/optimize_test.jl deleted file mode 100644 index 9987d1e..0000000 --- a/test/solution/methods/TimeDecomposition/optimize_test.jl +++ /dev/null @@ -1,52 +0,0 @@ -# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment -# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. -# Released under the modified BSD license. See COPYING.md for more details. - -using UnitCommitment, DataStructures, Cbc -import UnitCommitment: TimeDecomposition, XavQiuWanThi2019, Formulation - -@testset "optimize_time_decomposition" begin - # read one scenario - instance = UnitCommitment.read("$FIXTURES/case14.json.gz") - solution = UnitCommitment.optimize!( - instance, - TimeDecomposition( - time_window = 3, - time_increment = 2, - inner_method = XavQiuWanThi2019.Method(), - formulation = Formulation(), - ), - optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0), - ) - @test length(solution["Thermal production (MW)"]["g1"]) == 4 - @test length(solution["Is on"]["g2"]) == 4 - @test length(solution["Spinning reserve (MW)"]["r1"]["g2"]) == 4 - - # read multiple scenarios - instance = UnitCommitment.read([ - "$FIXTURES/case14.json.gz", - "$FIXTURES/case14-profiled.json.gz", - ]) - solution = UnitCommitment.optimize!( - instance, - TimeDecomposition( - time_window = 3, - time_increment = 2, - inner_method = XavQiuWanThi2019.Method(), - formulation = Formulation(), - ), - optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0), - ) - @test length(solution["case14"]["Thermal production (MW)"]["g3"]) == 4 - @test length(solution["case14"]["Is on"]["g4"]) == 4 - @test length( - solution["case14-profiled"]["Thermal production (MW)"]["g5"], - ) == 4 - @test length(solution["case14-profiled"]["Is on"]["g6"]) == 4 - @test length( - solution["case14-profiled"]["Profiled production (MW)"]["g7"], - ) == 4 - @test length( - solution["case14-profiled"]["Spinning reserve (MW)"]["r1"]["g3"], - ) == 4 -end diff --git a/test/solution/methods/TimeDecomposition/update_solution_test.jl b/test/solution/methods/TimeDecomposition/update_solution_test.jl deleted file mode 100644 index 106002e..0000000 --- a/test/solution/methods/TimeDecomposition/update_solution_test.jl +++ /dev/null @@ -1,49 +0,0 @@ -# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment -# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. -# Released under the modified BSD license. See COPYING.md for more details. - -using UnitCommitment, DataStructures - -@testset "update_solution" begin - psuedo_solution = OrderedDict() - time_increment = 4 - psuedo_sub_solution = OrderedDict( - "Thermal production (MW)" => - OrderedDict("g1" => [100.0, 200.0, 300.0, 400.0, 500.0, 600.0]), - "Is on" => OrderedDict("g1" => [1.0, 0.0, 1.0, 1.0, 0.0, 1.0]), - "Profiled production (MW)" => - OrderedDict("g1" => [199.0, 299.0, 399.0, 499.0, 599.0, 699.0]), - "Spinning reserve (MW)" => OrderedDict( - "r1" => OrderedDict("g1" => [31.0, 32.0, 33.0, 34.0, 35.0, 36.0]), - ), - ) - - # first update should directly copy the first 4 entries of sub solution - UnitCommitment._update_solution!( - psuedo_solution, - psuedo_sub_solution, - time_increment, - ) - @test psuedo_solution["Thermal production (MW)"]["g1"] == - [100.0, 200.0, 300.0, 400.0] - @test psuedo_solution["Is on"]["g1"] == [1.0, 0.0, 1.0, 1.0] - @test psuedo_solution["Profiled production (MW)"]["g1"] == - [199.0, 299.0, 399.0, 499.0] - @test psuedo_solution["Spinning reserve (MW)"]["r1"]["g1"] == - [31.0, 32.0, 33.0, 34.0] - - # second update should append the first 4 entries of sub solution - UnitCommitment._update_solution!( - psuedo_solution, - psuedo_sub_solution, - time_increment, - ) - @test psuedo_solution["Thermal production (MW)"]["g1"] == - [100.0, 200.0, 300.0, 400.0, 100.0, 200.0, 300.0, 400.0] - @test psuedo_solution["Is on"]["g1"] == - [1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0] - @test psuedo_solution["Profiled production (MW)"]["g1"] == - [199.0, 299.0, 399.0, 499.0, 199.0, 299.0, 399.0, 499.0] - @test psuedo_solution["Spinning reserve (MW)"]["r1"]["g1"] == - [31.0, 32.0, 33.0, 34.0, 31.0, 32.0, 33.0, 34.0] -end diff --git a/test/src/UnitCommitmentT.jl b/test/src/UnitCommitmentT.jl index f529c42..4ea0d73 100644 --- a/test/src/UnitCommitmentT.jl +++ b/test/src/UnitCommitmentT.jl @@ -13,6 +13,9 @@ include("solution/methods/XavQiuWanThi19/filter_test.jl") include("solution/methods/XavQiuWanThi19/find_test.jl") include("solution/methods/XavQiuWanThi19/sensitivity_test.jl") include("solution/methods/ProgressiveHedging/usage_test.jl") +include("solution/methods/TimeDecomposition/initial_status_test.jl") +include("solution/methods/TimeDecomposition/optimize_test.jl") +include("solution/methods/TimeDecomposition/update_solution_test.jl") include("transform/initcond_test.jl") include("transform/slice_test.jl") include("transform/randomize/XavQiuAhm2021_test.jl") @@ -39,6 +42,9 @@ function runtests() solution_methods_XavQiuWanThi19_find_test() solution_methods_XavQiuWanThi19_sensitivity_test() solution_methods_ProgressiveHedging_usage_test() + solution_methods_TimeDecomposition_initial_status_test() + solution_methods_TimeDecomposition_optimize_test() + solution_methods_TimeDecomposition_update_solution_test() transform_initcond_test() transform_slice_test() transform_randomize_XavQiuAhm2021_test() diff --git a/test/src/instance/read_test.jl b/test/src/instance/read_test.jl index 85f44ff..c9ae1fd 100644 --- a/test/src/instance/read_test.jl +++ b/test/src/instance/read_test.jl @@ -21,6 +21,7 @@ function instance_read_test() @test length(sc.contingencies) == 19 @test length(sc.price_sensitive_loads) == 1 @test instance.time == 4 + @test sc.time_step == 60 @test sc.lines[5].name == "l5" @test sc.lines[5].source.name == "b2" diff --git a/test/src/solution/methods/TimeDecomposition/initial_status_test.jl b/test/src/solution/methods/TimeDecomposition/initial_status_test.jl new file mode 100644 index 0000000..b3a127c --- /dev/null +++ b/test/src/solution/methods/TimeDecomposition/initial_status_test.jl @@ -0,0 +1,159 @@ +# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment +# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. +# Released under the modified BSD license. See COPYING.md for more details. + +using UnitCommitment, DataStructures + +function solution_methods_TimeDecomposition_initial_status_test() + @testset "determine_initial_status" begin + hot_start = 100 + cold_start = -100 + + # all on throughout + stat_seq = ones(36) + # hot start + new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq) + @test new_stat == 136 + # cold start + new_stat = + UnitCommitment._determine_initial_status(cold_start, stat_seq) + @test new_stat == 36 + + # off in the last 12 periods + stat_seq = ones(36) + stat_seq[25:end] .= 0 + # hot start + new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq) + @test new_stat == -12 + # cold start + new_stat = + UnitCommitment._determine_initial_status(cold_start, stat_seq) + @test new_stat == -12 + + # off in one period + stat_seq = ones(36) + stat_seq[10] = 0 + # hot start + new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq) + @test new_stat == 26 + # cold start + new_stat = + UnitCommitment._determine_initial_status(cold_start, stat_seq) + @test new_stat == 26 + + # off in several of the first 24 periods + stat_seq = ones(36) + stat_seq[[10, 11, 20]] .= 0 + # hot start + new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq) + @test new_stat == 16 + # cold start + new_stat = + UnitCommitment._determine_initial_status(cold_start, stat_seq) + @test new_stat == 16 + + # all off throughout + stat_seq = zeros(36) + # hot start + new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq) + @test new_stat == -36 + # cold start + new_stat = + UnitCommitment._determine_initial_status(cold_start, stat_seq) + @test new_stat == -136 + + # on in the last 12 periods + stat_seq = zeros(36) + stat_seq[25:end] .= 1 + # hot start + new_stat = UnitCommitment._determine_initial_status(hot_start, stat_seq) + @test new_stat == 12 + # cold start + new_stat = + UnitCommitment._determine_initial_status(cold_start, stat_seq) + @test new_stat == 12 + end + + @testset "set_initial_status" begin + # read one scenario + instance = UnitCommitment.read(fixture("case14.json.gz")) + psuedo_solution = OrderedDict( + "Thermal production (MW)" => OrderedDict( + "g1" => [0.0, 112.0, 114.0, 116.0], + "g2" => [0.0, 102.0, 0.0, 0.0], + "g3" => [0.0, 0.0, 0.0, 0.0], + "g4" => [0.0, 34.0, 66.0, 99.0], + "g5" => [0.0, 34.0, 66.0, 99.0], + "g6" => [0.0, 100.0, 100.0, 100.0], + ), + "Is on" => OrderedDict( + "g1" => [0.0, 1.0, 1.0, 1.0], + "g2" => [0.0, 1.0, 0.0, 0.0], + "g3" => [0.0, 0.0, 0.0, 0.0], + "g4" => [0.0, 1.0, 1.0, 1.0], + "g5" => [0.0, 1.0, 1.0, 1.0], + "g6" => [0.0, 1.0, 1.0, 1.0], + ), + ) + UnitCommitment._set_initial_status!(instance, psuedo_solution, 3) + thermal_units = instance.scenarios[1].thermal_units + @test thermal_units[1].initial_power == 116.0 + @test thermal_units[1].initial_status == 3.0 + @test thermal_units[2].initial_power == 0.0 + @test thermal_units[2].initial_status == -2.0 + @test thermal_units[3].initial_power == 0.0 + @test thermal_units[3].initial_status == -9.0 + + # read multiple scenarios + instance = UnitCommitment.read([ + fixture("case14.json.gz"), + fixture("case14-profiled.json.gz"), + ]) + psuedo_solution = OrderedDict( + "case14" => OrderedDict( + "Thermal production (MW)" => OrderedDict( + "g1" => [0.0, 112.0, 114.0, 116.0], + "g2" => [0.0, 102.0, 0.0, 0.0], + "g3" => [0.0, 0.0, 0.0, 0.0], + "g4" => [0.0, 34.0, 66.0, 99.0], + "g5" => [0.0, 34.0, 66.0, 99.0], + "g6" => [0.0, 100.0, 100.0, 100.0], + ), + "Is on" => OrderedDict( + "g1" => [0.0, 1.0, 1.0, 1.0], + "g2" => [0.0, 1.0, 0.0, 0.0], + "g3" => [0.0, 0.0, 0.0, 0.0], + "g4" => [0.0, 1.0, 1.0, 1.0], + "g5" => [0.0, 1.0, 1.0, 1.0], + "g6" => [0.0, 1.0, 1.0, 1.0], + ), + ), + "case14-profiled" => OrderedDict( + "Thermal production (MW)" => OrderedDict( + "g1" => [0.0, 113.0, 116.0, 115.0], + "g2" => [0.0, 0.0, 0.0, 0.0], + "g3" => [0.0, 0.0, 0.0, 20.0], + "g4" => [0.0, 34.0, 66.0, 98.0], + "g5" => [0.0, 34.0, 66.0, 97.0], + "g6" => [0.0, 100.0, 100.0, 100.0], + ), + "Is on" => OrderedDict( + "g1" => [0.0, 1.0, 1.0, 1.0], + "g2" => [0.0, 0.0, 0.0, 0.0], + "g3" => [0.0, 0.0, 0.0, 1.0], + "g4" => [0.0, 1.0, 1.0, 1.0], + "g5" => [0.0, 1.0, 1.0, 1.0], + "g6" => [0.0, 1.0, 1.0, 1.0], + ), + ), + ) + UnitCommitment._set_initial_status!(instance, psuedo_solution, 3) + thermal_units_sc2 = instance.scenarios[2].thermal_units + @test thermal_units_sc2[1].initial_power == 115.0 + @test thermal_units_sc2[1].initial_status == 3.0 + @test thermal_units_sc2[2].initial_power == 0.0 + @test thermal_units_sc2[2].initial_status == -11.0 + @test thermal_units_sc2[3].initial_power == 20.0 + @test thermal_units_sc2[3].initial_status == 1.0 + end +end diff --git a/test/src/solution/methods/TimeDecomposition/optimize_test.jl b/test/src/solution/methods/TimeDecomposition/optimize_test.jl new file mode 100644 index 0000000..a087e78 --- /dev/null +++ b/test/src/solution/methods/TimeDecomposition/optimize_test.jl @@ -0,0 +1,60 @@ +# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment +# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. +# Released under the modified BSD license. See COPYING.md for more details. + +using UnitCommitment, DataStructures, Cbc +import UnitCommitment: TimeDecomposition, XavQiuWanThi2019, Formulation + +function solution_methods_TimeDecomposition_optimize_test() + @testset "optimize_time_decomposition" begin + # read one scenario + instance = UnitCommitment.read(fixture("case14.json.gz")) + solution = UnitCommitment.optimize!( + instance, + TimeDecomposition( + time_window = 3, + time_increment = 2, + inner_method = XavQiuWanThi2019.Method(), + formulation = Formulation(), + ), + optimizer = optimizer_with_attributes( + Cbc.Optimizer, + "logLevel" => 0, + ), + ) + @test length(solution["Thermal production (MW)"]["g1"]) == 4 + @test length(solution["Is on"]["g2"]) == 4 + @test length(solution["Spinning reserve (MW)"]["r1"]["g2"]) == 4 + + # read multiple scenarios + instance = UnitCommitment.read([ + fixture("case14.json.gz"), + fixture("case14-profiled.json.gz"), + ]) + solution = UnitCommitment.optimize!( + instance, + TimeDecomposition( + time_window = 3, + time_increment = 2, + inner_method = XavQiuWanThi2019.Method(), + formulation = Formulation(), + ), + optimizer = optimizer_with_attributes( + Cbc.Optimizer, + "logLevel" => 0, + ), + ) + @test length(solution["case14"]["Thermal production (MW)"]["g3"]) == 4 + @test length(solution["case14"]["Is on"]["g4"]) == 4 + @test length( + solution["case14-profiled"]["Thermal production (MW)"]["g5"], + ) == 4 + @test length(solution["case14-profiled"]["Is on"]["g6"]) == 4 + @test length( + solution["case14-profiled"]["Profiled production (MW)"]["g7"], + ) == 4 + @test length( + solution["case14-profiled"]["Spinning reserve (MW)"]["r1"]["g3"], + ) == 4 + end +end diff --git a/test/src/solution/methods/TimeDecomposition/update_solution_test.jl b/test/src/solution/methods/TimeDecomposition/update_solution_test.jl new file mode 100644 index 0000000..ad1be68 --- /dev/null +++ b/test/src/solution/methods/TimeDecomposition/update_solution_test.jl @@ -0,0 +1,55 @@ +# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment +# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. +# Released under the modified BSD license. See COPYING.md for more details. + +using UnitCommitment, DataStructures + +function solution_methods_TimeDecomposition_update_solution_test() + @testset "update_solution" begin + psuedo_solution = OrderedDict() + time_increment = 4 + psuedo_sub_solution = OrderedDict( + "Thermal production (MW)" => OrderedDict( + "g1" => [100.0, 200.0, 300.0, 400.0, 500.0, 600.0], + ), + "Is on" => OrderedDict("g1" => [1.0, 0.0, 1.0, 1.0, 0.0, 1.0]), + "Profiled production (MW)" => OrderedDict( + "g1" => [199.0, 299.0, 399.0, 499.0, 599.0, 699.0], + ), + "Spinning reserve (MW)" => OrderedDict( + "r1" => OrderedDict( + "g1" => [31.0, 32.0, 33.0, 34.0, 35.0, 36.0], + ), + ), + ) + + # first update should directly copy the first 4 entries of sub solution + UnitCommitment._update_solution!( + psuedo_solution, + psuedo_sub_solution, + time_increment, + ) + @test psuedo_solution["Thermal production (MW)"]["g1"] == + [100.0, 200.0, 300.0, 400.0] + @test psuedo_solution["Is on"]["g1"] == [1.0, 0.0, 1.0, 1.0] + @test psuedo_solution["Profiled production (MW)"]["g1"] == + [199.0, 299.0, 399.0, 499.0] + @test psuedo_solution["Spinning reserve (MW)"]["r1"]["g1"] == + [31.0, 32.0, 33.0, 34.0] + + # second update should append the first 4 entries of sub solution + UnitCommitment._update_solution!( + psuedo_solution, + psuedo_sub_solution, + time_increment, + ) + @test psuedo_solution["Thermal production (MW)"]["g1"] == + [100.0, 200.0, 300.0, 400.0, 100.0, 200.0, 300.0, 400.0] + @test psuedo_solution["Is on"]["g1"] == + [1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0] + @test psuedo_solution["Profiled production (MW)"]["g1"] == + [199.0, 299.0, 399.0, 499.0, 199.0, 299.0, 399.0, 499.0] + @test psuedo_solution["Spinning reserve (MW)"]["r1"]["g1"] == + [31.0, 32.0, 33.0, 34.0, 31.0, 32.0, 33.0, 34.0] + end +end