Skip to content

Commit 1624a56

Browse files
authored
Merge branch 'main' into feature/current-sensor-main-model
2 parents 7f4f058 + fca3c9f commit 1624a56

File tree

5 files changed

+1128
-104
lines changed

5 files changed

+1128
-104
lines changed

power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,6 @@ inline auto get_edge_weights(TransformerGraph const& graph) -> TrafoGraphEdgePro
309309
}
310310
auto const edge_src_rank = vertex_distances[boost::source(e, graph)];
311311
auto const edge_tgt_rank = vertex_distances[boost::target(e, graph)];
312-
auto const edge_res = std::min(edge_src_rank, edge_tgt_rank);
313312

314313
// New edge logic for ranking
315314
// | Tap | Control | All edges |
@@ -328,11 +327,11 @@ inline auto get_edge_weights(TransformerGraph const& graph) -> TrafoGraphEdgePro
328327
// side via the bidirectional edge (if it exists). For delta configuration ABC, the above
329328
// situations can happen.
330329
// The logic still holds in meshed grids, albeit operating a more complex graph.
331-
if (edge_src_rank != edge_tgt_rank - 1) {
332-
throw AutomaticTapInputError("The control side of a transformer regulator should be relatively further "
333-
"away from the source than the tap side.\n");
334-
}
335-
if (!is_unreachable(edge_res)) {
330+
if (!is_unreachable(edge_src_rank) || !is_unreachable(edge_tgt_rank)) {
331+
if (edge_src_rank != edge_tgt_rank - 1) {
332+
throw AutomaticTapInputError("The control side of a transformer regulator should be relatively further "
333+
"away from the source than the tap side.\n");
334+
}
336335
result.emplace_back(graph[e].regulated_idx, edge_tgt_rank);
337336
}
338337
}

tests/cpp_unit_tests/test_tap_position_optimizer.cpp

Lines changed: 123 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ using TestComponentContainer =
2424
ThreeWindingTransformer, TransformerTapRegulator, Source>;
2525
using TestState = main_core::MainModelState<TestComponentContainer>;
2626

27-
TransformerInput get_transformer(ID id, ID from, ID to, BranchSide tap_side, IntS tap_pos = na_IntS) {
27+
TransformerInput get_transformer(ID id, ID from, ID to, BranchSide tap_side, IntS tap_pos = na_IntS,
28+
IntS from_status = 1) {
2829
return TransformerInput{.id = id,
2930
.from_node = from,
3031
.to_node = to,
31-
.from_status = 1,
32+
.from_status = from_status,
3233
.to_status = 1,
3334
.u1 = nan,
3435
.u2 = nan,
@@ -184,6 +185,67 @@ TEST_CASE("Test Transformer ranking") {
184185
CHECK_NOTHROW(pgm_tap::build_transformer_graph(get_state(6, 2, 1, 4, 5)));
185186
}
186187

188+
SUBCASE("Process edge weights") {
189+
using vertex_iterator = boost::graph_traits<pgm_tap::TransformerGraph>::vertex_iterator;
190+
191+
// Dummy graph
192+
pgm_tap::TrafoGraphEdges const edge_array = {{0, 1}, {0, 2}, {2, 3}};
193+
pgm_tap::TrafoGraphEdgeProperties const edge_prop{{{0, 1}, 1}, {{-1, -1}, 0}, {{2, 3}, 1}};
194+
std::vector<pgm_tap::TrafoGraphVertex> vertex_props{{true}, {false}, {false}, {false}};
195+
196+
pgm_tap::TransformerGraph g{boost::edges_are_unsorted_multi_pass, edge_array.cbegin(), edge_array.cend(),
197+
edge_prop.cbegin(), 4};
198+
199+
// Vertex properties can not be set during graph creation
200+
vertex_iterator vi;
201+
vertex_iterator vi_end;
202+
for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
203+
g[*vi].is_source = vertex_props[*vi].is_source;
204+
}
205+
206+
pgm_tap::TrafoGraphEdgeProperties const regulated_edge_weights = get_edge_weights(g);
207+
pgm_tap::TrafoGraphEdgeProperties const ref_regulated_edge_weights{{{0, 1}, 1}, {{2, 3}, 1}};
208+
CHECK(regulated_edge_weights == ref_regulated_edge_weights);
209+
}
210+
211+
SUBCASE("Sorting transformer edges") {
212+
pgm_tap::TrafoGraphEdgeProperties const trafoList{
213+
{Idx2D{1, 1}, pgm_tap::infty}, {Idx2D{1, 2}, 5}, {Idx2D{1, 3}, 4}, {Idx2D{2, 1}, 4}};
214+
215+
pgm_tap::RankedTransformerGroups const referenceList{{Idx2D{1, 3}, Idx2D{2, 1}}, {Idx2D{1, 2}}, {Idx2D{1, 1}}};
216+
217+
pgm_tap::RankedTransformerGroups const sortedTrafoList = pgm_tap::rank_transformers(trafoList);
218+
REQUIRE(sortedTrafoList.size() == referenceList.size());
219+
for (Idx idx : boost::counting_range(Idx{0}, static_cast<Idx>(sortedTrafoList.size()))) {
220+
CAPTURE(idx);
221+
CHECK(sortedTrafoList[idx] == referenceList[idx]);
222+
}
223+
}
224+
225+
SUBCASE("Multiple source grid") {
226+
using vertex_iterator = boost::graph_traits<pgm_tap::TransformerGraph>::vertex_iterator;
227+
228+
// Grid with multiple sources and symetric graph
229+
pgm_tap::TrafoGraphEdges const edge_array = {{0, 1}, {1, 2}, {3, 2}, {4, 3}};
230+
pgm_tap::TrafoGraphEdgeProperties const edge_prop{{{0, 1}, 1}, {{1, 2}, 1}, {{2, 3}, 1}, {{3, 4}, 1}};
231+
std::vector<pgm_tap::TrafoGraphVertex> vertex_props{{true}, {false}, {false}, {false}, {true}};
232+
233+
pgm_tap::TransformerGraph g{boost::edges_are_unsorted_multi_pass, edge_array.cbegin(), edge_array.cend(),
234+
edge_prop.cbegin(), 5};
235+
236+
// Vertex properties can not be set during graph creation
237+
vertex_iterator vi;
238+
vertex_iterator vi_end;
239+
for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
240+
g[*vi].is_source = vertex_props[*vi].is_source;
241+
}
242+
243+
pgm_tap::TrafoGraphEdgeProperties const regulated_edge_weights = get_edge_weights(g);
244+
pgm_tap::TrafoGraphEdgeProperties const ref_regulated_edge_weights{
245+
{{0, 1}, 1}, {{1, 2}, 2}, {{2, 3}, 2}, {{3, 4}, 1}};
246+
CHECK(regulated_edge_weights == ref_regulated_edge_weights);
247+
}
248+
187249
SUBCASE("Full grid 1 - For graph construction steps") {
188250
// =====Test Grid=====
189251
// ________[0]________
@@ -194,19 +256,24 @@ TEST_CASE("Test Transformer ranking") {
194256
// | [6] |
195257
// [3]----------| [8]
196258
// | |
197-
// L---------------[9]
259+
// L---------------[9] -----x- [100]
260+
//
261+
// [101] ---- [102]
262+
198263
TestState state;
199-
std::vector<NodeInput> nodes{{.id = 0, .u_rated = 150e3}, {.id = 1, .u_rated = 10e3},
200-
{.id = 2, .u_rated = 10e3}, {.id = 3, .u_rated = 10e3},
201-
{.id = 4, .u_rated = 10e3}, {.id = 5, .u_rated = 50e3},
202-
{.id = 6, .u_rated = 10e3}, {.id = 7, .u_rated = 10e3},
203-
{.id = 8, .u_rated = 10e3}, {.id = 9, .u_rated = 10e3}};
264+
std::vector<NodeInput> nodes{
265+
{.id = 0, .u_rated = 150e3}, {.id = 1, .u_rated = 10e3}, {.id = 2, .u_rated = 10e3},
266+
{.id = 3, .u_rated = 10e3}, {.id = 4, .u_rated = 10e3}, {.id = 5, .u_rated = 50e3},
267+
{.id = 6, .u_rated = 10e3}, {.id = 7, .u_rated = 10e3}, {.id = 8, .u_rated = 10e3},
268+
{.id = 9, .u_rated = 10e3}, {.id = 100, .u_rated = 10e3}, {.id = 101, .u_rated = 10e3},
269+
{.id = 102, .u_rated = 10e3}};
204270
main_core::add_component<Node>(state, nodes.begin(), nodes.end(), 50.0);
205271

206272
std::vector<TransformerInput> transformers{
207-
get_transformer(11, 0, 1, BranchSide::from), get_transformer(12, 0, 1, BranchSide::from),
208-
get_transformer(13, 5, 7, BranchSide::from), get_transformer(14, 2, 3, BranchSide::from),
209-
get_transformer(15, 8, 9, BranchSide::from)};
273+
get_transformer(11, 0, 1, BranchSide::from), get_transformer(12, 0, 1, BranchSide::from),
274+
get_transformer(13, 5, 7, BranchSide::from), get_transformer(14, 2, 3, BranchSide::from),
275+
get_transformer(15, 8, 9, BranchSide::from), get_transformer(103, 9, 100, BranchSide::from, na_IntS, 0),
276+
get_transformer(104, 101, 102, BranchSide::from)};
210277
main_core::add_component<Transformer>(state, transformers.begin(), transformers.end(), 50.0);
211278

212279
std::vector<ThreeWindingTransformerInput> transformers3w{
@@ -232,9 +299,10 @@ TEST_CASE("Test Transformer ranking") {
232299
main_core::add_component<Source>(state, sources.begin(), sources.end(), 50.0);
233300

234301
std::vector<TransformerTapRegulatorInput> regulators{
235-
get_regulator(23, 11, ControlSide::to), get_regulator(24, 12, ControlSide::to),
236-
get_regulator(25, 13, ControlSide::to), get_regulator(26, 14, ControlSide::to),
237-
get_regulator(27, 15, ControlSide::to), get_regulator(28, 16, ControlSide::side_2)};
302+
get_regulator(23, 11, ControlSide::to), get_regulator(24, 12, ControlSide::to),
303+
get_regulator(25, 13, ControlSide::to), get_regulator(26, 14, ControlSide::to),
304+
get_regulator(27, 15, ControlSide::to), get_regulator(28, 16, ControlSide::side_2),
305+
get_regulator(105, 103, ControlSide::from), get_regulator(106, 104, ControlSide::from)};
238306
main_core::add_component<TransformerTapRegulator>(state, regulators.begin(), regulators.end(), 50.0);
239307

240308
state.components.set_construction_complete();
@@ -250,14 +318,16 @@ TEST_CASE("Test Transformer ranking") {
250318
{{.group = 3, .pos = 1}, 1},
251319
{{.group = 3, .pos = 2}, 1},
252320
{{.group = 3, .pos = 3}, 1},
253-
{{.group = 3, .pos = 4}, 1}});
321+
{{.group = 3, .pos = 4}, 1},
322+
{{.group = 3, .pos = 6}, 1}});
254323
expected_edges_prop.insert(
255324
expected_edges_prop.end(),
256325
{{{.group = 4, .pos = 0}, 1}, {{.group = 4, .pos = 0}, 1}, {unregulated_idx, 0}, {unregulated_idx, 0}});
257326
expected_edges_prop.insert(expected_edges_prop.end(), 10, {unregulated_idx, 0});
258327

259328
std::vector<pgm_tap::TrafoGraphVertex> const expected_vertex_props{
260-
{true}, {false}, {false}, {false}, {false}, {false}, {false}, {false}, {false}, {false}};
329+
{true}, {false}, {false}, {false}, {false}, {false}, {false},
330+
{false}, {false}, {false}, {false}, {false}, {false}};
261331

262332
pgm_tap::TransformerGraph actual_graph = pgm_tap::build_transformer_graph(state);
263333
pgm_tap::TrafoGraphEdgeProperties actual_edges_prop;
@@ -365,21 +435,37 @@ TEST_CASE("Test Transformer ranking") {
365435
// | | |
366436
// [2] | [8]
367437
// | [6] |
368-
// [3]----[7]---| [9]
438+
// [3]----[7]---| [9] ----x- [100]
369439
// | |
370440
// L--------------[10]
441+
//
442+
// [101] ---- [102]
371443
TestState state;
372-
std::vector<NodeInput> nodes{
373-
{.id = 0, .u_rated = 150e3}, {.id = 1, .u_rated = 10e3}, {.id = 2, .u_rated = 10e3},
374-
{.id = 3, .u_rated = 10e3}, {.id = 4, .u_rated = 10e3}, {.id = 5, .u_rated = 50e3},
375-
{.id = 6, .u_rated = 10e3}, {.id = 7, .u_rated = 10e3}, {.id = 8, .u_rated = 10e3},
376-
{.id = 9, .u_rated = 10e3}, {.id = 10, .u_rated = 10e3}};
444+
std::vector<NodeInput> nodes{{.id = 0, .u_rated = 150e3},
445+
{.id = 1, .u_rated = 10e3},
446+
{.id = 2, .u_rated = 10e3},
447+
{.id = 3, .u_rated = 10e3},
448+
{4, 10e3},
449+
{.id = 5, .u_rated = 50e3},
450+
{.id = 6, .u_rated = 10e3},
451+
{.id = 7, .u_rated = 10e3},
452+
{.id = 8, .u_rated = 10e3},
453+
{9, 10e3},
454+
{.id = 10, .u_rated = 10e3},
455+
{.id = 100, .u_rated = 10e3},
456+
{.id = 101, .u_rated = 10e3},
457+
{.id = 102, .u_rated = 10e3}};
458+
377459
main_core::add_component<Node>(state, nodes.begin(), nodes.end(), 50.0);
378460

379-
std::vector<TransformerInput> transformers{
380-
get_transformer(11, 0, 1, BranchSide::to), get_transformer(12, 0, 1, BranchSide::from),
381-
get_transformer(13, 2, 3, BranchSide::from), get_transformer(14, 6, 7, BranchSide::from),
382-
get_transformer(15, 5, 8, BranchSide::from), get_transformer(16, 9, 10, BranchSide::from)};
461+
std::vector<TransformerInput> transformers{get_transformer(11, 0, 1, BranchSide::to),
462+
get_transformer(12, 0, 1, BranchSide::from),
463+
get_transformer(13, 2, 3, BranchSide::from),
464+
get_transformer(14, 6, 7, BranchSide::from),
465+
get_transformer(15, 5, 8, BranchSide::from),
466+
get_transformer(16, 9, 10, BranchSide::from),
467+
get_transformer(103, 9, 100, BranchSide::from, na_IntS, 0),
468+
get_transformer(104, 101, 102, BranchSide::from)};
383469
main_core::add_component<Transformer>(state, transformers.begin(), transformers.end(), 50.0);
384470

385471
std::vector<ThreeWindingTransformerInput> transformers3w{
@@ -405,23 +491,21 @@ TEST_CASE("Test Transformer ranking") {
405491
main_core::add_component<Source>(state, sources.begin(), sources.end(), 50.0);
406492

407493
std::vector<TransformerTapRegulatorInput> regulators{
408-
get_regulator(24, 11, ControlSide::to), get_regulator(25, 12, ControlSide::to),
409-
get_regulator(26, 13, ControlSide::to), get_regulator(27, 14, ControlSide::to),
410-
get_regulator(28, 15, ControlSide::to), get_regulator(29, 16, ControlSide::to),
411-
get_regulator(30, 17, ControlSide::side_2)};
494+
get_regulator(24, 11, ControlSide::to), get_regulator(25, 12, ControlSide::to),
495+
get_regulator(26, 13, ControlSide::to), get_regulator(27, 14, ControlSide::to),
496+
get_regulator(28, 15, ControlSide::to), get_regulator(29, 16, ControlSide::to),
497+
get_regulator(30, 17, ControlSide::side_2), get_regulator(105, 103, ControlSide::from),
498+
get_regulator(106, 104, ControlSide::from)};
412499
main_core::add_component<TransformerTapRegulator>(state, regulators.begin(), regulators.end(), 50.0);
413500

414501
state.components.set_construction_complete();
415502

416-
// Subcases
417-
SUBCASE("Ranking complete the graph") {
418-
pgm_tap::RankedTransformerGroups order = pgm_tap::rank_transformers(state);
419-
pgm_tap::RankedTransformerGroups const ref_order{
420-
{{Idx2D{.group = 3, .pos = 0}, Idx2D{.group = 3, .pos = 1}, Idx2D{.group = 4, .pos = 0},
421-
Idx2D{.group = 3, .pos = 4}},
422-
{Idx2D{.group = 3, .pos = 2}, Idx2D{.group = 3, .pos = 3}, Idx2D{.group = 3, .pos = 5}}}};
423-
CHECK(order == ref_order);
424-
}
503+
pgm_tap::RankedTransformerGroups order = pgm_tap::rank_transformers(state);
504+
pgm_tap::RankedTransformerGroups const ref_order{
505+
{{Idx2D{.group = 3, .pos = 0}, Idx2D{.group = 3, .pos = 1}, Idx2D{.group = 4, .pos = 0},
506+
Idx2D{.group = 3, .pos = 4}},
507+
{Idx2D{.group = 3, .pos = 2}, Idx2D{.group = 3, .pos = 3}, Idx2D{.group = 3, .pos = 5}}}};
508+
CHECK(order == ref_order);
425509
}
426510
}
427511

0 commit comments

Comments
 (0)