From 7f92e62aa57a81828722cecd9c8b255cf5c18bf0 Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Wed, 19 Mar 2025 10:48:59 +0100 Subject: [PATCH 01/14] allow meshed control transformers Signed-off-by: Nitish Bharambe --- .../optimizer/tap_position_optimizer.hpp | 18 ++++++++++++------ .../test_tap_position_optimizer.cpp | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp index f17f3c2eaf..c1600e2876 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp @@ -41,6 +41,7 @@ using EdgeWeight = int64_t; using RankedTransformerGroups = std::vector>; constexpr auto infty = std::numeric_limits::max(); +constexpr auto last_rank = infty - 1; constexpr Idx2D unregulated_idx = {-1, -1}; struct TrafoGraphVertex { bool is_source{}; @@ -309,7 +310,7 @@ inline auto get_edge_weights(TransformerGraph const& graph) -> TrafoGraphEdgePro } auto const edge_src_rank = vertex_distances[boost::source(e, graph)]; auto const edge_tgt_rank = vertex_distances[boost::target(e, graph)]; - auto const edge_res = std::min(edge_src_rank, edge_tgt_rank); + auto edge_res = std::min(edge_src_rank, edge_tgt_rank); // New edge logic for ranking // | Tap | Control | All edges | @@ -328,13 +329,18 @@ inline auto get_edge_weights(TransformerGraph const& graph) -> TrafoGraphEdgePro // side via the bidirectional edge (if it exists). For delta configuration ABC, the above // situations can happen. // The logic still holds in meshed grids, albeit operating a more complex graph. - if (edge_src_rank != edge_tgt_rank - 1) { - throw AutomaticTapInputError("The control side of a transformer regulator should be relatively further " - "away from the source than the tap side.\n"); + if (is_unreachable(edge_res)) { + continue; } - if (!is_unreachable(edge_res)) { - result.emplace_back(graph[e].regulated_idx, edge_tgt_rank); + if (edge_src_rank == infty && edge_tgt_rank != infty) { + throw AutomaticTapInputError( + "The transformer is being controlled from non source side towards source side which is unsupported.\n"); } + if (edge_src_rank != edge_tgt_rank - 1) { + edge_res = last_rank; + } + + result.emplace_back(graph[e].regulated_idx, edge_tgt_rank); } return result; diff --git a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp index 3ca814d253..85e959cc33 100644 --- a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp +++ b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp @@ -325,7 +325,7 @@ TEST_CASE("Test Transformer ranking") { SUBCASE("Ranking complete the graph") { // The test grid 1 is not compatible with the updated logic for step up transformers - CHECK_THROWS_AS(pgm_tap::rank_transformers(state), AutomaticTapInputError); + // CHECK_THROWS_AS(pgm_tap::rank_transformers(state), AutomaticTapInputError); } } From 3757e7b2a4e273259b24dc1714fd32c640099d64 Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Wed, 19 Mar 2025 11:22:01 +0100 Subject: [PATCH 02/14] add suggestions Signed-off-by: Nitish Bharambe --- .../optimizer/tap_position_optimizer.hpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp index c1600e2876..2998f7d036 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp @@ -329,18 +329,18 @@ inline auto get_edge_weights(TransformerGraph const& graph) -> TrafoGraphEdgePro // side via the bidirectional edge (if it exists). For delta configuration ABC, the above // situations can happen. // The logic still holds in meshed grids, albeit operating a more complex graph. - if (is_unreachable(edge_res)) { - continue; - } - if (edge_src_rank == infty && edge_tgt_rank != infty) { - throw AutomaticTapInputError( - "The transformer is being controlled from non source side towards source side which is unsupported.\n"); - } - if (edge_src_rank != edge_tgt_rank - 1) { - edge_res = last_rank; + if (!is_unreachable(edge_res)) { + if (edge_src_rank == infty && edge_tgt_rank != infty) { + throw AutomaticTapInputError("The transformer is being controlled from non source side towards source " + "side.\n"); + } + if (edge_src_rank != edge_tgt_rank - 1) { + // Control side is also controlled by a closer regulated transformer. + // Make this transformer have the lowest possible priority. + edge_res = last_rank; + } + result.emplace_back(graph[e].regulated_idx, edge_tgt_rank); } - - result.emplace_back(graph[e].regulated_idx, edge_tgt_rank); } return result; From ddcdcb8b3c8b128f5e7a24b242e72117ae550b21 Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Mon, 24 Mar 2025 09:59:28 +0100 Subject: [PATCH 03/14] add meshed trafo tests Signed-off-by: Nitish Bharambe --- .../test_tap_position_optimizer.cpp | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp index 82336ec733..6041c92301 100644 --- a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp +++ b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp @@ -331,7 +331,10 @@ TEST_CASE("Test Transformer ranking") { SUBCASE("Ranking complete the graph") { // The test grid 1 is not compatible with the updated logic for step up transformers - // CHECK_THROWS_AS(pgm_tap::rank_transformers(state), AutomaticTapInputError); + pgm_tap::RankedTransformerGroups order = pgm_tap::rank_transformers(state); + pgm_tap::RankedTransformerGroups const ref_order{ + {{Idx2D{3, 0}, Idx2D{3, 1}, Idx2D{4, 0}, Idx2D{3, 4}}, {Idx2D{3, 2}, Idx2D{3, 3}, Idx2D{3, 5}}}}; + CHECK(order == ref_order); } } @@ -393,6 +396,43 @@ TEST_CASE("Test Transformer ranking") { {{Idx2D{3, 0}, Idx2D{3, 1}, Idx2D{4, 0}, Idx2D{3, 4}}, {Idx2D{3, 2}, Idx2D{3, 3}, Idx2D{3, 5}}}}; CHECK(order == ref_order); } + + SUBCASE("Full grid 3 - For Meshed grid with low priority ranks") { + // =====Test Grid===== + // ________[0]________ + // | | + // | | + // | [1] + // | | + // _|______[2]_____|__ + // | + // [3] + TestState state; + std::vector nodes{{0, 10e3}, {1, 10e3}, {2, 10e3}, {3, 10e3}}; + main_core::add_component(state, nodes.begin(), nodes.end(), 50.0); + + std::vector transformers{get_transformer(11, 0, 1, BranchSide::to), + get_transformer(12, 1, 2, BranchSide::from), + get_transformer(13, 2, 3, BranchSide::from)}; + main_core::add_component(state, transformers.begin(), transformers.end(), 50.0); + + std::vector lines{get_line_input(21, 0, 2)}; + main_core::add_component(state, lines.begin(), lines.end(), 50.0); + + std::vector sources{{31, 0, 1, 1.0, 0, nan, nan, nan}}; + main_core::add_component(state, sources.begin(), sources.end(), 50.0); + + std::vector regulators{get_regulator(41, 11, ControlSide::to), + get_regulator(42, 12, ControlSide::to), + get_regulator(43, 13, ControlSide::to)}; + main_core::add_component(state, regulators.begin(), regulators.end(), 50.0); + + state.components.set_construction_complete(); + + pgm_tap::RankedTransformerGroups order = pgm_tap::rank_transformers(state); + pgm_tap::RankedTransformerGroups const ref_order{{{Idx2D{3, 0}}, {Idx2D{3, 2}}, {Idx2D{3, 1}}}}; + CHECK(order == ref_order); + } } namespace optimizer::tap_position_optimizer::test { From dff3d460bda38bd636bdfbff655a30fd66a0a35d Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Mon, 24 Mar 2025 10:10:57 +0100 Subject: [PATCH 04/14] modify test order Signed-off-by: Nitish Bharambe --- tests/cpp_unit_tests/test_tap_position_optimizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp index 6041c92301..3ad2bdfe10 100644 --- a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp +++ b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp @@ -430,7 +430,7 @@ TEST_CASE("Test Transformer ranking") { state.components.set_construction_complete(); pgm_tap::RankedTransformerGroups order = pgm_tap::rank_transformers(state); - pgm_tap::RankedTransformerGroups const ref_order{{{Idx2D{3, 0}}, {Idx2D{3, 2}}, {Idx2D{3, 1}}}}; + pgm_tap::RankedTransformerGroups const ref_order{{{Idx2D{3, 0}}, {Idx2D{3, 2}}}, {{Idx2D{3, 1}}}}; CHECK(order == ref_order); } } From 07a8486dac51271d5122b22ff81d5b3078bb43c4 Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Mon, 24 Mar 2025 10:11:44 +0100 Subject: [PATCH 05/14] modify the relaxation condition Signed-off-by: Nitish Bharambe --- .../optimizer/tap_position_optimizer.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp index 2998f7d036..34efe49fdc 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp @@ -329,17 +329,17 @@ inline auto get_edge_weights(TransformerGraph const& graph) -> TrafoGraphEdgePro // side via the bidirectional edge (if it exists). For delta configuration ABC, the above // situations can happen. // The logic still holds in meshed grids, albeit operating a more complex graph. - if (!is_unreachable(edge_res)) { - if (edge_src_rank == infty && edge_tgt_rank != infty) { + if (!(edge_src_rank == infty && edge_tgt_rank == infty)) { + if ((edge_src_rank == infty) != (edge_tgt_rank == infty)) { throw AutomaticTapInputError("The transformer is being controlled from non source side towards source " "side.\n"); - } - if (edge_src_rank != edge_tgt_rank - 1) { + } else if (edge_src_rank != edge_tgt_rank - 1) { // Control side is also controlled by a closer regulated transformer. - // Make this transformer have the lowest possible priority. - edge_res = last_rank; + // Make this transformer have the lowest possible priority. + result.emplace_back(graph[e].regulated_idx, last_rank); + } else { + result.emplace_back(graph[e].regulated_idx, edge_res); } - result.emplace_back(graph[e].regulated_idx, edge_tgt_rank); } } From c407aed9c78dea574d3203fb25551b978496d1ad Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Mon, 24 Mar 2025 10:49:18 +0100 Subject: [PATCH 06/14] correction at edge_tgt_rank Signed-off-by: Nitish Bharambe --- .../power_grid_model/optimizer/tap_position_optimizer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp index 34efe49fdc..0800b4e95f 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp @@ -338,7 +338,7 @@ inline auto get_edge_weights(TransformerGraph const& graph) -> TrafoGraphEdgePro // Make this transformer have the lowest possible priority. result.emplace_back(graph[e].regulated_idx, last_rank); } else { - result.emplace_back(graph[e].regulated_idx, edge_res); + result.emplace_back(graph[e].regulated_idx, edge_tgt_rank); } } } From 31aae236157e30db94f544108b15e0c58213ae56 Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Mon, 24 Mar 2025 11:25:26 +0100 Subject: [PATCH 07/14] add new ranks of grid 1 Signed-off-by: Nitish Bharambe --- tests/cpp_unit_tests/test_tap_position_optimizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp index 3ad2bdfe10..c4af2ec9a1 100644 --- a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp +++ b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp @@ -333,7 +333,7 @@ TEST_CASE("Test Transformer ranking") { // The test grid 1 is not compatible with the updated logic for step up transformers pgm_tap::RankedTransformerGroups order = pgm_tap::rank_transformers(state); pgm_tap::RankedTransformerGroups const ref_order{ - {{Idx2D{3, 0}, Idx2D{3, 1}, Idx2D{4, 0}, Idx2D{3, 4}}, {Idx2D{3, 2}, Idx2D{3, 3}, Idx2D{3, 5}}}}; + {{Idx2D{3, 0}, Idx2D{3, 1}, Idx2D{4, 0}}, {Idx2D{3, 2}}, {Idx2D{3, 3}, Idx2D{3, 4}}}}; CHECK(order == ref_order); } } From b02e9f6b87041ffce355d3e289be311a9e38c895 Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Tue, 25 Mar 2025 08:58:21 +0100 Subject: [PATCH 08/14] simplify condition Signed-off-by: Nitish Bharambe --- .../power_grid_model/optimizer/tap_position_optimizer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp index e79f2caa67..a85ce43a4b 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp @@ -329,7 +329,7 @@ inline auto get_edge_weights(TransformerGraph const& graph) -> TrafoGraphEdgePro // situations can happen. // The logic still holds in meshed grids, albeit operating a more complex graph. if (!is_unreachable(edge_src_rank) || !is_unreachable(edge_tgt_rank)) { - if ((edge_src_rank == infty) != (edge_tgt_rank == infty)) { + if ((edge_src_rank == infty) || (edge_tgt_rank == infty)) { throw AutomaticTapInputError("The transformer is being controlled from non source side towards source " "side.\n"); } else if (edge_src_rank != edge_tgt_rank - 1) { From 45e3636763f373269676d7f96c6d14604e5ac07f Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Tue, 25 Mar 2025 09:53:28 +0100 Subject: [PATCH 09/14] add extra attribtues Signed-off-by: Nitish Bharambe --- tests/unit/test_error_handling.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/unit/test_error_handling.py b/tests/unit/test_error_handling.py index b322757e5a..e68cd32cd2 100644 --- a/tests/unit/test_error_handling.py +++ b/tests/unit/test_error_handling.py @@ -315,10 +315,22 @@ def test_transformer_tap_regulator_control_side_not_closer_to_source(): transformer_input["to_node"] = [1] transformer_input["from_status"] = [1] transformer_input["to_status"] = [1] + transformer_input["u1"] = [1e4] + transformer_input["u2"] = [4e2] + transformer_input["sn"] = [1e5] + transformer_input["uk"] = [0.1] + transformer_input["pk"] = [1e3] + transformer_input["i0"] = [1.0e-6] + transformer_input["p0"] = [0.1] transformer_input["winding_from"] = [1] transformer_input["winding_to"] = [1] transformer_input["clock"] = [0] transformer_input["tap_side"] = [1] + transformer_input["tap_pos"] = [0] + transformer_input["tap_nom"] = [0] + transformer_input["tap_min"] = [-1] + transformer_input["tap_max"] = [1] + transformer_input["tap_size"] = [100] source_input = initialize_array("input", "source", 1) source_input["id"] = [3] @@ -330,6 +342,8 @@ def test_transformer_tap_regulator_control_side_not_closer_to_source(): transformer_tap_regulator_input["id"] = [4] transformer_tap_regulator_input["regulated_object"] = [2] transformer_tap_regulator_input["status"] = [1] + transformer_tap_regulator_input["u_set"] = [10] + transformer_tap_regulator_input["u_band"] = [200] transformer_tap_regulator_input["control_side"] = [0] model = PowerGridModel( From a03a851d932705ca900c83326ca42f829ac499f7 Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Tue, 25 Mar 2025 15:44:18 +0100 Subject: [PATCH 10/14] add unit test for source side controlling Signed-off-by: Nitish Bharambe --- .../test_tap_position_optimizer.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp index 0e63a141af..18ceee441e 100644 --- a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp +++ b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp @@ -185,6 +185,25 @@ TEST_CASE("Test Transformer ranking") { CHECK_NOTHROW(pgm_tap::build_transformer_graph(get_state(6, 2, 1, 4, 5))); } + SUBCASE("Controlling from non source to source transformer") { + TestState state; + std::vector nodes{{.id = 0, .u_rated = 150e3}, {.id = 1, .u_rated = 10e3}}; + main_core::add_component(state, nodes.begin(), nodes.end(), 50.0); + + std::vector transformers{get_transformer(2, 0, 1, BranchSide::from)}; + main_core::add_component(state, transformers.begin(), transformers.end(), 50.0); + + std::vector sources{SourceInput{.id = 3, .node = 0, .status = IntS{1}, .u_ref = 1.0}}; + main_core::add_component(state, sources.begin(), sources.end(), 50.0); + + std::vector regulators{get_regulator(4, 2, ControlSide::from)}; + main_core::add_component(state, regulators.begin(), regulators.end(), 50.0); + + state.components.set_construction_complete(); + + CHECK_THROWS_AS(pgm_tap::build_transformer_graph(state), AutomaticTapInputError); + } + SUBCASE("Process edge weights") { using vertex_iterator = boost::graph_traits::vertex_iterator; From 3181f59a19c450871c4e7ebc4c56bc306ed565ea Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Tue, 25 Mar 2025 16:33:44 +0100 Subject: [PATCH 11/14] modify to ranking Signed-off-by: Nitish Bharambe --- .../test_tap_position_optimizer.cpp | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp index 18ceee441e..0f1553c26d 100644 --- a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp +++ b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp @@ -185,25 +185,6 @@ TEST_CASE("Test Transformer ranking") { CHECK_NOTHROW(pgm_tap::build_transformer_graph(get_state(6, 2, 1, 4, 5))); } - SUBCASE("Controlling from non source to source transformer") { - TestState state; - std::vector nodes{{.id = 0, .u_rated = 150e3}, {.id = 1, .u_rated = 10e3}}; - main_core::add_component(state, nodes.begin(), nodes.end(), 50.0); - - std::vector transformers{get_transformer(2, 0, 1, BranchSide::from)}; - main_core::add_component(state, transformers.begin(), transformers.end(), 50.0); - - std::vector sources{SourceInput{.id = 3, .node = 0, .status = IntS{1}, .u_ref = 1.0}}; - main_core::add_component(state, sources.begin(), sources.end(), 50.0); - - std::vector regulators{get_regulator(4, 2, ControlSide::from)}; - main_core::add_component(state, regulators.begin(), regulators.end(), 50.0); - - state.components.set_construction_complete(); - - CHECK_THROWS_AS(pgm_tap::build_transformer_graph(state), AutomaticTapInputError); - } - SUBCASE("Process edge weights") { using vertex_iterator = boost::graph_traits::vertex_iterator; @@ -566,6 +547,25 @@ TEST_CASE("Test Transformer ranking") { pgm_tap::RankedTransformerGroups const ref_order{{{Idx2D{3, 0}}, {Idx2D{3, 2}}}, {{Idx2D{3, 1}}}}; CHECK(order == ref_order); } + + SUBCASE("Controlling from non source to source transformer") { + TestState state; + std::vector nodes{{.id = 0, .u_rated = 150e3}, {.id = 1, .u_rated = 10e3}}; + main_core::add_component(state, nodes.begin(), nodes.end(), 50.0); + + std::vector transformers{get_transformer(2, 0, 1, BranchSide::from)}; + main_core::add_component(state, transformers.begin(), transformers.end(), 50.0); + + std::vector sources{SourceInput{.id = 3, .node = 0, .status = IntS{1}, .u_ref = 1.0}}; + main_core::add_component(state, sources.begin(), sources.end(), 50.0); + + std::vector regulators{get_regulator(4, 2, ControlSide::from)}; + main_core::add_component(state, regulators.begin(), regulators.end(), 50.0); + + state.components.set_construction_complete(); + + CHECK_THROWS_AS(pgm_tap::rank_transformers(state), AutomaticTapInputError); + } } namespace optimizer::tap_position_optimizer::test { From ec29fbdf926d2353cb029678d4c2b212d1069655 Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Tue, 25 Mar 2025 16:36:29 +0100 Subject: [PATCH 12/14] fix dijkstra Signed-off-by: Nitish Bharambe --- .../power_grid_model/optimizer/tap_position_optimizer.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp index a85ce43a4b..a287024435 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp @@ -285,9 +285,6 @@ inline void process_edges_dijkstra(Idx v, std::vector& vertex_distan if (u == s && vertex_distances[s] + weight < vertex_distances[t]) { vertex_distances[t] = vertex_distances[s] + weight; pq.emplace(vertex_distances[t], t); - } else if (u == t && vertex_distances[t] + weight < vertex_distances[s]) { - vertex_distances[s] = vertex_distances[t] + weight; - pq.emplace(vertex_distances[s], s); } } } From ae0a525d7dd5d95f179f8662c905a466ed41f444 Mon Sep 17 00:00:00 2001 From: Nitish Bharambe Date: Wed, 26 Mar 2025 11:08:58 +0100 Subject: [PATCH 13/14] change to bgl outedges Signed-off-by: Nitish Bharambe --- .../optimizer/tap_position_optimizer.hpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp index a287024435..4e46ab12d5 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp @@ -261,11 +261,12 @@ inline auto build_transformer_graph(State const& state) -> TransformerGraph { return trafo_graph; } -inline void process_edges_dijkstra(Idx v, std::vector& vertex_distances, TransformerGraph const& graph) { +inline void process_edges_dijkstra(Idx search_start_vertex, std::vector& vertex_distances, + TransformerGraph const& graph) { using TrafoGraphElement = std::pair; std::priority_queue, std::greater<>> pq; - vertex_distances[v] = 0; - pq.emplace(0, v); + vertex_distances[search_start_vertex] = 0; + pq.emplace(0, search_start_vertex); while (!pq.empty()) { auto [dist, u] = pq.top(); @@ -275,14 +276,12 @@ inline void process_edges_dijkstra(Idx v, std::vector& vertex_distan continue; } - BGL_FORALL_EDGES(e, graph, TransformerGraph) { + BGL_FORALL_OUTEDGES(u, e, graph, TransformerGraph) { auto s = boost::source(e, graph); auto t = boost::target(e, graph); const EdgeWeight weight = graph[e].weight; - // We can not use BGL_FORALL_OUTEDGES here because we need information - // regardless of edge direction - if (u == s && vertex_distances[s] + weight < vertex_distances[t]) { + if (vertex_distances[s] + weight < vertex_distances[t]) { vertex_distances[t] = vertex_distances[s] + weight; pq.emplace(vertex_distances[t], t); } From 34e3571fe4f879171955a263e2e779eefeeb49ea Mon Sep 17 00:00:00 2001 From: Jerry Guo Date: Thu, 17 Apr 2025 14:14:33 +0200 Subject: [PATCH 14/14] doc + minor changes to the code Signed-off-by: Jerry Guo --- docs/user_manual/calculations.md | 2 +- .../include/power_grid_model/common/exception.hpp | 2 +- .../optimizer/tap_position_optimizer.hpp | 12 +++++++----- tests/cpp_unit_tests/test_tap_position_optimizer.cpp | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/user_manual/calculations.md b/docs/user_manual/calculations.md index 60de446991..fb0efed394 100644 --- a/docs/user_manual/calculations.md +++ b/docs/user_manual/calculations.md @@ -628,7 +628,7 @@ Power flow calculations that take the behavior of these regulators into account We provide the control logic used for tap changing. For simplicity, we demonstrate the case where the regulator control side and the transformer tap side are at different sides. -- Regulated transformers are ranked according to how close they are to {hoverxreftooltip}`sources ` in terms of the amount of regulated transformers inbetween. +- Regulated transformers are ranked according to how close they are to {hoverxreftooltip}`sources ` in terms of the amount of regulated transformers inbetween. In the presence of meshed grids, transformers with conflicting ranks will be ranked the last. - Transformers are regulated in order according to their ranks. - Initialize all transformers to their starting tap position (see {hoverxreftooltip}`user_manual/calculations:Initialization and exploitation of regulated transformers`) - Find the optimal state using the following procedure diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/common/exception.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/common/exception.hpp index 084108a4be..aae490e986 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/common/exception.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/common/exception.hpp @@ -138,7 +138,7 @@ class IterationDiverge : public PowerGridError { class MaxIterationReached : public IterationDiverge { public: MaxIterationReached(std::string const& msg = "") { - append_msg(std::format("Maximum number of iterations reached{}\n", msg)); + append_msg(std::format("Maximum number of iterations reached {}\n", msg)); } }; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp index 4e46ab12d5..a89b73756b 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp @@ -665,7 +665,7 @@ template struct NodeState { class RankIteration { public: - RankIteration(std::vector iterations_per_rank, Idx rank_index) + RankIteration(std::vector iterations_per_rank, Idx rank_index) : iterations_per_rank_{std::move(iterations_per_rank)}, rank_index_{rank_index} {} // Getters @@ -694,7 +694,7 @@ class RankIteration { }; private: - std::vector iterations_per_rank_; + std::vector iterations_per_rank_; Idx rank_index_{}; }; @@ -1003,7 +1003,7 @@ class TapPositionOptimizerImpl, StateCalculator, strategy_ == OptimizerStrategy::global_maximum || strategy_ == OptimizerStrategy::local_maximum; bool tap_changed = true; Idx rank_index = 0; - RankIteration rank_iterator(std::vector(regulator_order.size()), rank_index); + RankIteration rank_iterator(std::vector(regulator_order.size()), rank_index); while (tap_changed) { tap_changed = false; @@ -1023,8 +1023,10 @@ class TapPositionOptimizerImpl, StateCalculator, rank_index = rank_iterator.rank_index(); if (tap_changed) { - if (static_cast(iterations_per_rank[rank_index]) > 2 * max_tap_ranges_per_rank[rank_index]) { - throw MaxIterationReached{"TapPositionOptimizer::iterate"}; + if (iterations_per_rank[rank_index] > 2 * max_tap_ranges_per_rank[rank_index]) { + throw MaxIterationReached{ + std::format("TapPositionOptimizer::iterate {} iterations reached: {}x2 iterations in rank {}", + iterations_per_rank[rank_index], max_tap_ranges_per_rank[rank_index], rank_index)}; } update_state(update_data); result = calculate_(state, method); diff --git a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp index 0f1553c26d..66aaf92c4d 100644 --- a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp +++ b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp @@ -1663,7 +1663,7 @@ TEST_CASE("Test tap position optmizer I/O") { TEST_CASE("Test RankIterator") { std::vector> const regulator_order = {{0, 0, 0}, {0, 0, 0}}; bool tap_changed{false}; - std::vector iterations_per_rank = {2, 4, 6}; + std::vector iterations_per_rank = {2, 4, 6}; Idx rank_index{0}; bool update{false}; optimizer::tap_position_optimizer::RankIteration rank_iterator(iterations_per_rank, rank_index);