From b3879993ef3a6d7a547eaebf3a3bfd196a563400 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 20 Nov 2023 11:11:57 +0100 Subject: [PATCH 01/66] add sparse iteration to code base Signed-off-by: Martijn Govers --- .../math_solver/sparse_iteration.hpp | 231 ++++++++++++++++++ tests/cpp_unit_tests/CMakeLists.txt | 1 + .../cpp_unit_tests/test_sparse_iteration.cpp | 57 +++++ 3 files changed, 289 insertions(+) create mode 100644 power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_iteration.hpp create mode 100644 tests/cpp_unit_tests/test_sparse_iteration.cpp diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_iteration.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_iteration.hpp new file mode 100644 index 000000000..b91ae4bf6 --- /dev/null +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_iteration.hpp @@ -0,0 +1,231 @@ +// SPDX-FileCopyrightText: 2022 Contributors to the Power Grid Model project +// +// SPDX-License-Identifier: MPL-2.0 + +#pragma once +#ifndef POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ITERATION_HPP +#define POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ITERATION_HPP + +#include "../power_grid_model.hpp" + +#include // remove and remove_if +#include +#include +#include +#include +#include + +namespace power_grid_model::math_solver { + +void rmElemVectPair(ID& u, std::vector>& dgd) { + ID i = 0; + while (i < dgd.size()) + if (dgd[i].first == u) { + dgd.erase(dgd.begin() + i); + break; + } else + i++; +} + +void setElemVectPair(ID& u, ID v, std::vector>& dgd) { + ID i = 0; + while (i < dgd.size()) { + if (dgd[i].first == u) { + dgd[i].second = v; + break; + } else { + i++; + } + } +} + +std::vector adj(ID& u, std::map>& d) { + std::vector l; + + for (const auto& it : d) { + if (it.first == u) + l.insert(l.end(), it.second.begin(), it.second.end()); + + if (find(it.second.begin(), it.second.end(), u) != it.second.end()) { + std::vector v{it.first}; + l.insert(l.end(), v.begin(), v.end()); + } + } + + return l; +} + +bool cmpFirts(std::pair& a, std::pair& b) { return a.first < b.first; } + +std::vector>>> compSizeDegreesGraph(std::map>& d) { + std::vector> dd; + std::vector v; + ID n = 0; + + for (const auto& it : d) { + ID k = it.first; + if (find(v.begin(), v.end(), k) == v.end()) { + std::vector vk{k}; + v.insert(v.end(), vk.begin(), vk.end()); + n += 1; + dd.push_back({k, adj(k, d).size()}); + } + for (const ID& el : it.second) { + ID e = el; + if (find(v.begin(), v.end(), e) == v.end()) { + std::vector ve{e}; + v.insert(v.end(), ve.begin(), ve.end()); + n += 1; + dd.push_back({e, adj(e, d).size()}); + } + } + } + + sort(dd.begin(), dd.end(), cmpFirts); + + return {{n, dd}}; +} + +std::vector, std::vector>> checkIndistguishable(ID& u, std::map>& d) { + std::vector l, rl, lu, lv, vu{u}, vv; + l = adj(u, d); + lu = l; + lu.insert(lu.end(), vu.begin(), vu.end()); + + for (auto& v : l) { + lv = adj(v, d); + vv = {v}; + lv.insert(lv.end(), vv.begin(), vv.end()); + sort(lu.begin(), lu.end()); + sort(lv.begin(), lv.end()); + if (lu == lv) { + rl.insert(rl.end(), vv.begin(), vv.end()); + } + } + + return {{l, rl}}; +} + +std::map> makeClique(std::vector& l) { + std::map> d; + ID b = l.size() - 1; + + for (int i = 0; i < b; i++) { + ID index = i + 1; + auto start = l.begin() + index; + std::vector sl(l.size() - index); + copy(start, l.end(), sl.begin()); + d[l[i]] = sl; + } + + return d; +} + +bool inGraph(std::vector& e, std::map>& d) { + bool t1 = (d.find(e[0]) != d.end()) and (find(d[e[0]].begin(), d[e[0]].end(), e[1]) != d[e[0]].end()); + bool t2 = (d.find(e[1]) != d.end()) and (find(d[e[1]].begin(), d[e[1]].end(), e[0]) != d[e[1]].end()); + + return (t1 || t2); +} + +std::vector rmvVerticesUpdateDegrees(ID& u, std::map>& d, std::vector>& dgd, + std::vector>& fills) { + std::vector, std::vector>> nbsrl = checkIndistguishable(u, d); + std::vector& nbs = nbsrl[0].first; + std::vector& rl = nbsrl[0].second; + std::vector alpha = rl, vu{u}; + std::map> dd; + + rl.insert(rl.begin(), vu.begin(), vu.end()); + + for (auto& uu : rl) { + if (uu != u) + nbs.erase(remove(nbs.begin(), nbs.end(), uu), nbs.end()); + + rmElemVectPair(uu, dgd); + std::vector el; + for (auto& it : d) { + it.second.erase(remove(it.second.begin(), it.second.end(), uu), it.second.end()); + if (it.second.empty()) { + ID k = it.first; + std::vector vk{k}; + el.insert(el.end(), vk.begin(), vk.end()); + } + } + + std::vector vuu{uu}; + el.insert(el.end(), vuu.begin(), vuu.end()); + + for (auto& it : el) + d.erase(it); + } + + dd = makeClique(nbs); + + for (auto& it : dd) { + ID k = it.first; + for (const ID& e : it.second) { + std::vector t{k, e}; + if (not inGraph(t, d)) { + if (d.find(k) != d.end()) { + std::vector ve{e}; + d[k].insert(d[k].end(), ve.begin(), ve.end()); + fills.push_back({k, e}); + } else if (d.find(e) != d.end()) { + std::vector vk{k}; + d[e].insert(d[e].end(), vk.begin(), vk.end()); + fills.push_back({e, k}); + } else { + std::vector ve{e}; + d[k].insert(d[k].end(), ve.begin(), ve.end()); + fills.push_back({k, e}); + } + } + } + } + + for (auto& e : nbs) { + setElemVectPair(e, adj(e, d).size(), dgd); + } + + return alpha; +} + +std::vector, std::vector>>> +minimumDegreeAlgorithm(std::map>& d) { + std::vector>>> data = compSizeDegreesGraph(d); + ID& n = data[0].first; + std::vector>& dgd = data[0].second; + std::vector alpha; + std::vector> fills; + std::vector, std::vector>>> alpha_fills; + + for (int k = 0; k < n; k++) { + ID u = get<0>(*min_element(begin(dgd), end(dgd), [](auto lhs, auto rhs) { return get<1>(lhs) < get<1>(rhs); })); + std::vector vu{u}; + alpha.insert(alpha.end(), vu.begin(), vu.end()); + if ((d.size() == 1) and d.begin()->second.size() == 1) { + ID a = d.begin()->first; + ID b = d.begin()->second[0]; + if (alpha.back() == a) { + std::vector vb{b}; + alpha.insert(alpha.end(), vb.begin(), vb.end()); + } else { + std::vector va{a}; + alpha.insert(alpha.end(), va.begin(), va.end()); + } + break; + } else { + std::vector va = rmvVerticesUpdateDegrees(u, d, dgd, fills); + alpha.insert(alpha.end(), va.begin(), va.end()); + if (d.empty()) { + break; + } + } + } + alpha_fills = {{alpha, fills}}; + return alpha_fills; +} +} // namespace power_grid_model::math_solver + +#endif diff --git a/tests/cpp_unit_tests/CMakeLists.txt b/tests/cpp_unit_tests/CMakeLists.txt index aa270ec72..5b358fc75 100644 --- a/tests/cpp_unit_tests/CMakeLists.txt +++ b/tests/cpp_unit_tests/CMakeLists.txt @@ -18,6 +18,7 @@ set(PROJECT_SOURCES "test_shunt.cpp" "test_transformer.cpp" "test_sparse_lu_solver.cpp" + "test_sparse_iteration.cpp" "test_y_bus.cpp" "test_math_solver.cpp" "test_measured_values.cpp" diff --git a/tests/cpp_unit_tests/test_sparse_iteration.cpp b/tests/cpp_unit_tests/test_sparse_iteration.cpp new file mode 100644 index 000000000..8a72f4af0 --- /dev/null +++ b/tests/cpp_unit_tests/test_sparse_iteration.cpp @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: 2022 Contributors to the Power Grid Model project +// +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include + +#include + +namespace { +namespace solver = power_grid_model::math_solver; +using namespace power_grid_model; + +void printVectPair(std::vector>& d) { + for (const auto& it : d) { + std::cout << it.first << ": " << it.second << std::endl; + } +} + +void printMap(std::map>& d) { + for (const auto& it : d) { + std::cout << it.first << ": "; + for (const ID& el : it.second) { + std::cout << el << " "; + } + std::cout << std::endl; + } +} + +void show(std::vector const& input) { + for (auto const& i : input) + std::cout << i << ", "; + std::cout << std::endl; +} +} // namespace + +TEST_CASE("Test sparse iteration") { + std::map> graph{{0, {3, 5}}, {1, {4, 5, 8}}, {2, {4, 5, 6}}, {3, {6, 7}}, + {4, {6, 8}}, {6, {7, 8, 9}}, {7, {8, 9}}, {8, {9}}}; + + auto start = std::chrono::high_resolution_clock::now(); + std::vector, std::vector>>> alpha_fills = + solver::minimumDegreeAlgorithm(graph); + auto stop = std::chrono::high_resolution_clock::now(); + + auto duration = duration_cast(stop - start); + float seconds = duration.count() / 1000000.0; + /* + std::cout << "Time taken by function: " + << duration.count() << " microseconds" << std::endl; + */ + std::cout << "Time taken by function: " << seconds << " seconds" << std::endl; + + show(alpha_fills[0].first); + printVectPair(alpha_fills[0].second); +} From bf05a4d9d08ffcc50bff1b0acf51a0f5d18eb505 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 20 Nov 2023 11:22:39 +0100 Subject: [PATCH 02/66] fix naming conventions Signed-off-by: Martijn Govers --- .../math_solver/sparse_iteration.hpp | 50 ++++++++++--------- .../cpp_unit_tests/test_sparse_iteration.cpp | 23 +++------ 2 files changed, 34 insertions(+), 39 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_iteration.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_iteration.hpp index b91ae4bf6..ab13eac21 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_iteration.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_iteration.hpp @@ -17,17 +17,20 @@ namespace power_grid_model::math_solver { -void rmElemVectPair(ID& u, std::vector>& dgd) { +namespace detail { +void remove_element_vector_pair(ID& u, std::vector>& dgd) { ID i = 0; - while (i < dgd.size()) + while (i < dgd.size()) { if (dgd[i].first == u) { dgd.erase(dgd.begin() + i); break; - } else + } else { i++; + } + } } -void setElemVectPair(ID& u, ID v, std::vector>& dgd) { +void set_element_vector_pair(ID& u, ID v, std::vector>& dgd) { ID i = 0; while (i < dgd.size()) { if (dgd[i].first == u) { @@ -55,9 +58,9 @@ std::vector adj(ID& u, std::map>& d) { return l; } -bool cmpFirts(std::pair& a, std::pair& b) { return a.first < b.first; } +bool compair_ids(std::pair& a, std::pair& b) { return a.first < b.first; } -std::vector>>> compSizeDegreesGraph(std::map>& d) { +std::vector>>> comp_size_degrees_graph(std::map>& d) { std::vector> dd; std::vector v; ID n = 0; @@ -81,12 +84,13 @@ std::vector>>> compSizeDegreesGraph( } } - sort(dd.begin(), dd.end(), cmpFirts); + sort(dd.begin(), dd.end()); return {{n, dd}}; } -std::vector, std::vector>> checkIndistguishable(ID& u, std::map>& d) { +std::vector, std::vector>> check_indistguishable(ID& u, + std::map>& d) { std::vector l, rl, lu, lv, vu{u}, vv; l = adj(u, d); lu = l; @@ -106,7 +110,7 @@ std::vector, std::vector>> checkIndistguishable(ID return {{l, rl}}; } -std::map> makeClique(std::vector& l) { +std::map> make_clique(std::vector& l) { std::map> d; ID b = l.size() - 1; @@ -121,16 +125,17 @@ std::map> makeClique(std::vector& l) { return d; } -bool inGraph(std::vector& e, std::map>& d) { +bool in_graph(std::vector& e, std::map>& d) { bool t1 = (d.find(e[0]) != d.end()) and (find(d[e[0]].begin(), d[e[0]].end(), e[1]) != d[e[0]].end()); bool t2 = (d.find(e[1]) != d.end()) and (find(d[e[1]].begin(), d[e[1]].end(), e[0]) != d[e[1]].end()); return (t1 || t2); } -std::vector rmvVerticesUpdateDegrees(ID& u, std::map>& d, std::vector>& dgd, - std::vector>& fills) { - std::vector, std::vector>> nbsrl = checkIndistguishable(u, d); +std::vector remove_vertices_update_degrees(ID& u, std::map>& d, + std::vector>& dgd, + std::vector>& fills) { + std::vector, std::vector>> nbsrl = check_indistguishable(u, d); std::vector& nbs = nbsrl[0].first; std::vector& rl = nbsrl[0].second; std::vector alpha = rl, vu{u}; @@ -142,7 +147,7 @@ std::vector rmvVerticesUpdateDegrees(ID& u, std::map>& d if (uu != u) nbs.erase(remove(nbs.begin(), nbs.end(), uu), nbs.end()); - rmElemVectPair(uu, dgd); + remove_element_vector_pair(uu, dgd); std::vector el; for (auto& it : d) { it.second.erase(remove(it.second.begin(), it.second.end(), uu), it.second.end()); @@ -160,13 +165,13 @@ std::vector rmvVerticesUpdateDegrees(ID& u, std::map>& d d.erase(it); } - dd = makeClique(nbs); + dd = make_clique(nbs); for (auto& it : dd) { ID k = it.first; for (const ID& e : it.second) { std::vector t{k, e}; - if (not inGraph(t, d)) { + if (not in_graph(t, d)) { if (d.find(k) != d.end()) { std::vector ve{e}; d[k].insert(d[k].end(), ve.begin(), ve.end()); @@ -185,20 +190,20 @@ std::vector rmvVerticesUpdateDegrees(ID& u, std::map>& d } for (auto& e : nbs) { - setElemVectPair(e, adj(e, d).size(), dgd); + set_element_vector_pair(e, adj(e, d).size(), dgd); } return alpha; } +} // namespace detail std::vector, std::vector>>> -minimumDegreeAlgorithm(std::map>& d) { - std::vector>>> data = compSizeDegreesGraph(d); +minimum_degree_ordering(std::map>& d) { + std::vector>>> data = detail::comp_size_degrees_graph(d); ID& n = data[0].first; std::vector>& dgd = data[0].second; std::vector alpha; std::vector> fills; - std::vector, std::vector>>> alpha_fills; for (int k = 0; k < n; k++) { ID u = get<0>(*min_element(begin(dgd), end(dgd), [](auto lhs, auto rhs) { return get<1>(lhs) < get<1>(rhs); })); @@ -216,15 +221,14 @@ minimumDegreeAlgorithm(std::map>& d) { } break; } else { - std::vector va = rmvVerticesUpdateDegrees(u, d, dgd, fills); + std::vector va = detail::remove_vertices_update_degrees(u, d, dgd, fills); alpha.insert(alpha.end(), va.begin(), va.end()); if (d.empty()) { break; } } } - alpha_fills = {{alpha, fills}}; - return alpha_fills; + return {{alpha, fills}}; } } // namespace power_grid_model::math_solver diff --git a/tests/cpp_unit_tests/test_sparse_iteration.cpp b/tests/cpp_unit_tests/test_sparse_iteration.cpp index 8a72f4af0..8e80d7843 100644 --- a/tests/cpp_unit_tests/test_sparse_iteration.cpp +++ b/tests/cpp_unit_tests/test_sparse_iteration.cpp @@ -12,25 +12,16 @@ namespace { namespace solver = power_grid_model::math_solver; using namespace power_grid_model; -void printVectPair(std::vector>& d) { +void print_vector_pair(std::vector>& d) { for (const auto& it : d) { std::cout << it.first << ": " << it.second << std::endl; } } -void printMap(std::map>& d) { - for (const auto& it : d) { - std::cout << it.first << ": "; - for (const ID& el : it.second) { - std::cout << el << " "; - } - std::cout << std::endl; - } -} - -void show(std::vector const& input) { - for (auto const& i : input) +void print_vector(std::vector const& input) { + for (auto const& i : input) { std::cout << i << ", "; + } std::cout << std::endl; } } // namespace @@ -41,7 +32,7 @@ TEST_CASE("Test sparse iteration") { auto start = std::chrono::high_resolution_clock::now(); std::vector, std::vector>>> alpha_fills = - solver::minimumDegreeAlgorithm(graph); + solver::minimum_degree_ordering(graph); auto stop = std::chrono::high_resolution_clock::now(); auto duration = duration_cast(stop - start); @@ -52,6 +43,6 @@ TEST_CASE("Test sparse iteration") { */ std::cout << "Time taken by function: " << seconds << " seconds" << std::endl; - show(alpha_fills[0].first); - printVectPair(alpha_fills[0].second); + print_vector(alpha_fills[0].first); + print_vector_pair(alpha_fills[0].second); } From d970f42aa2174d5e6cbdcac40857c8d61bb5f6e2 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 22 Nov 2023 09:05:21 +0100 Subject: [PATCH 03/66] different location Signed-off-by: Martijn Govers --- ...arse_iteration.hpp => sparse_ordening.hpp} | 7 ++- tests/cpp_unit_tests/CMakeLists.txt | 2 +- .../cpp_unit_tests/test_sparse_iteration.cpp | 48 ----------------- tests/cpp_unit_tests/test_sparse_ordening.cpp | 52 +++++++++++++++++++ 4 files changed, 56 insertions(+), 53 deletions(-) rename power_grid_model_c/power_grid_model/include/power_grid_model/{math_solver/sparse_iteration.hpp => sparse_ordening.hpp} (98%) delete mode 100644 tests/cpp_unit_tests/test_sparse_iteration.cpp create mode 100644 tests/cpp_unit_tests/test_sparse_ordening.cpp diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_iteration.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp similarity index 98% rename from power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_iteration.hpp rename to power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index ab13eac21..a476a0a57 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_iteration.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -6,16 +6,15 @@ #ifndef POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ITERATION_HPP #define POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ITERATION_HPP -#include "../power_grid_model.hpp" +#include "power_grid_model.hpp" #include // remove and remove_if -#include #include #include #include #include -namespace power_grid_model::math_solver { +namespace power_grid_model { namespace detail { void remove_element_vector_pair(ID& u, std::vector>& dgd) { @@ -230,6 +229,6 @@ minimum_degree_ordering(std::map>& d) { } return {{alpha, fills}}; } -} // namespace power_grid_model::math_solver +} // namespace power_grid_model #endif diff --git a/tests/cpp_unit_tests/CMakeLists.txt b/tests/cpp_unit_tests/CMakeLists.txt index 5b358fc75..2c05a5c43 100644 --- a/tests/cpp_unit_tests/CMakeLists.txt +++ b/tests/cpp_unit_tests/CMakeLists.txt @@ -18,11 +18,11 @@ set(PROJECT_SOURCES "test_shunt.cpp" "test_transformer.cpp" "test_sparse_lu_solver.cpp" - "test_sparse_iteration.cpp" "test_y_bus.cpp" "test_math_solver.cpp" "test_measured_values.cpp" "test_topology.cpp" + "test_sparse_ordening.cpp" "test_grouped_index_vector.cpp" "test_container.cpp" "test_sparse_mapping.cpp" diff --git a/tests/cpp_unit_tests/test_sparse_iteration.cpp b/tests/cpp_unit_tests/test_sparse_iteration.cpp deleted file mode 100644 index 8e80d7843..000000000 --- a/tests/cpp_unit_tests/test_sparse_iteration.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Contributors to the Power Grid Model project -// -// SPDX-License-Identifier: MPL-2.0 - -#include - -#include - -#include - -namespace { -namespace solver = power_grid_model::math_solver; -using namespace power_grid_model; - -void print_vector_pair(std::vector>& d) { - for (const auto& it : d) { - std::cout << it.first << ": " << it.second << std::endl; - } -} - -void print_vector(std::vector const& input) { - for (auto const& i : input) { - std::cout << i << ", "; - } - std::cout << std::endl; -} -} // namespace - -TEST_CASE("Test sparse iteration") { - std::map> graph{{0, {3, 5}}, {1, {4, 5, 8}}, {2, {4, 5, 6}}, {3, {6, 7}}, - {4, {6, 8}}, {6, {7, 8, 9}}, {7, {8, 9}}, {8, {9}}}; - - auto start = std::chrono::high_resolution_clock::now(); - std::vector, std::vector>>> alpha_fills = - solver::minimum_degree_ordering(graph); - auto stop = std::chrono::high_resolution_clock::now(); - - auto duration = duration_cast(stop - start); - float seconds = duration.count() / 1000000.0; - /* - std::cout << "Time taken by function: " - << duration.count() << " microseconds" << std::endl; - */ - std::cout << "Time taken by function: " << seconds << " seconds" << std::endl; - - print_vector(alpha_fills[0].first); - print_vector_pair(alpha_fills[0].second); -} diff --git a/tests/cpp_unit_tests/test_sparse_ordening.cpp b/tests/cpp_unit_tests/test_sparse_ordening.cpp new file mode 100644 index 000000000..0cf1c9edb --- /dev/null +++ b/tests/cpp_unit_tests/test_sparse_ordening.cpp @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: 2022 Contributors to the Power Grid Model project +// +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include + +#include +#include +#include + +namespace { +using namespace power_grid_model; + +auto to_string(std::vector> const& d) { + std::stringstream sstr; + sstr << "{"; + for (const auto& it : d) { + sstr << it.first << ": " << it.second << ", "; + } + sstr << "}"; + return sstr.str(); +} + +auto to_string(std::vector const& input) { + std::stringstream sstr; + for (auto const& i : input) { + sstr << i << ", "; + } + return sstr.str(); +} +} // namespace + +TEST_CASE("Test sparse ordening") { + SUBCASE("minimum_degree_ordening") { + std::map> graph{{0, {3, 5}}, {1, {4, 5, 8}}, {2, {4, 5, 6}}, {3, {6, 7}}, + {4, {6, 8}}, {6, {7, 8, 9}}, {7, {8, 9}}, {8, {9}}}; + + auto const start = std::chrono::high_resolution_clock::now(); + std::vector, std::vector>>> const alpha_fills = + minimum_degree_ordering(graph); + auto const stop = std::chrono::high_resolution_clock::now(); + + auto const duration = duration_cast(stop - start); + std::cout << "Time taken by function: " << duration.count() << " microseconds" + << "\n"; + + std::cout << to_string(alpha_fills[0].first) << "\n"; + std::cout << to_string(alpha_fills[0].second) << "\n"; + } +} From e97d59444161d6c2f458da952d17a1d0b4fed9f1 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 22 Nov 2023 09:17:20 +0100 Subject: [PATCH 04/66] use doctest instead of raw print Signed-off-by: Martijn Govers --- tests/cpp_unit_tests/test_sparse_ordening.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cpp_unit_tests/test_sparse_ordening.cpp b/tests/cpp_unit_tests/test_sparse_ordening.cpp index 0cf1c9edb..38ec6faad 100644 --- a/tests/cpp_unit_tests/test_sparse_ordening.cpp +++ b/tests/cpp_unit_tests/test_sparse_ordening.cpp @@ -46,7 +46,7 @@ TEST_CASE("Test sparse ordening") { std::cout << "Time taken by function: " << duration.count() << " microseconds" << "\n"; - std::cout << to_string(alpha_fills[0].first) << "\n"; - std::cout << to_string(alpha_fills[0].second) << "\n"; + CHECK(alpha_fills[0].first == std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + CHECK(alpha_fills[0].second == std::vector>{{3, 5}, {4, 5}, {8, 5}, {6, 5}, {7, 5}}); } } From fbfe02d1292ed3d7dd8f3a2b7d0f4a164721a3c5 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 22 Nov 2023 09:28:52 +0100 Subject: [PATCH 05/66] remove deprecated Signed-off-by: Martijn Govers --- .../include/power_grid_model/topology.hpp | 2 +- tests/cpp_unit_tests/test_sparse_ordening.cpp | 22 ++----------------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index eeba049c0..eff687bbc 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -701,7 +701,7 @@ class Topology { {comp_topo_.power_sensor_object_idx, comp_coup_.node}, comp_coup_.power_sensor, [this](Idx i) { return comp_topo_.power_sensor_terminal_type[i] == MeasuredTerminalType::node; }); } -}; // namespace power_grid_model +}; } // namespace power_grid_model diff --git a/tests/cpp_unit_tests/test_sparse_ordening.cpp b/tests/cpp_unit_tests/test_sparse_ordening.cpp index 38ec6faad..4862ab14f 100644 --- a/tests/cpp_unit_tests/test_sparse_ordening.cpp +++ b/tests/cpp_unit_tests/test_sparse_ordening.cpp @@ -11,25 +11,7 @@ #include namespace { -using namespace power_grid_model; - -auto to_string(std::vector> const& d) { - std::stringstream sstr; - sstr << "{"; - for (const auto& it : d) { - sstr << it.first << ": " << it.second << ", "; - } - sstr << "}"; - return sstr.str(); -} - -auto to_string(std::vector const& input) { - std::stringstream sstr; - for (auto const& i : input) { - sstr << i << ", "; - } - return sstr.str(); -} +using power_grid_model::ID; } // namespace TEST_CASE("Test sparse ordening") { @@ -39,7 +21,7 @@ TEST_CASE("Test sparse ordening") { auto const start = std::chrono::high_resolution_clock::now(); std::vector, std::vector>>> const alpha_fills = - minimum_degree_ordering(graph); + power_grid_model::minimum_degree_ordering(graph); auto const stop = std::chrono::high_resolution_clock::now(); auto const duration = duration_cast(stop - start); From 3d5b74b4600cd0129d116865670d54ac82b7cda7 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 22 Nov 2023 09:52:28 +0100 Subject: [PATCH 06/66] remove redundant vector Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordening.hpp | 5 +- .../include/power_grid_model/topology.hpp | 93 +------------------ tests/cpp_unit_tests/test_sparse_ordening.cpp | 6 +- 3 files changed, 7 insertions(+), 97 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index a476a0a57..1cace56ae 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -196,8 +196,7 @@ std::vector remove_vertices_update_degrees(ID& u, std::map, std::vector>>> -minimum_degree_ordering(std::map>& d) { +std::pair, std::vector>> minimum_degree_ordering(std::map>& d) { std::vector>>> data = detail::comp_size_degrees_graph(d); ID& n = data[0].first; std::vector>& dgd = data[0].second; @@ -227,7 +226,7 @@ minimum_degree_ordering(std::map>& d) { } } } - return {{alpha, fills}}; + return {alpha, fills}; } } // namespace power_grid_model diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index eff687bbc..95c4fdbe6 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -310,97 +310,8 @@ class Topology { } // assign temporary bus number as increasing from 0, 1, 2, ..., n_cycle_node - 1 - for (GraphIdx i = 0; i != n_cycle_node; ++i) { - node_status_[cyclic_node[i]] = static_cast(i); - } - // build graph lambda - auto const build_graph = [&](ReorderGraph& g) { - // add edges - for (GraphIdx i = 0; i != n_cycle_node; ++i) { - // loop all edges of vertex i - auto const global_i = static_cast(cyclic_node[i]); - BGL_FORALL_ADJ(global_i, global_j, global_graph_, GlobalGraph) { - // skip if j is not part of cyclic sub graph - if (node_status_[global_j] == -1) { - continue; - } - auto const j = static_cast(node_status_[global_j]); - if (!boost::edge(i, j, g).second) { - boost::add_edge(i, j, g); - } - } - } - }; - ReorderGraph meshed_graph{n_cycle_node}; - build_graph(meshed_graph); - // start minimum degree ordering - std::vector> perm(n_cycle_node); - std::vector> inverse_perm(n_cycle_node); - std::vector> degree(n_cycle_node); - std::vector> supernode_sizes(n_cycle_node, 1); - boost::vec_adj_list_vertex_id_map> const id{}; - int const delta = 0; - boost::minimum_degree_ordering(meshed_graph, boost::make_iterator_property_map(degree.begin(), id), - boost::make_iterator_property_map(inverse_perm.begin(), id), - boost::make_iterator_property_map(perm.begin(), id), - boost::make_iterator_property_map(supernode_sizes.begin(), id), delta, id); - // re-order cyclic node - std::vector const cyclic_node_copy{cyclic_node}; - for (GraphIdx i = 0; i != n_cycle_node; ++i) { - cyclic_node[i] = cyclic_node_copy[perm[i]]; - } - // copy back to dfs node - std::copy(cyclic_node.cbegin(), cyclic_node.cend(), std::back_inserter(dfs_node)); - - // analyze and record fill-ins - // re-assign temporary bus number as increasing from 0, 1, 2, ..., n_cycle_node - 1 - for (GraphIdx i = 0; i != n_cycle_node; ++i) { - node_status_[cyclic_node[i]] = static_cast(i); - } - // re-build graph with reordered cyclic node - meshed_graph.clear(); - meshed_graph = ReorderGraph{n_cycle_node}; - build_graph(meshed_graph); - // begin to remove vertices from graph, create fill-ins - BGL_FORALL_VERTICES(i, meshed_graph, ReorderGraph) { - // double loop to loop all pairs of adjacent vertices - BGL_FORALL_ADJ(i, j1, meshed_graph, ReorderGraph) { - // skip for already removed vertices - if (j1 < i) { - continue; - } - BGL_FORALL_ADJ(i, j2, meshed_graph, ReorderGraph) { - // no self edges - assert(i != j1); - assert(i != j2); - // skip for already removed vertices - if (j2 < i) { - continue; - } - // only keep pair with j1 < j2 - if (j1 >= j2) { - continue; - } - // if edge j1 -> j2 does not already exists - // it is a fill-in - if (!boost::edge(j1, j2, meshed_graph).second) { - // anti edge should also not exist - assert(!boost::edge(j2, j1, meshed_graph).second); - // add both edges to the graph - boost::add_edge(j1, j2, meshed_graph); - boost::add_edge(j2, j1, meshed_graph); - // add to fill-in - fill_in.push_back({static_cast(j1), static_cast(j2)}); - } - } - } - } - // offset fill-in indices by n_node - n_cycle_node - auto const offset = static_cast(dfs_node.size() - n_cycle_node); - std::for_each(fill_in.begin(), fill_in.end(), [offset](BranchIdx& b) { - b[0] += offset; - b[1] += offset; - }); + // TODO(mgovers): fill node_status_ + // TODO(mgovers): construct fill_in return fill_in; } diff --git a/tests/cpp_unit_tests/test_sparse_ordening.cpp b/tests/cpp_unit_tests/test_sparse_ordening.cpp index 4862ab14f..50526e667 100644 --- a/tests/cpp_unit_tests/test_sparse_ordening.cpp +++ b/tests/cpp_unit_tests/test_sparse_ordening.cpp @@ -20,7 +20,7 @@ TEST_CASE("Test sparse ordening") { {4, {6, 8}}, {6, {7, 8, 9}}, {7, {8, 9}}, {8, {9}}}; auto const start = std::chrono::high_resolution_clock::now(); - std::vector, std::vector>>> const alpha_fills = + std::pair, std::vector>> const alpha_fills = power_grid_model::minimum_degree_ordering(graph); auto const stop = std::chrono::high_resolution_clock::now(); @@ -28,7 +28,7 @@ TEST_CASE("Test sparse ordening") { std::cout << "Time taken by function: " << duration.count() << " microseconds" << "\n"; - CHECK(alpha_fills[0].first == std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); - CHECK(alpha_fills[0].second == std::vector>{{3, 5}, {4, 5}, {8, 5}, {6, 5}, {7, 5}}); + CHECK(alpha_fills.first == std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + CHECK(alpha_fills.second == std::vector>{{3, 5}, {4, 5}, {8, 5}, {6, 5}, {7, 5}}); } } From 6bb3c49a4289021a5d5dad7a6cc3dee784dde769 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 22 Nov 2023 10:53:19 +0100 Subject: [PATCH 07/66] call minimum degree ordening from topology Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordening.hpp | 138 ++++++++++-------- .../include/power_grid_model/topology.hpp | 21 ++- tests/cpp_unit_tests/test_sparse_ordening.cpp | 12 +- 3 files changed, 99 insertions(+), 72 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index 1cace56ae..1d11f404e 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MPL-2.0 #pragma once -#ifndef POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ITERATION_HPP -#define POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ITERATION_HPP +#ifndef POWER_GRIdx_MODEL_MATH_SOLVER_SPARSE_ORDENING_HPP +#define POWER_GRIdx_MODEL_MATH_SOLVER_SPARSE_ORDENING_HPP #include "power_grid_model.hpp" @@ -17,8 +17,8 @@ namespace power_grid_model { namespace detail { -void remove_element_vector_pair(ID& u, std::vector>& dgd) { - ID i = 0; +inline void remove_element_vector_pair(Idx& u, std::vector>& dgd) { + Idx i = 0; while (i < dgd.size()) { if (dgd[i].first == u) { dgd.erase(dgd.begin() + i); @@ -29,8 +29,8 @@ void remove_element_vector_pair(ID& u, std::vector>& dgd) { } } -void set_element_vector_pair(ID& u, ID v, std::vector>& dgd) { - ID i = 0; +inline void set_element_vector_pair(Idx& u, Idx v, std::vector>& dgd) { + Idx i = 0; while (i < dgd.size()) { if (dgd[i].first == u) { dgd[i].second = v; @@ -41,15 +41,15 @@ void set_element_vector_pair(ID& u, ID v, std::vector>& dgd) { } } -std::vector adj(ID& u, std::map>& d) { - std::vector l; +inline std::vector adj(Idx& u, std::map>& d) { + std::vector l; for (const auto& it : d) { if (it.first == u) l.insert(l.end(), it.second.begin(), it.second.end()); if (find(it.second.begin(), it.second.end(), u) != it.second.end()) { - std::vector v{it.first}; + std::vector v{it.first}; l.insert(l.end(), v.begin(), v.end()); } } @@ -57,25 +57,26 @@ std::vector adj(ID& u, std::map>& d) { return l; } -bool compair_ids(std::pair& a, std::pair& b) { return a.first < b.first; } +inline bool compair_ids(std::pair& a, std::pair& b) { return a.first < b.first; } -std::vector>>> comp_size_degrees_graph(std::map>& d) { - std::vector> dd; - std::vector v; - ID n = 0; +inline std::vector>>> +comp_size_degrees_graph(std::map>& d) { + std::vector> dd; + std::vector v; + Idx n = 0; for (const auto& it : d) { - ID k = it.first; + Idx k = it.first; if (find(v.begin(), v.end(), k) == v.end()) { - std::vector vk{k}; + std::vector vk{k}; v.insert(v.end(), vk.begin(), vk.end()); n += 1; dd.push_back({k, adj(k, d).size()}); } - for (const ID& el : it.second) { - ID e = el; + for (const Idx& el : it.second) { + Idx e = el; if (find(v.begin(), v.end(), e) == v.end()) { - std::vector ve{e}; + std::vector ve{e}; v.insert(v.end(), ve.begin(), ve.end()); n += 1; dd.push_back({e, adj(e, d).size()}); @@ -88,9 +89,9 @@ std::vector>>> comp_size_degrees_gra return {{n, dd}}; } -std::vector, std::vector>> check_indistguishable(ID& u, - std::map>& d) { - std::vector l, rl, lu, lv, vu{u}, vv; +inline std::vector, std::vector>> +check_indistguishable(Idx& u, std::map>& d) { + std::vector l, rl, lu, lv, vu{u}, vv; l = adj(u, d); lu = l; lu.insert(lu.end(), vu.begin(), vu.end()); @@ -109,14 +110,14 @@ std::vector, std::vector>> check_indistguishable(I return {{l, rl}}; } -std::map> make_clique(std::vector& l) { - std::map> d; - ID b = l.size() - 1; +inline std::map> make_clique(std::vector& l) { + std::map> d; + Idx b = l.size() - 1; for (int i = 0; i < b; i++) { - ID index = i + 1; + Idx index = i + 1; auto start = l.begin() + index; - std::vector sl(l.size() - index); + std::vector sl(l.size() - index); copy(start, l.end(), sl.begin()); d[l[i]] = sl; } @@ -124,21 +125,28 @@ std::map> make_clique(std::vector& l) { return d; } -bool in_graph(std::vector& e, std::map>& d) { - bool t1 = (d.find(e[0]) != d.end()) and (find(d[e[0]].begin(), d[e[0]].end(), e[1]) != d[e[0]].end()); - bool t2 = (d.find(e[1]) != d.end()) and (find(d[e[1]].begin(), d[e[1]].end(), e[0]) != d[e[1]].end()); - - return (t1 || t2); +inline bool in_graph(std::pair const& e, std::map> const& d) { + if (auto edges_it = d.find(e.first); edges_it != d.cend()) { + if (std::ranges::find(edges_it->second, e.second) != edges_it->second.cend()) { + return true; + } + } + if (auto edges_it = d.find(e.second); edges_it != d.cend()) { + if (std::ranges::find(edges_it->second, e.first) != edges_it->second.cend()) { + return true; + } + } + return false; } -std::vector remove_vertices_update_degrees(ID& u, std::map>& d, - std::vector>& dgd, - std::vector>& fills) { - std::vector, std::vector>> nbsrl = check_indistguishable(u, d); - std::vector& nbs = nbsrl[0].first; - std::vector& rl = nbsrl[0].second; - std::vector alpha = rl, vu{u}; - std::map> dd; +inline std::vector remove_vertices_update_degrees(Idx& u, std::map>& d, + std::vector>& dgd, + std::vector>& fills) { + std::vector, std::vector>> nbsrl = check_indistguishable(u, d); + std::vector& nbs = nbsrl[0].first; + std::vector& rl = nbsrl[0].second; + std::vector alpha = rl, vu{u}; + std::map> dd; rl.insert(rl.begin(), vu.begin(), vu.end()); @@ -147,17 +155,17 @@ std::vector remove_vertices_update_degrees(ID& u, std::map el; + std::vector el; for (auto& it : d) { it.second.erase(remove(it.second.begin(), it.second.end(), uu), it.second.end()); if (it.second.empty()) { - ID k = it.first; - std::vector vk{k}; + Idx k = it.first; + std::vector vk{k}; el.insert(el.end(), vk.begin(), vk.end()); } } - std::vector vuu{uu}; + std::vector vuu{uu}; el.insert(el.end(), vuu.begin(), vuu.end()); for (auto& it : el) @@ -167,20 +175,20 @@ std::vector remove_vertices_update_degrees(ID& u, std::map t{k, e}; - if (not in_graph(t, d)) { + Idx k = it.first; + for (const Idx& e : it.second) { + std::pair t{k, e}; + if (!in_graph(t, d)) { if (d.find(k) != d.end()) { - std::vector ve{e}; + std::vector ve{e}; d[k].insert(d[k].end(), ve.begin(), ve.end()); fills.push_back({k, e}); } else if (d.find(e) != d.end()) { - std::vector vk{k}; + std::vector vk{k}; d[e].insert(d[e].end(), vk.begin(), vk.end()); fills.push_back({e, k}); } else { - std::vector ve{e}; + std::vector ve{e}; d[k].insert(d[k].end(), ve.begin(), ve.end()); fills.push_back({k, e}); } @@ -196,30 +204,32 @@ std::vector remove_vertices_update_degrees(ID& u, std::map, std::vector>> minimum_degree_ordering(std::map>& d) { - std::vector>>> data = detail::comp_size_degrees_graph(d); - ID& n = data[0].first; - std::vector>& dgd = data[0].second; - std::vector alpha; - std::vector> fills; +inline std::pair, std::vector>> +minimum_degree_ordering(std::map>& d) { + std::vector>>> data = detail::comp_size_degrees_graph(d); + Idx& n = data[0].first; + std::vector>& dgd = data[0].second; + std::vector alpha; + std::vector> fills; for (int k = 0; k < n; k++) { - ID u = get<0>(*min_element(begin(dgd), end(dgd), [](auto lhs, auto rhs) { return get<1>(lhs) < get<1>(rhs); })); - std::vector vu{u}; + Idx u = + get<0>(*min_element(begin(dgd), end(dgd), [](auto lhs, auto rhs) { return get<1>(lhs) < get<1>(rhs); })); + std::vector vu{u}; alpha.insert(alpha.end(), vu.begin(), vu.end()); if ((d.size() == 1) and d.begin()->second.size() == 1) { - ID a = d.begin()->first; - ID b = d.begin()->second[0]; + Idx a = d.begin()->first; + Idx b = d.begin()->second[0]; if (alpha.back() == a) { - std::vector vb{b}; + std::vector vb{b}; alpha.insert(alpha.end(), vb.begin(), vb.end()); } else { - std::vector va{a}; + std::vector va{a}; alpha.insert(alpha.end(), va.begin(), va.end()); } break; } else { - std::vector va = detail::remove_vertices_update_degrees(u, d, dgd, fills); + std::vector va = detail::remove_vertices_update_degrees(u, d, dgd, fills); alpha.insert(alpha.end(), va.begin(), va.end()); if (d.empty()) { break; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index 95c4fdbe6..d85e52cde 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -11,6 +11,7 @@ #include "exception.hpp" #include "power_grid_model.hpp" #include "sparse_mapping.hpp" +#include "sparse_ordening.hpp" #include #include @@ -310,8 +311,24 @@ class Topology { } // assign temporary bus number as increasing from 0, 1, 2, ..., n_cycle_node - 1 - // TODO(mgovers): fill node_status_ - // TODO(mgovers): construct fill_in + std::map> unique_nearest_neighbours; + for (Idx node_idx : dfs_node) { + unique_nearest_neighbours[node_idx] = {}; + } + for (auto const& edge : back_edges) { + auto const from{static_cast(edge.first)}; + auto const to{static_cast(edge.second)}; + if (!detail::in_graph(std::pair{from, to}, unique_nearest_neighbours)) { + unique_nearest_neighbours[from].push_back(to); + } + } + + auto alpha_fills = minimum_degree_ordering(unique_nearest_neighbours); + + // TODO(mgovers): set node_status_ + // TODO(mgovers): fill dfs_node = dfs_node[alpha_fills.first] + // TODO(mgovers): construct fill_in = alpha_fills.second + return fill_in; } diff --git a/tests/cpp_unit_tests/test_sparse_ordening.cpp b/tests/cpp_unit_tests/test_sparse_ordening.cpp index 50526e667..5b668ce15 100644 --- a/tests/cpp_unit_tests/test_sparse_ordening.cpp +++ b/tests/cpp_unit_tests/test_sparse_ordening.cpp @@ -11,16 +11,16 @@ #include namespace { -using power_grid_model::ID; +using power_grid_model::Idx; } // namespace TEST_CASE("Test sparse ordening") { SUBCASE("minimum_degree_ordening") { - std::map> graph{{0, {3, 5}}, {1, {4, 5, 8}}, {2, {4, 5, 6}}, {3, {6, 7}}, - {4, {6, 8}}, {6, {7, 8, 9}}, {7, {8, 9}}, {8, {9}}}; + std::map> graph{{0, {3, 5}}, {1, {4, 5, 8}}, {2, {4, 5, 6}}, {3, {6, 7}}, + {4, {6, 8}}, {6, {7, 8, 9}}, {7, {8, 9}}, {8, {9}}}; auto const start = std::chrono::high_resolution_clock::now(); - std::pair, std::vector>> const alpha_fills = + std::pair, std::vector>> const alpha_fills = power_grid_model::minimum_degree_ordering(graph); auto const stop = std::chrono::high_resolution_clock::now(); @@ -28,7 +28,7 @@ TEST_CASE("Test sparse ordening") { std::cout << "Time taken by function: " << duration.count() << " microseconds" << "\n"; - CHECK(alpha_fills.first == std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); - CHECK(alpha_fills.second == std::vector>{{3, 5}, {4, 5}, {8, 5}, {6, 5}, {7, 5}}); + CHECK(alpha_fills.first == std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + CHECK(alpha_fills.second == std::vector>{{3, 5}, {4, 5}, {8, 5}, {6, 5}, {7, 5}}); } } From 1a4b122732449e2cf94041fe4ef92908870e18de Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 27 Nov 2023 14:02:08 +0100 Subject: [PATCH 08/66] switch to new min degree algorithm Signed-off-by: Martijn Govers --- .../include/power_grid_model/topology.hpp | 113 ++++++++++++----- tests/cpp_unit_tests/test_topology.cpp | 116 +++++++++++++----- 2 files changed, 162 insertions(+), 67 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index d85e52cde..a193f1e4e 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -19,6 +19,8 @@ #include #include +#include + // build topology of the grid // divide grid into several math models // start search from a source @@ -279,55 +281,100 @@ class Topology { // return list of fill-ins when factorize the matrix std::vector reorder_node(std::vector& dfs_node, std::vector> const& back_edges) { - std::vector fill_in; - // make a copy and clear current vector - std::vector const dfs_node_copy(dfs_node); - dfs_node.clear(); - - // loop all back edges assign all nodes before the back edges as inside cycle - for (auto const& back_edge : back_edges) { - GraphIdx node_in_cycle = back_edge.first; - // loop back from source in the predecessor tree - // stop if it is already marked as in cycle - while (node_status_[node_in_cycle] != -2) { - // assign cycle status and go to predecessor - node_status_[node_in_cycle] = -2; - node_in_cycle = predecessors_[node_in_cycle]; - } - } - - // copy all the far-end non-cyclic node, in reverse order - std::copy_if(dfs_node_copy.crbegin(), dfs_node_copy.crend(), std::back_inserter(dfs_node), - [this](Idx x) { return node_status_[x] == -1; }); - // copy all cyclic node - std::vector cyclic_node; - std::copy_if(dfs_node_copy.cbegin(), dfs_node_copy.cend(), std::back_inserter(cyclic_node), - [this](Idx x) { return node_status_[x] == -2; }); - GraphIdx const n_cycle_node = cyclic_node.size(); - // reorder does not make sense if number of cyclic nodes in a sub graph is smaller than 4 - if (n_cycle_node < 4) { - std::copy(cyclic_node.crbegin(), cyclic_node.crend(), std::back_inserter(dfs_node)); - return fill_in; - } - + // std::vector fill_in; + // // make a copy and clear current vector + // std::vector const dfs_node_copy(dfs_node); + // dfs_node.clear(); + + // // loop all back edges assign all nodes before the back edges as inside cycle + // for (auto const& back_edge : back_edges) { + // GraphIdx node_in_cycle = back_edge.first; + + // // loop back from source in the predecessor tree + // // stop if it is already marked as in cycle + // while (node_status_[node_in_cycle] != -2) { + // // assign cycle status and go to predecessor + // node_status_[node_in_cycle] = -2; + // node_in_cycle = predecessors_[node_in_cycle]; + // } + // } + + // // copy all the far-end non-cyclic node, in reverse order + // std::copy_if(dfs_node_copy.crbegin(), dfs_node_copy.crend(), std::back_inserter(dfs_node), + // [this](Idx x) { return node_status_[x] == -1; }); + // // copy all cyclic node + // std::vector cyclic_node; + // std::copy_if(dfs_node_copy.cbegin(), dfs_node_copy.cend(), std::back_inserter(cyclic_node), + // [this](Idx x) { return node_status_[x] == -2; }); + // GraphIdx const n_cycle_node = cyclic_node.size(); + // // reorder does not make sense if number of cyclic nodes in a sub graph is smaller than 4 + // if (n_cycle_node < 4) { + // std::copy(cyclic_node.crbegin(), cyclic_node.crend(), std::back_inserter(dfs_node)); + // return fill_in; + // } + // for (GraphIdx i = 0; i != n_cycle_node; ++i) { + // node_status_[cyclic_node[i]] = static_cast(i); + // } + + // // build graph lambda + // auto const build_graph = [&](ReorderGraph& g) { + // // add edges + // for (GraphIdx i = 0; i != n_cycle_node; ++i) { + // // loop all edges of vertex i + // auto const global_i = static_cast(cyclic_node[i]); + // BGL_FORALL_ADJ(global_i, global_j, global_graph_, GlobalGraph) { + // // skip if j is not part of cyclic sub graph + // if (node_status_[global_j] == -1) { + // continue; + // } + // auto const j = static_cast(node_status_[global_j]); + // if (!boost::edge(i, j, g).second) { + // boost::add_edge(i, j, g); + // } + // } + // } + // }; // assign temporary bus number as increasing from 0, 1, 2, ..., n_cycle_node - 1 std::map> unique_nearest_neighbours; for (Idx node_idx : dfs_node) { - unique_nearest_neighbours[node_idx] = {}; + auto predecessor = static_cast(predecessors_[node_idx]); + std::cout << node_idx << ": predecessor = " << predecessor << "\n"; + if (predecessor != node_idx) { + unique_nearest_neighbours[node_idx] = {predecessor}; + } } + std::cout << std::endl; for (auto const& edge : back_edges) { auto const from{static_cast(edge.first)}; auto const to{static_cast(edge.second)}; + std::cout << "back edge: " << from << ", " << to; if (!detail::in_graph(std::pair{from, to}, unique_nearest_neighbours)) { + std::cout << " (new)"; unique_nearest_neighbours[from].push_back(to); } + std::cout << "\n"; + } + std::cout << std::endl; + + for (auto const& [node, neighbours] : unique_nearest_neighbours) { + std::cout << "node: " << node << ", adjacent = ["; + for (auto neighbour : neighbours) { + std::cout << neighbour << ", "; + } + std::cout << "]\n"; } + std::cout << std::endl; - auto alpha_fills = minimum_degree_ordering(unique_nearest_neighbours); + auto [reordered, fills] = minimum_degree_ordering(unique_nearest_neighbours); // TODO(mgovers): set node_status_ // TODO(mgovers): fill dfs_node = dfs_node[alpha_fills.first] // TODO(mgovers): construct fill_in = alpha_fills.second + std::vector fill_in; + for (auto [from, to] : fills) { + fill_in.push_back({reordered[from], reordered[to]}); + } + dfs_node = std::move(reordered); return fill_in; } diff --git a/tests/cpp_unit_tests/test_topology.cpp b/tests/cpp_unit_tests/test_topology.cpp index 2085c2222..d466f4349 100644 --- a/tests/cpp_unit_tests/test_topology.cpp +++ b/tests/cpp_unit_tests/test_topology.cpp @@ -324,41 +324,89 @@ TEST_CASE("Test topology") { } TEST_CASE("Test cycle reorder") { - // component topology - ComponentTopology comp_topo{}; - comp_topo.n_node = 7; - comp_topo.branch_node_idx = { - {0, 1}, // 0 - {1, 2}, // 1 - {2, 3}, // 2 - {3, 4}, // 3 - {4, 5}, // 4 - {0, 5}, // 5 - {1, 4}, // 6 - {6, 0}, // 7 - {6, 2}, // 8 - {5, 1}, // 9 - {3, 1}, // 10 - {6, 1}, // 11 - {2, 1}, // 12 - }; - comp_topo.source_node_idx = {0}; - // component connection - ComponentConnections comp_conn{}; - comp_conn.branch_connected = std::vector(13, {1, 1}); - comp_conn.branch_phase_shift = std::vector(13, 0.0); - comp_conn.source_connected = {1}; - // result - TopologicalComponentToMathCoupling comp_coup_ref{}; - comp_coup_ref.node = {{0, 3}, {0, 5}, {0, 4}, {0, 2}, {0, 6}, {0, 1}, {0, 0}}; - std::vector const fill_in_ref{{3, 4}, {3, 6}, {4, 6}}; + SUBCASE("9 nodes") { + // { + // 0: [3, 5], + // 1: [4, 5, 8], + // 2: [4, 5, 6], + // 3: [6, 7], + // 4: [6, 8], + // 6: [7, 8, 9], + // 7: [8, 9], + // 8: [9] + // } - Topology topo{comp_topo, comp_conn}; - auto pair = topo.build_topology(); - auto const& topo_comp_coup = *pair.second; - auto const& math_topo = *pair.first[0]; - CHECK(topo_comp_coup.node == comp_coup_ref.node); - CHECK(math_topo.fill_in == fill_in_ref); + // component topology + ComponentTopology comp_topo{}; + comp_topo.n_node = 10; + comp_topo.branch_node_idx = { + {0, 3}, {0, 5}, {1, 4}, {1, 5}, {1, 8}, {2, 4}, {2, 5}, {2, 6}, {3, 6}, + {3, 7}, {4, 6}, {4, 8}, {6, 7}, {6, 8}, {6, 9}, {7, 8}, {7, 9}, {8, 9}, + }; + comp_topo.source_node_idx = {0}; + // component connection + ComponentConnections comp_conn{}; + comp_conn.branch_connected = std::vector(18, {1, 1}); + comp_conn.branch_phase_shift = std::vector(18, 0.0); + comp_conn.source_connected = {1}; + // result + TopologicalComponentToMathCoupling comp_coup_ref{}; + comp_coup_ref.node = {{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}, {0, 9}}; + std::vector const fill_in_ref{{5, 3}, {4, 5}, {5, 8}, {6, 5}, {5, 7}}; + + Topology topo{comp_topo, comp_conn}; + auto pair = topo.build_topology(); + auto const& topo_comp_coup = *pair.second; + auto const& math_topo = *pair.first[0]; + CHECK(topo_comp_coup.node == comp_coup_ref.node); + CHECK(math_topo.fill_in == fill_in_ref); + } + + SUBCASE("7 nodes") { + // { + // 0: [1, 5, 6], + // 1: [2, 4, 5, 3, 6], + // 2: [3, 6] + // 3: [4], + // 4: [5], + // } + + // component topology + ComponentTopology comp_topo{}; + comp_topo.n_node = 7; + comp_topo.branch_node_idx = { + {0, 1}, // 0 + {1, 2}, // 1 + {2, 3}, // 2 + {3, 4}, // 3 + {4, 5}, // 4 + {0, 5}, // 5 + {1, 4}, // 6 + {6, 0}, // 7 + {6, 2}, // 8 + {5, 1}, // 9 + {3, 1}, // 10 + {6, 1}, // 11 + {2, 1}, // 12 + }; + comp_topo.source_node_idx = {0}; + // component connection + ComponentConnections comp_conn{}; + comp_conn.branch_connected = std::vector(13, {1, 1}); + comp_conn.branch_phase_shift = std::vector(13, 0.0); + comp_conn.source_connected = {1}; + // result + TopologicalComponentToMathCoupling comp_coup_ref{}; + comp_coup_ref.node = {{0, 0}, {0, 3}, {0, 1}, {0, 2}, {0, 4}, {0, 5}, {0, 6}}; + std::vector const fill_in_ref{{5, 6}, {1, 6}, {6, 4}}; + + Topology topo{comp_topo, comp_conn}; + auto pair = topo.build_topology(); + auto const& topo_comp_coup = *pair.second; + auto const& math_topo = *pair.first[0]; + CHECK(topo_comp_coup.node == comp_coup_ref.node); + CHECK(math_topo.fill_in == fill_in_ref); + } } } // namespace power_grid_model \ No newline at end of file From ef9ae2942910abbfec69c667b71c10ef0a1735c2 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Fri, 1 Dec 2023 15:40:36 +0100 Subject: [PATCH 09/66] attempt to fix permutations Signed-off-by: Martijn Govers --- .../power_grid_model/math_solver/y_bus.hpp | 9 ++ .../include/power_grid_model/topology.hpp | 94 +++++++++++-------- tests/cpp_unit_tests/test_topology.cpp | 4 +- .../cpp_validation_tests/test_validation.cpp | 15 +-- 4 files changed, 77 insertions(+), 45 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/y_bus.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/y_bus.hpp index 9ca9b702b..7f7191db0 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/y_bus.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/y_bus.hpp @@ -11,6 +11,8 @@ #include "../sparse_mapping.hpp" #include "../three_phase_tensor.hpp" +#include // TODO(mgovers) remove + namespace power_grid_model { // hide implementation in inside namespace @@ -152,6 +154,13 @@ struct YBusStructure { y_bus_element.push_back(m.element); } } + for (size_t idx = 0; idx < vec_map_element.size(); ++idx) { + auto const& m = vec_map_element[idx]; + std::cout << "idx = " << idx << ", pos = [" << m.pos.first << ", " << m.pos.second + << "], element = {element_type = " << static_cast(m.element.element_type) + << ", idx = " << m.element.idx << "}\n"; + } + std::cout << std::endl; // iterate the whole element include fill-in for (auto it_element = vec_map_element.cbegin(); it_element != vec_map_element.cend(); diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index a193f1e4e..cd68aec48 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -281,37 +281,37 @@ class Topology { // return list of fill-ins when factorize the matrix std::vector reorder_node(std::vector& dfs_node, std::vector> const& back_edges) { - // std::vector fill_in; - // // make a copy and clear current vector - // std::vector const dfs_node_copy(dfs_node); - // dfs_node.clear(); - - // // loop all back edges assign all nodes before the back edges as inside cycle - // for (auto const& back_edge : back_edges) { - // GraphIdx node_in_cycle = back_edge.first; - - // // loop back from source in the predecessor tree - // // stop if it is already marked as in cycle - // while (node_status_[node_in_cycle] != -2) { - // // assign cycle status and go to predecessor - // node_status_[node_in_cycle] = -2; - // node_in_cycle = predecessors_[node_in_cycle]; - // } - // } + std::vector fill_in; + // make a copy and clear current vector + std::vector const dfs_node_copy(dfs_node); + dfs_node.clear(); + + // loop all back edges assign all nodes before the back edges as inside cycle + for (auto const& back_edge : back_edges) { + GraphIdx node_in_cycle = back_edge.first; + + // loop back from source in the predecessor tree + // stop if it is already marked as in cycle + while (node_status_[node_in_cycle] != -2) { + // assign cycle status and go to predecessor + node_status_[node_in_cycle] = -2; + node_in_cycle = predecessors_[node_in_cycle]; + } + } - // // copy all the far-end non-cyclic node, in reverse order - // std::copy_if(dfs_node_copy.crbegin(), dfs_node_copy.crend(), std::back_inserter(dfs_node), - // [this](Idx x) { return node_status_[x] == -1; }); - // // copy all cyclic node - // std::vector cyclic_node; - // std::copy_if(dfs_node_copy.cbegin(), dfs_node_copy.cend(), std::back_inserter(cyclic_node), - // [this](Idx x) { return node_status_[x] == -2; }); - // GraphIdx const n_cycle_node = cyclic_node.size(); - // // reorder does not make sense if number of cyclic nodes in a sub graph is smaller than 4 - // if (n_cycle_node < 4) { - // std::copy(cyclic_node.crbegin(), cyclic_node.crend(), std::back_inserter(dfs_node)); - // return fill_in; - // } + // copy all the far-end non-cyclic node, in reverse order + std::copy_if(dfs_node_copy.crbegin(), dfs_node_copy.crend(), std::back_inserter(dfs_node), + [this](Idx x) { return node_status_[x] == -1; }); + // copy all cyclic node + std::vector cyclic_node; + std::copy_if(dfs_node_copy.cbegin(), dfs_node_copy.cend(), std::back_inserter(cyclic_node), + [this](Idx x) { return node_status_[x] == -2; }); + GraphIdx const n_cycle_node = cyclic_node.size(); + // reorder does not make sense if number of cyclic nodes in a sub graph is smaller than 4 + if (n_cycle_node < 4) { + std::copy(cyclic_node.crbegin(), cyclic_node.crend(), std::back_inserter(dfs_node)); + return fill_in; + } // for (GraphIdx i = 0; i != n_cycle_node; ++i) { // node_status_[cyclic_node[i]] = static_cast(i); // } @@ -336,7 +336,7 @@ class Topology { // }; // assign temporary bus number as increasing from 0, 1, 2, ..., n_cycle_node - 1 std::map> unique_nearest_neighbours; - for (Idx node_idx : dfs_node) { + for (Idx node_idx : cyclic_node) { auto predecessor = static_cast(predecessors_[node_idx]); std::cout << node_idx << ": predecessor = " << predecessor << "\n"; if (predecessor != node_idx) { @@ -367,14 +367,33 @@ class Topology { auto [reordered, fills] = minimum_degree_ordering(unique_nearest_neighbours); - // TODO(mgovers): set node_status_ - // TODO(mgovers): fill dfs_node = dfs_node[alpha_fills.first] - // TODO(mgovers): construct fill_in = alpha_fills.second - std::vector fill_in; + std::ranges::transform(reordered, std::back_inserter(dfs_node), + [&cyclic_node](Idx idx) { return cyclic_node[idx]; }); + + // TODO(mgovers): make this more efficient + auto const permuted_node_idx = [&dfs_node](Idx node_idx) { + return static_cast(std::distance(dfs_node.begin(), std::ranges::find(dfs_node, node_idx))); + }; + + for (auto [from, to] : fills) { + auto from_reordered = permuted_node_idx(reordered[from]); + auto to_reordered = permuted_node_idx(reordered[to]); + fill_in.push_back({from_reordered, to_reordered}); + } + + std::cout << "reordered: ["; + for (auto n : reordered) { + std::cout << n << ", "; + } + std::cout << "]\nfill_in (before reordening) : ["; for (auto [from, to] : fills) { - fill_in.push_back({reordered[from], reordered[to]}); + std::cout << "(" << from << ", " << to << "), "; + } + std::cout << "]\nfill_in (reordered) : ["; + for (auto [from, to] : fill_in) { + std::cout << "(" << from << ", " << to << "), "; } - dfs_node = std::move(reordered); + std::cout << "\n" << std::endl; return fill_in; } @@ -395,6 +414,7 @@ class Topology { Idx2D const i_math = comp_coup_.node[i]; Idx2D const j_math = comp_coup_.node[j]; Idx const math_group = [&]() { + // TODO(mgovers): rewrite Idx group = -1; if (i_status != 0 && i_math.group != -1) { group = i_math.group; diff --git a/tests/cpp_unit_tests/test_topology.cpp b/tests/cpp_unit_tests/test_topology.cpp index d466f4349..bd5f2e4ce 100644 --- a/tests/cpp_unit_tests/test_topology.cpp +++ b/tests/cpp_unit_tests/test_topology.cpp @@ -352,7 +352,7 @@ TEST_CASE("Test cycle reorder") { // result TopologicalComponentToMathCoupling comp_coup_ref{}; comp_coup_ref.node = {{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}, {0, 9}}; - std::vector const fill_in_ref{{5, 3}, {4, 5}, {5, 8}, {6, 5}, {5, 7}}; + std::vector const fill_in_ref{{3, 5}, {4, 5}, {5, 8}, {5, 6}, {5, 7}}; Topology topo{comp_topo, comp_conn}; auto pair = topo.build_topology(); @@ -398,7 +398,7 @@ TEST_CASE("Test cycle reorder") { // result TopologicalComponentToMathCoupling comp_coup_ref{}; comp_coup_ref.node = {{0, 0}, {0, 3}, {0, 1}, {0, 2}, {0, 4}, {0, 5}, {0, 6}}; - std::vector const fill_in_ref{{5, 6}, {1, 6}, {6, 4}}; + std::vector const fill_in_ref{{5, 6}, {3, 6}, {4, 6}}; Topology topo{comp_topo, comp_conn}; auto pair = topo.build_topology(); diff --git a/tests/cpp_validation_tests/test_validation.cpp b/tests/cpp_validation_tests/test_validation.cpp index 6b61a33c7..ee8e5a8c6 100644 --- a/tests/cpp_validation_tests/test_validation.cpp +++ b/tests/cpp_validation_tests/test_validation.cpp @@ -592,12 +592,15 @@ TEST_CASE("Validation test single") { TEST_CASE("Validation test batch") { std::vector const& all_cases = get_all_batch_cases(); for (CaseParam const& param : all_cases) { - SUBCASE(param.case_name.c_str()) { - try { - validate_batch_case(param); - } catch (std::exception& e) { - auto const msg = std::string("Unexpected exception with message: ") + e.what(); - FAIL_CHECK(msg); + if (param.case_name == + "power_flow/pandapower/networks/asymmetric/distribution-case-asym-newton_raphson_batch") { + SUBCASE(param.case_name.c_str()) { + try { + validate_batch_case(param); + } catch (std::exception& e) { + auto const msg = std::string("Unexpected exception with message: ") + e.what(); + FAIL_CHECK(msg); + } } } } From 0d8fe104d0de1cf746311ead0e241ccf3bff4630 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 13 Dec 2023 08:26:22 +0100 Subject: [PATCH 10/66] more debug Signed-off-by: Martijn Govers --- .../include/power_grid_model/topology.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index cd68aec48..bb6a32381 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -381,10 +381,14 @@ class Topology { fill_in.push_back({from_reordered, to_reordered}); } - std::cout << "reordered: ["; + std::cout << "reordered (before permutation): ["; for (auto n : reordered) { std::cout << n << ", "; } + std::cout << "]\nreordered (after permutation): ["; + for (auto n : dfs_node) { + std::cout << n << ", "; + } std::cout << "]\nfill_in (before reordening) : ["; for (auto [from, to] : fills) { std::cout << "(" << from << ", " << to << "), "; @@ -393,7 +397,7 @@ class Topology { for (auto [from, to] : fill_in) { std::cout << "(" << from << ", " << to << "), "; } - std::cout << "\n" << std::endl; + std::cout << "]\n" << std::endl; return fill_in; } From d2c7514327d3341eb074f513dfb3257aebac81ad Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Fri, 15 Dec 2023 08:32:44 +0100 Subject: [PATCH 11/66] fix last remaining issue Signed-off-by: Martijn Govers --- .../include/power_grid_model/topology.hpp | 4 +- tests/cpp_unit_tests/test_topology.cpp | 70 +++++++++---------- 2 files changed, 34 insertions(+), 40 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index bb6a32381..9a0073fea 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -366,9 +366,7 @@ class Topology { std::cout << std::endl; auto [reordered, fills] = minimum_degree_ordering(unique_nearest_neighbours); - - std::ranges::transform(reordered, std::back_inserter(dfs_node), - [&cyclic_node](Idx idx) { return cyclic_node[idx]; }); + std::ranges::copy(reordered, std::back_inserter(dfs_node)); // TODO(mgovers): make this more efficient auto const permuted_node_idx = [&dfs_node](Idx node_idx) { diff --git a/tests/cpp_unit_tests/test_topology.cpp b/tests/cpp_unit_tests/test_topology.cpp index bd5f2e4ce..ab9959ce4 100644 --- a/tests/cpp_unit_tests/test_topology.cpp +++ b/tests/cpp_unit_tests/test_topology.cpp @@ -6,8 +6,6 @@ #include -#include - /* * [0] = Node / Bus * --0--> = Branch (from --id--> to) @@ -178,10 +176,10 @@ TEST_CASE("Test topology") { // result TopologicalComponentToMathCoupling comp_coup_ref{}; comp_coup_ref.node = { // 0 1 2 3 - {0, 4}, // Topological node 0 has become node 4 in mathematical model (group) 0 + {0, 1}, // Topological node 0 has become node 4 in mathematical model (group) 0 {0, 2}, {0, 0}, - {0, 1}, + {0, 3}, // 4 5 6 {1, 2}, // Topological node 4 has become node 2 in mathematical model (group) 1 {1, 3}, @@ -194,7 +192,7 @@ TEST_CASE("Test topology") { {-1, -1}, {-1, -1}, // b0, b1, b2 - {0, 3}, // Branch3 b0 is replaced by a virtual node 3, in mathematical model 0 + {0, 4}, // Branch3 b0 is replaced by a virtual node 3, in mathematical model 0 {-1, -1}, {1, 1}}; comp_coup_ref.source = { @@ -218,9 +216,9 @@ TEST_CASE("Test topology") { {-1, {-1, -1, -1}}, // b1 {1, {2, 3, 4}}, // b2 }; - comp_coup_ref.load_gen = {{0, 1}, {-1, -1}, {1, 0}, {0, 0}}; + comp_coup_ref.load_gen = {{0, 0}, {-1, -1}, {1, 0}, {0, 1}}; comp_coup_ref.shunt = {{0, 0}, {1, 0}, {-1, -1}}; - comp_coup_ref.voltage_sensor = {{0, 0}, {0, 3}, {0, 1}, {0, 2}, {1, 0}, {-1, -1}}; + comp_coup_ref.voltage_sensor = {{0, 0}, {0, 2}, {0, 1}, {0, 3}, {1, 0}, {-1, -1}}; comp_coup_ref.power_sensor = { {0, 0}, // 0 branch_from {1, 0}, // 1 source @@ -244,43 +242,41 @@ TEST_CASE("Test topology") { // Sub graph / math model 0 MathModelTopology math0; - math0.slack_bus_ = 4; - math0.sources_per_bus = {from_sparse, {0, 0, 0, 0, 0, 1}}; - math0.branch_bus_idx = {{4, 2}, {4, 1}, {1, -1}, {-1, 0}, {2, 3}, {1, 3}, {0, 3}}; - math0.phase_shift = {0.0, -1.0, 0.0, 0.0, 0.0}; - math0.load_gens_per_bus = {from_sparse, {0, 0, 0, 1, 1, 2}}; - math0.load_gen_type = {LoadGenType::const_y, LoadGenType::const_pq}; - math0.shunts_per_bus = {from_sparse, {0, 0, 1, 1, 1, 1}}; - math0.voltage_sensors_per_bus = {from_sparse, {0, 2, 3, 4, 4, 4}}; - math0.power_sensors_per_bus = {from_sparse, {0, 0, 0, 0, 0, 0}}; - math0.power_sensors_per_source = {from_sparse, {0, 0}}; - math0.power_sensors_per_shunt = {from_sparse, {0, 0}}; - math0.power_sensors_per_load_gen = {from_sparse, {0, 1, 1}}; - math0.power_sensors_per_branch_from = {from_sparse, {0, 0, 2, 2, 2, 3, 4, 5}}; + math0.slack_bus_ = 1; + math0.sources_per_bus = {from_dense, {1}, 5}; + math0.branch_bus_idx = {{1, 2}, {1, 3}, {3, -1}, {-1, 0}, {2, 4}, {3, 4}, {0, 4}}; + math0.phase_shift = {0.0, 0.0, 0.0, -1.0, 0.0}; + math0.load_gens_per_bus = {from_dense, {1, 2}, 5}; + math0.load_gen_type = {LoadGenType::const_pq, LoadGenType::const_y}; + math0.shunts_per_bus = {from_dense, {3}, 5}; + math0.voltage_sensors_per_bus = {from_dense, {0, 0, 2, 3}, 5}; + math0.power_sensors_per_bus = {from_dense, {}, 5}; + math0.power_sensors_per_source = {from_dense, {}, 1}; + math0.power_sensors_per_shunt = {from_dense, {}, 1}; + math0.power_sensors_per_load_gen = {from_dense, {1}, 2}; + math0.power_sensors_per_branch_from = {from_dense, {1, 1, 4, 5, 6}, 7}; // 7 branches, 3 branch-to power sensors // sensor 0 is connected to branch 0 // sensor 1 and 2 are connected to branch 1 - math0.power_sensors_per_branch_to = {from_sparse, {0, 1, 3, 3, 3, 3, 3, 3}}; - math0.fill_in = {{3, 4}}; + math0.power_sensors_per_branch_to = {from_dense, {0, 1, 1}, 7}; + math0.fill_in = {{4, 2}}; // Sub graph / math model 1 MathModelTopology math1; math1.slack_bus_ = 3; - math1.sources_per_bus = {from_sparse, {0, 0, 0, 0, 1}}; - math1.branch_bus_idx = { - {3, 2}, {2, 3}, {-1, 1}, {0, 1}, {3, 1}, - }; + math1.sources_per_bus = {from_dense, {3}, 4}; + math1.branch_bus_idx = {{3, 2}, {2, 3}, {-1, 1}, {0, 1}, {3, 1}}; math1.phase_shift = {0, 0, 0, 0}; - math1.load_gens_per_bus = {from_sparse, {0, 0, 0, 0, 1}}; + math1.load_gens_per_bus = {from_dense, {3}, 4}; math1.load_gen_type = {LoadGenType::const_i}; - math1.shunts_per_bus = {from_sparse, {0, 1, 1, 1, 1}}; - math1.voltage_sensors_per_bus = {from_sparse, {0, 0, 0, 0, 1}}; - math1.power_sensors_per_bus = {from_sparse, {0, 0, 0, 0, 1}}; - math1.power_sensors_per_source = {from_sparse, {0, 2}}; - math1.power_sensors_per_shunt = {from_sparse, {0, 2}}; - math1.power_sensors_per_load_gen = {from_sparse, {0, 2}}; - math1.power_sensors_per_branch_from = {from_sparse, {0, 0, 0, 0, 0, 0}}; - math1.power_sensors_per_branch_to = {from_sparse, {0, 0, 0, 0, 0, 0}}; + math1.shunts_per_bus = {from_dense, {0}, 4}; + math1.voltage_sensors_per_bus = {from_dense, {3}, 4}; + math1.power_sensors_per_bus = {from_dense, {3}, 4}; + math1.power_sensors_per_source = {from_dense, {0, 0}, 1}; + math1.power_sensors_per_shunt = {from_dense, {0, 0}, 1}; + math1.power_sensors_per_load_gen = {from_dense, {0, 0}, 1}; + math1.power_sensors_per_branch_from = {from_dense, {}, 5}; + math1.power_sensors_per_branch_to = {from_dense, {}, 5}; std::vector math_topology_ref = {math0, math1}; @@ -352,7 +348,7 @@ TEST_CASE("Test cycle reorder") { // result TopologicalComponentToMathCoupling comp_coup_ref{}; comp_coup_ref.node = {{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}, {0, 9}}; - std::vector const fill_in_ref{{3, 5}, {4, 5}, {5, 8}, {5, 6}, {5, 7}}; + std::vector const fill_in_ref{{5, 3}, {4, 5}, {5, 8}, {6, 5}, {5, 7}}; Topology topo{comp_topo, comp_conn}; auto pair = topo.build_topology(); @@ -398,7 +394,7 @@ TEST_CASE("Test cycle reorder") { // result TopologicalComponentToMathCoupling comp_coup_ref{}; comp_coup_ref.node = {{0, 0}, {0, 3}, {0, 1}, {0, 2}, {0, 4}, {0, 5}, {0, 6}}; - std::vector const fill_in_ref{{5, 6}, {3, 6}, {4, 6}}; + std::vector const fill_in_ref{{5, 6}, {3, 6}, {6, 4}}; Topology topo{comp_topo, comp_conn}; auto pair = topo.build_topology(); From 15846b5d7a96f98b3496f67a8469b7d0ede34e50 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Fri, 15 Dec 2023 08:34:58 +0100 Subject: [PATCH 12/66] remove logging Signed-off-by: Martijn Govers --- .../include/power_grid_model/topology.hpp | 59 +------------------ 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index 9a0073fea..cc7fc5bf2 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -19,8 +19,6 @@ #include #include -#include - // build topology of the grid // divide grid into several math models // start search from a source @@ -312,58 +310,21 @@ class Topology { std::copy(cyclic_node.crbegin(), cyclic_node.crend(), std::back_inserter(dfs_node)); return fill_in; } - // for (GraphIdx i = 0; i != n_cycle_node; ++i) { - // node_status_[cyclic_node[i]] = static_cast(i); - // } - - // // build graph lambda - // auto const build_graph = [&](ReorderGraph& g) { - // // add edges - // for (GraphIdx i = 0; i != n_cycle_node; ++i) { - // // loop all edges of vertex i - // auto const global_i = static_cast(cyclic_node[i]); - // BGL_FORALL_ADJ(global_i, global_j, global_graph_, GlobalGraph) { - // // skip if j is not part of cyclic sub graph - // if (node_status_[global_j] == -1) { - // continue; - // } - // auto const j = static_cast(node_status_[global_j]); - // if (!boost::edge(i, j, g).second) { - // boost::add_edge(i, j, g); - // } - // } - // } - // }; - // assign temporary bus number as increasing from 0, 1, 2, ..., n_cycle_node - 1 + std::map> unique_nearest_neighbours; for (Idx node_idx : cyclic_node) { auto predecessor = static_cast(predecessors_[node_idx]); - std::cout << node_idx << ": predecessor = " << predecessor << "\n"; if (predecessor != node_idx) { unique_nearest_neighbours[node_idx] = {predecessor}; } } - std::cout << std::endl; for (auto const& edge : back_edges) { auto const from{static_cast(edge.first)}; auto const to{static_cast(edge.second)}; - std::cout << "back edge: " << from << ", " << to; if (!detail::in_graph(std::pair{from, to}, unique_nearest_neighbours)) { - std::cout << " (new)"; unique_nearest_neighbours[from].push_back(to); } - std::cout << "\n"; - } - std::cout << std::endl; - - for (auto const& [node, neighbours] : unique_nearest_neighbours) { - std::cout << "node: " << node << ", adjacent = ["; - for (auto neighbour : neighbours) { - std::cout << neighbour << ", "; - } - std::cout << "]\n"; } - std::cout << std::endl; auto [reordered, fills] = minimum_degree_ordering(unique_nearest_neighbours); std::ranges::copy(reordered, std::back_inserter(dfs_node)); @@ -379,24 +340,6 @@ class Topology { fill_in.push_back({from_reordered, to_reordered}); } - std::cout << "reordered (before permutation): ["; - for (auto n : reordered) { - std::cout << n << ", "; - } - std::cout << "]\nreordered (after permutation): ["; - for (auto n : dfs_node) { - std::cout << n << ", "; - } - std::cout << "]\nfill_in (before reordening) : ["; - for (auto [from, to] : fills) { - std::cout << "(" << from << ", " << to << "), "; - } - std::cout << "]\nfill_in (reordered) : ["; - for (auto [from, to] : fill_in) { - std::cout << "(" << from << ", " << to << "), "; - } - std::cout << "]\n" << std::endl; - return fill_in; } From ed9f48327dc0c00cabeda7aad19d6ad453ca3821 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 2 Jan 2024 14:19:32 +0100 Subject: [PATCH 13/66] remove bad import Signed-off-by: Martijn Govers --- .../include/power_grid_model/math_solver/y_bus.hpp | 2 -- .../include/power_grid_model/sparse_ordening.hpp | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/y_bus.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/y_bus.hpp index 2cb2b2ada..b81eedbf6 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/y_bus.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/y_bus.hpp @@ -10,8 +10,6 @@ #include "../power_grid_model.hpp" #include "../three_phase_tensor.hpp" -#include // TODO(mgovers) remove - namespace power_grid_model { // hide implementation in inside namespace diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index 1d11f404e..4d9550c4c 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MPL-2.0 #pragma once -#ifndef POWER_GRIdx_MODEL_MATH_SOLVER_SPARSE_ORDENING_HPP -#define POWER_GRIdx_MODEL_MATH_SOLVER_SPARSE_ORDENING_HPP +#ifndef POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ORDENING_HPP +#define POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ORDENING_HPP #include "power_grid_model.hpp" From 632798ea58f6314504784b6c1f0cbb6a5bf77a4d Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 2 Jan 2024 15:59:59 +0100 Subject: [PATCH 14/66] major cleanup minimum degree ordening Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordening.hpp | 140 ++++++++---------- 1 file changed, 58 insertions(+), 82 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index 4d9550c4c..1730d9fdc 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -17,27 +17,13 @@ namespace power_grid_model { namespace detail { -inline void remove_element_vector_pair(Idx& u, std::vector>& dgd) { - Idx i = 0; - while (i < dgd.size()) { - if (dgd[i].first == u) { - dgd.erase(dgd.begin() + i); - break; - } else { - i++; - } - } +inline void remove_element_vector_pair(Idx u, std::vector>& dgd) { + std::erase_if(dgd, [u](auto const& v) { return v.first == u; }); } -inline void set_element_vector_pair(Idx& u, Idx v, std::vector>& dgd) { - Idx i = 0; - while (i < dgd.size()) { - if (dgd[i].first == u) { - dgd[i].second = v; - break; - } else { - i++; - } +inline void set_element_vector_pair(Idx u, Idx v, std::vector>& dgd) { + if (auto it = std::ranges::find_if(dgd, [u](auto const& value) { return value.first == u; }); it != dgd.end()) { + it->second = v; } } @@ -45,20 +31,18 @@ inline std::vector adj(Idx& u, std::map>& d) { std::vector l; for (const auto& it : d) { - if (it.first == u) - l.insert(l.end(), it.second.begin(), it.second.end()); + if (it.first == u) { + l.insert(l.end(), it.second.cbegin(), it.second.cend()); + } - if (find(it.second.begin(), it.second.end(), u) != it.second.end()) { - std::vector v{it.first}; - l.insert(l.end(), v.begin(), v.end()); + if (std::ranges::find(it.second, u) != it.second.cend()) { + l.push_back(it.first); } } return l; } -inline bool compair_ids(std::pair& a, std::pair& b) { return a.first < b.first; } - inline std::vector>>> comp_size_degrees_graph(std::map>& d) { std::vector> dd; @@ -67,64 +51,60 @@ comp_size_degrees_graph(std::map>& d) { for (const auto& it : d) { Idx k = it.first; - if (find(v.begin(), v.end(), k) == v.end()) { - std::vector vk{k}; - v.insert(v.end(), vk.begin(), vk.end()); - n += 1; - dd.push_back({k, adj(k, d).size()}); + if (std::ranges::find(v, k) == v.end()) { + ++n; + v.push_back(k); + dd.emplace_back(k, adj(k, d).size()); } for (const Idx& el : it.second) { Idx e = el; if (find(v.begin(), v.end(), e) == v.end()) { - std::vector ve{e}; - v.insert(v.end(), ve.begin(), ve.end()); - n += 1; - dd.push_back({e, adj(e, d).size()}); + ++n; + v.push_back(e); + dd.emplace_back(e, adj(e, d).size()); } } } - sort(dd.begin(), dd.end()); + std::ranges::sort(dd); return {{n, dd}}; } +inline std::map> make_clique(std::vector& l) { + std::map> d; + + for (Idx i = 0; i < static_cast(l.size()) - 1; i++) { + Idx const idx = i + 1; + std::vector sl(l.size() - idx); + std::copy(l.begin() + idx, l.end(), sl.begin()); + d[l[i]] = sl; + } + + return d; +} + inline std::vector, std::vector>> check_indistguishable(Idx& u, std::map>& d) { - std::vector l, rl, lu, lv, vu{u}, vv; - l = adj(u, d); - lu = l; - lu.insert(lu.end(), vu.begin(), vu.end()); + std::vector rl; + + auto l = adj(u, d); + auto lu = l; + lu.push_back(u); for (auto& v : l) { - lv = adj(v, d); - vv = {v}; - lv.insert(lv.end(), vv.begin(), vv.end()); - sort(lu.begin(), lu.end()); - sort(lv.begin(), lv.end()); + auto lv = adj(v, d); + lv.push_back(v); + std::ranges::sort(lu); + std::ranges::sort(lv); if (lu == lv) { - rl.insert(rl.end(), vv.begin(), vv.end()); + rl.push_back(v); } } return {{l, rl}}; } -inline std::map> make_clique(std::vector& l) { - std::map> d; - Idx b = l.size() - 1; - - for (int i = 0; i < b; i++) { - Idx index = i + 1; - auto start = l.begin() + index; - std::vector sl(l.size() - index); - copy(start, l.end(), sl.begin()); - d[l[i]] = sl; - } - - return d; -} - inline bool in_graph(std::pair const& e, std::map> const& d) { if (auto edges_it = d.find(e.first); edges_it != d.cend()) { if (std::ranges::find(edges_it->second, e.second) != edges_it->second.cend()) { @@ -145,31 +125,30 @@ inline std::vector remove_vertices_update_degrees(Idx& u, std::map, std::vector>> nbsrl = check_indistguishable(u, d); std::vector& nbs = nbsrl[0].first; std::vector& rl = nbsrl[0].second; - std::vector alpha = rl, vu{u}; + std::vector alpha = rl; std::map> dd; - rl.insert(rl.begin(), vu.begin(), vu.end()); + rl.push_back(u); - for (auto& uu : rl) { - if (uu != u) - nbs.erase(remove(nbs.begin(), nbs.end(), uu), nbs.end()); + for (auto uu : rl) { + if (uu != u) { + std::erase(nbs, uu); + } remove_element_vector_pair(uu, dgd); std::vector el; for (auto& it : d) { - it.second.erase(remove(it.second.begin(), it.second.end(), uu), it.second.end()); + std::erase(it.second, uu); if (it.second.empty()) { - Idx k = it.first; - std::vector vk{k}; - el.insert(el.end(), vk.begin(), vk.end()); + el.push_back(it.first); } } - std::vector vuu{uu}; - el.insert(el.end(), vuu.begin(), vuu.end()); + el.push_back(uu); - for (auto& it : el) + for (auto& it : el) { d.erase(it); + } } dd = make_clique(nbs); @@ -180,17 +159,14 @@ inline std::vector remove_vertices_update_degrees(Idx& u, std::map t{k, e}; if (!in_graph(t, d)) { if (d.find(k) != d.end()) { - std::vector ve{e}; - d[k].insert(d[k].end(), ve.begin(), ve.end()); - fills.push_back({k, e}); + d[k].push_back(e); + fills.emplace_back(k, e); } else if (d.find(e) != d.end()) { - std::vector vk{k}; - d[e].insert(d[e].end(), vk.begin(), vk.end()); - fills.push_back({e, k}); + d[e].push_back(k); + fills.emplace_back(e, k); } else { - std::vector ve{e}; - d[k].insert(d[k].end(), ve.begin(), ve.end()); - fills.push_back({k, e}); + d[k].push_back(e); + fills.emplace_back(k, e); } } } From 9de4a4435d226cd0a901e4e08576b19945df1389 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 2 Jan 2024 16:09:26 +0100 Subject: [PATCH 15/66] more cleanup Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordening.hpp | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index 1730d9fdc..e78433ca9 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -182,31 +182,22 @@ inline std::vector remove_vertices_update_degrees(Idx& u, std::map, std::vector>> minimum_degree_ordering(std::map>& d) { - std::vector>>> data = detail::comp_size_degrees_graph(d); - Idx& n = data[0].first; - std::vector>& dgd = data[0].second; + auto data = detail::comp_size_degrees_graph(d); + auto& [n, dgd] = data[0]; + std::vector alpha; std::vector> fills; - for (int k = 0; k < n; k++) { - Idx u = - get<0>(*min_element(begin(dgd), end(dgd), [](auto lhs, auto rhs) { return get<1>(lhs) < get<1>(rhs); })); - std::vector vu{u}; - alpha.insert(alpha.end(), vu.begin(), vu.end()); - if ((d.size() == 1) and d.begin()->second.size() == 1) { - Idx a = d.begin()->first; - Idx b = d.begin()->second[0]; - if (alpha.back() == a) { - std::vector vb{b}; - alpha.insert(alpha.end(), vb.begin(), vb.end()); - } else { - std::vector va{a}; - alpha.insert(alpha.end(), va.begin(), va.end()); - } + for (Idx k = 0; k < n; k++) { + Idx u = get<0>(*std::ranges::min_element(dgd, [](auto lhs, auto rhs) { return get<1>(lhs) < get<1>(rhs); })); + alpha.push_back(u); + if ((d.size() == 1) && d.begin()->second.size() == 1) { + Idx const a = d.begin()->first; + Idx const b = d.begin()->second[0]; + alpha.push_back(alpha.back() == a ? b : a); break; } else { - std::vector va = detail::remove_vertices_update_degrees(u, d, dgd, fills); - alpha.insert(alpha.end(), va.begin(), va.end()); + std::ranges::copy(detail::remove_vertices_update_degrees(u, d, dgd, fills), std::back_inserter(alpha)); if (d.empty()) { break; } From 6f3e9b5b003b247280911f6d956aa028f740ff51 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 2 Jan 2024 16:15:38 +0100 Subject: [PATCH 16/66] more improvements Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordening.hpp | 50 ++++++++----------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index e78433ca9..38381cf93 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -27,8 +27,8 @@ inline void set_element_vector_pair(Idx u, Idx v, std::vector adj(Idx& u, std::map>& d) { - std::vector l; +inline IdxVector adj(Idx& u, std::map& d) { + IdxVector l; for (const auto& it : d) { if (it.first == u) { @@ -44,9 +44,9 @@ inline std::vector adj(Idx& u, std::map>& d) { } inline std::vector>>> -comp_size_degrees_graph(std::map>& d) { +comp_size_degrees_graph(std::map& d) { std::vector> dd; - std::vector v; + IdxVector v; Idx n = 0; for (const auto& it : d) { @@ -71,12 +71,12 @@ comp_size_degrees_graph(std::map>& d) { return {{n, dd}}; } -inline std::map> make_clique(std::vector& l) { - std::map> d; +inline std::map make_clique(IdxVector& l) { + std::map d; for (Idx i = 0; i < static_cast(l.size()) - 1; i++) { Idx const idx = i + 1; - std::vector sl(l.size() - idx); + IdxVector sl(l.size() - idx); std::copy(l.begin() + idx, l.end(), sl.begin()); d[l[i]] = sl; } @@ -84,9 +84,8 @@ inline std::map> make_clique(std::vector& l) { return d; } -inline std::vector, std::vector>> -check_indistguishable(Idx& u, std::map>& d) { - std::vector rl; +inline std::vector> check_indistguishable(Idx& u, std::map& d) { + IdxVector rl; auto l = adj(u, d); auto lu = l; @@ -105,7 +104,7 @@ check_indistguishable(Idx& u, std::map>& d) { return {{l, rl}}; } -inline bool in_graph(std::pair const& e, std::map> const& d) { +inline bool in_graph(std::pair const& e, std::map const& d) { if (auto edges_it = d.find(e.first); edges_it != d.cend()) { if (std::ranges::find(edges_it->second, e.second) != edges_it->second.cend()) { return true; @@ -119,14 +118,13 @@ inline bool in_graph(std::pair const& e, std::map remove_vertices_update_degrees(Idx& u, std::map>& d, - std::vector>& dgd, - std::vector>& fills) { - std::vector, std::vector>> nbsrl = check_indistguishable(u, d); - std::vector& nbs = nbsrl[0].first; - std::vector& rl = nbsrl[0].second; - std::vector alpha = rl; - std::map> dd; +inline IdxVector remove_vertices_update_degrees(Idx& u, std::map& d, + std::vector>& dgd, + std::vector>& fills) { + std::vector> nbsrl = check_indistguishable(u, d); + auto& [nbs, rl] = nbsrl[0]; + IdxVector alpha = rl; + std::map dd; rl.push_back(u); @@ -136,7 +134,7 @@ inline std::vector remove_vertices_update_degrees(Idx& u, std::map el; + IdxVector el; for (auto& it : d) { std::erase(it.second, uu); if (it.second.empty()) { @@ -158,15 +156,12 @@ inline std::vector remove_vertices_update_degrees(Idx& u, std::map t{k, e}; if (!in_graph(t, d)) { - if (d.find(k) != d.end()) { + if (d.find(k) != d.end() || d.find(e) == d.end()) { d[k].push_back(e); fills.emplace_back(k, e); - } else if (d.find(e) != d.end()) { + } else { d[e].push_back(k); fills.emplace_back(e, k); - } else { - d[k].push_back(e); - fills.emplace_back(k, e); } } } @@ -180,12 +175,11 @@ inline std::vector remove_vertices_update_degrees(Idx& u, std::map, std::vector>> -minimum_degree_ordering(std::map>& d) { +inline std::pair>> minimum_degree_ordering(std::map& d) { auto data = detail::comp_size_degrees_graph(d); auto& [n, dgd] = data[0]; - std::vector alpha; + IdxVector alpha; std::vector> fills; for (Idx k = 0; k < n; k++) { From 0c0c6673044a2c228d9e80fa21c655efa79231f6 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 2 Jan 2024 16:18:33 +0100 Subject: [PATCH 17/66] minor Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordening.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index 38381cf93..fbfb28e67 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -78,7 +78,7 @@ inline std::map make_clique(IdxVector& l) { Idx const idx = i + 1; IdxVector sl(l.size() - idx); std::copy(l.begin() + idx, l.end(), sl.begin()); - d[l[i]] = sl; + d[l[i]] = std::move(sl); } return d; From f1e992311dae32a8965301f1347a9d2bc379055f Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 30 Jan 2024 15:21:41 +0100 Subject: [PATCH 18/66] update licenses of new files Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordening.hpp | 2 +- tests/cpp_unit_tests/test_sparse_ordening.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index fbfb28e67..a71c05991 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 Contributors to the Power Grid Model project +// SPDX-FileCopyrightText: Contributors to the Power Grid Model project // // SPDX-License-Identifier: MPL-2.0 diff --git a/tests/cpp_unit_tests/test_sparse_ordening.cpp b/tests/cpp_unit_tests/test_sparse_ordening.cpp index 5b668ce15..d0c0bef8f 100644 --- a/tests/cpp_unit_tests/test_sparse_ordening.cpp +++ b/tests/cpp_unit_tests/test_sparse_ordening.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 Contributors to the Power Grid Model project +// SPDX-FileCopyrightText: Contributors to the Power Grid Model project // // SPDX-License-Identifier: MPL-2.0 From 7c78624092541456568c6952704fa0d8e9cd59cc Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Thu, 1 Feb 2024 09:52:13 +0100 Subject: [PATCH 19/66] fix clang tidy Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordening.hpp | 15 +++++++-------- .../include/power_grid_model/topology.hpp | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index a71c05991..b176eb095 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -152,9 +152,9 @@ inline IdxVector remove_vertices_update_degrees(Idx& u, std::map dd = make_clique(nbs); for (auto& it : dd) { - Idx k = it.first; + Idx const k = it.first; for (const Idx& e : it.second) { - std::pair t{k, e}; + std::pair const t{k, e}; if (!in_graph(t, d)) { if (d.find(k) != d.end() || d.find(e) == d.end()) { d[k].push_back(e); @@ -168,7 +168,7 @@ inline IdxVector remove_vertices_update_degrees(Idx& u, std::map } for (auto& e : nbs) { - set_element_vector_pair(e, adj(e, d).size(), dgd); + set_element_vector_pair(e, static_cast(adj(e, d).size()), dgd); } return alpha; @@ -190,11 +190,10 @@ inline std::pair>> minimum_degree_ord Idx const b = d.begin()->second[0]; alpha.push_back(alpha.back() == a ? b : a); break; - } else { - std::ranges::copy(detail::remove_vertices_update_degrees(u, d, dgd, fills), std::back_inserter(alpha)); - if (d.empty()) { - break; - } + } + std::ranges::copy(detail::remove_vertices_update_degrees(u, d, dgd, fills), std::back_inserter(alpha)); + if (d.empty()) { + break; } } return {alpha, fills}; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index 0df50f947..d098a8e81 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -312,7 +312,7 @@ class Topology { } std::map> unique_nearest_neighbours; - for (Idx node_idx : cyclic_node) { + for (Idx const node_idx : cyclic_node) { auto predecessor = static_cast(predecessors_[node_idx]); if (predecessor != node_idx) { unique_nearest_neighbours[node_idx] = {predecessor}; From d2b198a0aa9bdbd9df084cf57d9e3985969854f6 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 14 Feb 2024 11:45:04 +0100 Subject: [PATCH 20/66] resolve code smells - part 1 Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordening.hpp | 51 ++++++++----------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index b176eb095..f65d44e5e 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -27,16 +27,14 @@ inline void set_element_vector_pair(Idx u, Idx v, std::vector& d) { +inline IdxVector adj(Idx const& u, std::map const& d) { IdxVector l; - for (const auto& it : d) { - if (it.first == u) { - l.insert(l.end(), it.second.cbegin(), it.second.cend()); - } - - if (std::ranges::find(it.second, u) != it.second.cend()) { - l.push_back(it.first); + for (const auto& [k, adjacent] : d) { + if (k == u) { + l.insert(l.end(), adjacent.cbegin(), adjacent.cend()); + } else if (std::ranges::find(adjacent, u) != adjacent.cend()) { + l.push_back(k); } } @@ -49,15 +47,13 @@ comp_size_degrees_graph(std::map& d) { IdxVector v; Idx n = 0; - for (const auto& it : d) { - Idx k = it.first; + for (const auto& [k, adjacent] : d) { if (std::ranges::find(v, k) == v.end()) { ++n; v.push_back(k); dd.emplace_back(k, adj(k, d).size()); } - for (const Idx& el : it.second) { - Idx e = el; + for (const Idx& e : adjacent) { if (find(v.begin(), v.end(), e) == v.end()) { ++n; v.push_back(e); @@ -105,15 +101,13 @@ inline std::vector> check_indistguishable(Idx& u } inline bool in_graph(std::pair const& e, std::map const& d) { - if (auto edges_it = d.find(e.first); edges_it != d.cend()) { - if (std::ranges::find(edges_it->second, e.second) != edges_it->second.cend()) { - return true; - } + if (auto edges_it = d.find(e.first); + edges_it != d.cend() && std::ranges::find(edges_it->second, e.second) != edges_it->second.cend()) { + return true; } - if (auto edges_it = d.find(e.second); edges_it != d.cend()) { - if (std::ranges::find(edges_it->second, e.first) != edges_it->second.cend()) { - return true; - } + if (auto edges_it = d.find(e.second); + edges_it != d.cend() && std::ranges::find(edges_it->second, e.first) != edges_it->second.cend()) { + return true; } return false; } @@ -135,26 +129,25 @@ inline IdxVector remove_vertices_update_degrees(Idx& u, std::map remove_element_vector_pair(uu, dgd); IdxVector el; - for (auto& it : d) { - std::erase(it.second, uu); - if (it.second.empty()) { - el.push_back(it.first); + for (auto& [e, adjacent] : d) { + std::erase(adjacent, uu); + if (adjacent.empty()) { + el.push_back(e); } } el.push_back(uu); - for (auto& it : el) { + for (auto const& it : el) { d.erase(it); } } dd = make_clique(nbs); - for (auto& it : dd) { - Idx const k = it.first; - for (const Idx& e : it.second) { - std::pair const t{k, e}; + for (auto const& [k, adjacent] : dd) { + for (Idx e : adjacent) { + std::pair const t{k, e}; if (!in_graph(t, d)) { if (d.find(k) != d.end() || d.find(e) == d.end()) { d[k].push_back(e); From 6c4e36c37e1c0318e7f4eae487199e55b98c7d08 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 14 Feb 2024 13:19:40 +0100 Subject: [PATCH 21/66] resolve sonar cloud Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordening.hpp | 33 ++++++++++--------- .../include/power_grid_model/topology.hpp | 12 +++---- tests/cpp_unit_tests/test_sparse_ordening.cpp | 10 +++--- tests/cpp_unit_tests/test_topology.cpp | 7 ++-- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index f65d44e5e..a66d8879e 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -143,18 +143,24 @@ inline IdxVector remove_vertices_update_degrees(Idx& u, std::map } } - dd = make_clique(nbs); + dd = make_clique(nbs); // TODO check data type + + auto const add_element = [&fills](Idx from, Idx to, IdxVector& from_adjacent) { + from_adjacent.push_back(to); + fills.emplace_back(from, to); + }; for (auto const& [k, adjacent] : dd) { + auto it = d.find(k); for (Idx e : adjacent) { - std::pair const t{k, e}; - if (!in_graph(t, d)) { - if (d.find(k) != d.end() || d.find(e) == d.end()) { - d[k].push_back(e); - fills.emplace_back(k, e); + if (!in_graph(std::make_pair(k, e), d)) { + if (it != d.end()) { + add_element(k, e, it->second); + } + if (auto e_it = d.find(e); e_it != d.end()) { + add_element(e, k, e_it->second); } else { - d[e].push_back(k); - fills.emplace_back(e, k); + add_element(k, e, it->second); } } } @@ -175,19 +181,16 @@ inline std::pair>> minimum_degree_ord IdxVector alpha; std::vector> fills; - for (Idx k = 0; k < n; k++) { + for (Idx k = 0; k < n && !d.empty(); k++) { Idx u = get<0>(*std::ranges::min_element(dgd, [](auto lhs, auto rhs) { return get<1>(lhs) < get<1>(rhs); })); alpha.push_back(u); if ((d.size() == 1) && d.begin()->second.size() == 1) { - Idx const a = d.begin()->first; - Idx const b = d.begin()->second[0]; - alpha.push_back(alpha.back() == a ? b : a); + Idx const from = d.begin()->first; + Idx const to = d.begin()->second[0]; + alpha.push_back(alpha.back() == from ? to : from); break; } std::ranges::copy(detail::remove_vertices_update_degrees(u, d, dgd, fills), std::back_inserter(alpha)); - if (d.empty()) { - break; - } } return {alpha, fills}; } diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index 273d4c751..61d5b8f53 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -304,9 +304,9 @@ class Topology { std::vector cyclic_node; std::copy_if(dfs_node_copy.cbegin(), dfs_node_copy.cend(), std::back_inserter(cyclic_node), [this](Idx x) { return node_status_[x] == -2; }); - GraphIdx const n_cycle_node = cyclic_node.size(); + // reorder does not make sense if number of cyclic nodes in a sub graph is smaller than 4 - if (n_cycle_node < 4) { + if (cyclic_node.size() < 4) { std::copy(cyclic_node.crbegin(), cyclic_node.crend(), std::back_inserter(dfs_node)); return fill_in; } @@ -318,9 +318,9 @@ class Topology { unique_nearest_neighbours[node_idx] = {predecessor}; } } - for (auto const& edge : back_edges) { - auto const from{static_cast(edge.first)}; - auto const to{static_cast(edge.second)}; + for (auto const& [from_node, to_node] : back_edges) { + auto const from{static_cast(from_node)}; + auto const to{static_cast(to_node)}; if (!detail::in_graph(std::pair{from, to}, unique_nearest_neighbours)) { unique_nearest_neighbours[from].push_back(to); } @@ -331,7 +331,7 @@ class Topology { // TODO(mgovers): make this more efficient auto const permuted_node_idx = [&dfs_node](Idx node_idx) { - return static_cast(std::distance(dfs_node.begin(), std::ranges::find(dfs_node, node_idx))); + return narrow_cast(std::distance(dfs_node.begin(), std::ranges::find(dfs_node, node_idx))); }; for (auto [from, to] : fills) { diff --git a/tests/cpp_unit_tests/test_sparse_ordening.cpp b/tests/cpp_unit_tests/test_sparse_ordening.cpp index d0c0bef8f..cdd61ded0 100644 --- a/tests/cpp_unit_tests/test_sparse_ordening.cpp +++ b/tests/cpp_unit_tests/test_sparse_ordening.cpp @@ -20,15 +20,13 @@ TEST_CASE("Test sparse ordening") { {4, {6, 8}}, {6, {7, 8, 9}}, {7, {8, 9}}, {8, {9}}}; auto const start = std::chrono::high_resolution_clock::now(); - std::pair, std::vector>> const alpha_fills = - power_grid_model::minimum_degree_ordering(graph); + auto const [alpha, fills] = power_grid_model::minimum_degree_ordering(graph); auto const stop = std::chrono::high_resolution_clock::now(); auto const duration = duration_cast(stop - start); - std::cout << "Time taken by function: " << duration.count() << " microseconds" - << "\n"; + std::cout << "Time taken by function: " << duration.count() << " microseconds\n"; - CHECK(alpha_fills.first == std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); - CHECK(alpha_fills.second == std::vector>{{3, 5}, {4, 5}, {8, 5}, {6, 5}, {7, 5}}); + CHECK(alpha == std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + CHECK(fills == std::vector>{{3, 5}, {4, 5}, {8, 5}, {6, 5}, {7, 5}}); } } diff --git a/tests/cpp_unit_tests/test_topology.cpp b/tests/cpp_unit_tests/test_topology.cpp index a7e53af1e..70592def9 100644 --- a/tests/cpp_unit_tests/test_topology.cpp +++ b/tests/cpp_unit_tests/test_topology.cpp @@ -282,9 +282,10 @@ TEST_CASE("Test topology") { SUBCASE("Test topology result") { Topology topo{comp_topo, comp_conn}; - auto pair = topo.build_topology(); - auto const& math_topology = pair.first; - auto const& topo_comp_coup = *pair.second; + auto const [math_topology, topo_comp_coup_ptr] = topo.build_topology(); + + REQUIRE(topo_comp_coup_ptr != nullptr); + auto const& topo_comp_coup = *topo_comp_coup_ptr; CHECK(math_topology.size() == 2); // test component coupling From d65b929d16d4b49e3285e02a399def9195ad1364 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 14 Feb 2024 13:28:13 +0100 Subject: [PATCH 22/66] resolve sonar cloud Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordening.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index a66d8879e..dde4440a2 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -156,10 +156,10 @@ inline IdxVector remove_vertices_update_degrees(Idx& u, std::map if (!in_graph(std::make_pair(k, e), d)) { if (it != d.end()) { add_element(k, e, it->second); - } - if (auto e_it = d.find(e); e_it != d.end()) { + } else if (auto e_it = d.find(e); e_it != d.end()) { add_element(e, k, e_it->second); } else { + std::tie(it, std::ignore) = d.emplace(std::make_pair(k, IdxVector{})); add_element(k, e, it->second); } } From 0d645268e01102e717b5d807b93514ba11fda31a Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 14 Feb 2024 13:36:47 +0100 Subject: [PATCH 23/66] fix compilation Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordening.hpp | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index dde4440a2..b04602522 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -145,22 +145,16 @@ inline IdxVector remove_vertices_update_degrees(Idx& u, std::map dd = make_clique(nbs); // TODO check data type - auto const add_element = [&fills](Idx from, Idx to, IdxVector& from_adjacent) { - from_adjacent.push_back(to); - fills.emplace_back(from, to); - }; - for (auto const& [k, adjacent] : dd) { - auto it = d.find(k); for (Idx e : adjacent) { - if (!in_graph(std::make_pair(k, e), d)) { - if (it != d.end()) { - add_element(k, e, it->second); - } else if (auto e_it = d.find(e); e_it != d.end()) { - add_element(e, k, e_it->second); + std::pair const t{k, e}; + if (!in_graph(t, d)) { + if (d.contains(k) || !d.contains(e)) { + d[k].push_back(e); + fills.emplace_back(k, e); } else { - std::tie(it, std::ignore) = d.emplace(std::make_pair(k, IdxVector{})); - add_element(k, e, it->second); + d[e].push_back(k); + fills.emplace_back(e, k); } } } From 8b03643f69f0bce64e8edd335d608ab5468d3198 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 14 Feb 2024 13:40:17 +0100 Subject: [PATCH 24/66] more efficient implementation Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordening.hpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index b04602522..dde4440a2 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -145,16 +145,22 @@ inline IdxVector remove_vertices_update_degrees(Idx& u, std::map dd = make_clique(nbs); // TODO check data type + auto const add_element = [&fills](Idx from, Idx to, IdxVector& from_adjacent) { + from_adjacent.push_back(to); + fills.emplace_back(from, to); + }; + for (auto const& [k, adjacent] : dd) { + auto it = d.find(k); for (Idx e : adjacent) { - std::pair const t{k, e}; - if (!in_graph(t, d)) { - if (d.contains(k) || !d.contains(e)) { - d[k].push_back(e); - fills.emplace_back(k, e); + if (!in_graph(std::make_pair(k, e), d)) { + if (it != d.end()) { + add_element(k, e, it->second); + } else if (auto e_it = d.find(e); e_it != d.end()) { + add_element(e, k, e_it->second); } else { - d[e].push_back(k); - fills.emplace_back(e, k); + std::tie(it, std::ignore) = d.emplace(std::make_pair(k, IdxVector{})); + add_element(k, e, it->second); } } } From a3de21ddf7738ea0f7fc6477c7bbd42cd210437b Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 14 Feb 2024 13:54:56 +0100 Subject: [PATCH 25/66] fix clang tidy Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordening.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index dde4440a2..3d0a040fc 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -152,14 +152,14 @@ inline IdxVector remove_vertices_update_degrees(Idx& u, std::map for (auto const& [k, adjacent] : dd) { auto it = d.find(k); - for (Idx e : adjacent) { + for (Idx const e : adjacent) { if (!in_graph(std::make_pair(k, e), d)) { if (it != d.end()) { add_element(k, e, it->second); } else if (auto e_it = d.find(e); e_it != d.end()) { add_element(e, k, e_it->second); } else { - std::tie(it, std::ignore) = d.emplace(std::make_pair(k, IdxVector{})); + std::tie(it, std::ignore) = d.try_emplace(k); add_element(k, e, it->second); } } From 2b3804901d92762c2ef0eb0e688b9940caabe05d Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 14 Feb 2024 14:11:07 +0100 Subject: [PATCH 26/66] resolve sonar cloud Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordening.hpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index 3d0a040fc..d8cc1dbff 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -42,19 +42,19 @@ inline IdxVector adj(Idx const& u, std::map const& d) { } inline std::vector>>> -comp_size_degrees_graph(std::map& d) { +comp_size_degrees_graph(std::map const& d) { std::vector> dd; IdxVector v; Idx n = 0; for (const auto& [k, adjacent] : d) { - if (std::ranges::find(v, k) == v.end()) { + if (std::ranges::contains(v, k)) { ++n; v.push_back(k); dd.emplace_back(k, adj(k, d).size()); } for (const Idx& e : adjacent) { - if (find(v.begin(), v.end(), e) == v.end()) { + if (std::ranges::contains(v, e)) { ++n; v.push_back(e); dd.emplace_back(e, adj(e, d).size()); @@ -80,14 +80,15 @@ inline std::map make_clique(IdxVector& l) { return d; } -inline std::vector> check_indistguishable(Idx& u, std::map& d) { +inline std::vector> check_indistguishable(Idx const& u, + std::map const& d) { IdxVector rl; auto l = adj(u, d); auto lu = l; lu.push_back(u); - for (auto& v : l) { + for (auto const& v : l) { auto lv = adj(v, d); lv.push_back(v); std::ranges::sort(lu); @@ -166,7 +167,7 @@ inline IdxVector remove_vertices_update_degrees(Idx& u, std::map } } - for (auto& e : nbs) { + for (auto const& e : nbs) { set_element_vector_pair(e, static_cast(adj(e, d).size()), dgd); } @@ -181,7 +182,7 @@ inline std::pair>> minimum_degree_ord IdxVector alpha; std::vector> fills; - for (Idx k = 0; k < n && !d.empty(); k++) { + for (Idx k = 0; k < n; ++k) { Idx u = get<0>(*std::ranges::min_element(dgd, [](auto lhs, auto rhs) { return get<1>(lhs) < get<1>(rhs); })); alpha.push_back(u); if ((d.size() == 1) && d.begin()->second.size() == 1) { @@ -191,6 +192,9 @@ inline std::pair>> minimum_degree_ord break; } std::ranges::copy(detail::remove_vertices_update_degrees(u, d, dgd, fills), std::back_inserter(alpha)); + if (d.empty()) { + break; + } } return {alpha, fills}; } From 6549be4189333ccaf63d4fde5ebd114aafecdcd6 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 14 Feb 2024 14:17:23 +0100 Subject: [PATCH 27/66] fix Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordening.hpp | 4 ++-- .../include/power_grid_model/topology.hpp | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index d8cc1dbff..f4810ecc7 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -48,13 +48,13 @@ comp_size_degrees_graph(std::map const& d) { Idx n = 0; for (const auto& [k, adjacent] : d) { - if (std::ranges::contains(v, k)) { + if (std::ranges::find(v, k) == v.end()) { ++n; v.push_back(k); dd.emplace_back(k, adj(k, d).size()); } for (const Idx& e : adjacent) { - if (std::ranges::contains(v, e)) { + if (std::ranges::find(v, e) == v.end()) { ++n; v.push_back(e); dd.emplace_back(e, adj(e, d).size()); diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index 61d5b8f53..ffb837080 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -329,7 +329,6 @@ class Topology { auto [reordered, fills] = minimum_degree_ordering(unique_nearest_neighbours); std::ranges::copy(reordered, std::back_inserter(dfs_node)); - // TODO(mgovers): make this more efficient auto const permuted_node_idx = [&dfs_node](Idx node_idx) { return narrow_cast(std::distance(dfs_node.begin(), std::ranges::find(dfs_node, node_idx))); }; @@ -359,15 +358,13 @@ class Topology { Idx2D const i_math = comp_coup_.node[i]; Idx2D const j_math = comp_coup_.node[j]; Idx const math_group = [&]() { - // TODO(mgovers): rewrite - Idx group = -1; if (i_status != 0 && i_math.group != -1) { - group = i_math.group; + return i_math.group; } if (j_status != 0 && j_math.group != -1) { - group = j_math.group; + return j_math.group; } - return group; + return Idx{-1}; }(); // skip if no math model connected if (math_group == -1) { From a207fec8eff44e3118b7dc8ad770eeebd616e9d8 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 14 Feb 2024 15:57:01 +0100 Subject: [PATCH 28/66] fix more code smells Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordening.hpp | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index f4810ecc7..0460aa69a 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -9,8 +9,8 @@ #include "power_grid_model.hpp" #include // remove and remove_if -#include #include +#include #include #include @@ -27,7 +27,7 @@ inline void set_element_vector_pair(Idx u, Idx v, std::vector const& d) { +inline IdxVector adj(Idx const u, std::unordered_map const& d) { IdxVector l; for (const auto& [k, adjacent] : d) { @@ -42,18 +42,18 @@ inline IdxVector adj(Idx const& u, std::map const& d) { } inline std::vector>>> -comp_size_degrees_graph(std::map const& d) { +comp_size_degrees_graph(std::unordered_map const& d) { std::vector> dd; IdxVector v; Idx n = 0; - for (const auto& [k, adjacent] : d) { + for (auto const& [k, adjacent] : d) { if (std::ranges::find(v, k) == v.end()) { ++n; v.push_back(k); dd.emplace_back(k, adj(k, d).size()); } - for (const Idx& e : adjacent) { + for (Idx e : adjacent) { if (std::ranges::find(v, e) == v.end()) { ++n; v.push_back(e); @@ -67,8 +67,8 @@ comp_size_degrees_graph(std::map const& d) { return {{n, dd}}; } -inline std::map make_clique(IdxVector& l) { - std::map d; +inline std::unordered_map make_clique(IdxVector& l) { + std::unordered_map d; for (Idx i = 0; i < static_cast(l.size()) - 1; i++) { Idx const idx = i + 1; @@ -80,8 +80,8 @@ inline std::map make_clique(IdxVector& l) { return d; } -inline std::vector> check_indistguishable(Idx const& u, - std::map const& d) { +inline std::vector> check_indistguishable(Idx const u, + std::unordered_map const& d) { IdxVector rl; auto l = adj(u, d); @@ -101,7 +101,7 @@ inline std::vector> check_indistguishable(Idx co return {{l, rl}}; } -inline bool in_graph(std::pair const& e, std::map const& d) { +inline bool in_graph(std::pair const& e, std::unordered_map const& d) { if (auto edges_it = d.find(e.first); edges_it != d.cend() && std::ranges::find(edges_it->second, e.second) != edges_it->second.cend()) { return true; @@ -113,13 +113,13 @@ inline bool in_graph(std::pair const& e, std::map cons return false; } -inline IdxVector remove_vertices_update_degrees(Idx& u, std::map& d, +inline IdxVector remove_vertices_update_degrees(Idx const u, std::unordered_map& d, std::vector>& dgd, std::vector>& fills) { std::vector> nbsrl = check_indistguishable(u, d); auto& [nbs, rl] = nbsrl[0]; IdxVector alpha = rl; - std::map dd; + std::unordered_map dd; rl.push_back(u); @@ -175,7 +175,8 @@ inline IdxVector remove_vertices_update_degrees(Idx& u, std::map } } // namespace detail -inline std::pair>> minimum_degree_ordering(std::map& d) { +inline std::pair>> +minimum_degree_ordering(std::unordered_map& d) { auto data = detail::comp_size_degrees_graph(d); auto& [n, dgd] = data[0]; @@ -189,11 +190,11 @@ inline std::pair>> minimum_degree_ord Idx const from = d.begin()->first; Idx const to = d.begin()->second[0]; alpha.push_back(alpha.back() == from ? to : from); - break; + return {alpha, fills}; } std::ranges::copy(detail::remove_vertices_update_degrees(u, d, dgd, fills), std::back_inserter(alpha)); if (d.empty()) { - break; + return {alpha, fills}; } } return {alpha, fills}; From f1000b7c37698d81af5627913737b5282f245689 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 14 Feb 2024 16:00:17 +0100 Subject: [PATCH 29/66] fix Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordening.hpp | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index 0460aa69a..f2d09b6cb 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -9,8 +9,8 @@ #include "power_grid_model.hpp" #include // remove and remove_if +#include #include -#include #include #include @@ -27,7 +27,7 @@ inline void set_element_vector_pair(Idx u, Idx v, std::vector const& d) { +inline IdxVector adj(Idx const u, std::map const& d) { IdxVector l; for (const auto& [k, adjacent] : d) { @@ -42,7 +42,7 @@ inline IdxVector adj(Idx const u, std::unordered_map const& d) { } inline std::vector>>> -comp_size_degrees_graph(std::unordered_map const& d) { +comp_size_degrees_graph(std::map const& d) { std::vector> dd; IdxVector v; Idx n = 0; @@ -67,8 +67,8 @@ comp_size_degrees_graph(std::unordered_map const& d) { return {{n, dd}}; } -inline std::unordered_map make_clique(IdxVector& l) { - std::unordered_map d; +inline std::map make_clique(IdxVector& l) { + std::map d; for (Idx i = 0; i < static_cast(l.size()) - 1; i++) { Idx const idx = i + 1; @@ -81,7 +81,7 @@ inline std::unordered_map make_clique(IdxVector& l) { } inline std::vector> check_indistguishable(Idx const u, - std::unordered_map const& d) { + std::map const& d) { IdxVector rl; auto l = adj(u, d); @@ -101,7 +101,7 @@ inline std::vector> check_indistguishable(Idx co return {{l, rl}}; } -inline bool in_graph(std::pair const& e, std::unordered_map const& d) { +inline bool in_graph(std::pair const& e, std::map const& d) { if (auto edges_it = d.find(e.first); edges_it != d.cend() && std::ranges::find(edges_it->second, e.second) != edges_it->second.cend()) { return true; @@ -113,13 +113,13 @@ inline bool in_graph(std::pair const& e, std::unordered_map& d, +inline IdxVector remove_vertices_update_degrees(Idx const u, std::map& d, std::vector>& dgd, std::vector>& fills) { std::vector> nbsrl = check_indistguishable(u, d); auto& [nbs, rl] = nbsrl[0]; IdxVector alpha = rl; - std::unordered_map dd; + std::map dd; rl.push_back(u); @@ -175,8 +175,7 @@ inline IdxVector remove_vertices_update_degrees(Idx const u, std::unordered_map< } } // namespace detail -inline std::pair>> -minimum_degree_ordering(std::unordered_map& d) { +inline std::pair>> minimum_degree_ordering(std::map& d) { auto data = detail::comp_size_degrees_graph(d); auto& [n, dgd] = data[0]; From 4ad908421f6d8292830fbd9ce663f133423a1fc8 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 14 Feb 2024 16:09:31 +0100 Subject: [PATCH 30/66] clang-tidy Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordening.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp index f2d09b6cb..25bc36804 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp @@ -53,7 +53,7 @@ comp_size_degrees_graph(std::map const& d) { v.push_back(k); dd.emplace_back(k, adj(k, d).size()); } - for (Idx e : adjacent) { + for (Idx const e : adjacent) { if (std::ranges::find(v, e) == v.end()) { ++n; v.push_back(e); @@ -183,7 +183,8 @@ inline std::pair>> minimum_degree_ord std::vector> fills; for (Idx k = 0; k < n; ++k) { - Idx u = get<0>(*std::ranges::min_element(dgd, [](auto lhs, auto rhs) { return get<1>(lhs) < get<1>(rhs); })); + Idx const u = + get<0>(*std::ranges::min_element(dgd, [](auto lhs, auto rhs) { return get<1>(lhs) < get<1>(rhs); })); alpha.push_back(u); if ((d.size() == 1) && d.begin()->second.size() == 1) { Idx const from = d.begin()->first; From 01ea81e4f6e9853f0259b9f65149e3c32d548e92 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Thu, 15 Feb 2024 15:33:29 +0100 Subject: [PATCH 31/66] rename sparse ordening -> sparse ordering Signed-off-by: Martijn Govers --- .../{sparse_ordening.hpp => sparse_ordering.hpp} | 4 ++-- .../power_grid_model/include/power_grid_model/topology.hpp | 2 +- tests/cpp_unit_tests/CMakeLists.txt | 2 +- .../{test_sparse_ordening.cpp => test_sparse_ordering.cpp} | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) rename power_grid_model_c/power_grid_model/include/power_grid_model/{sparse_ordening.hpp => sparse_ordering.hpp} (98%) rename tests/cpp_unit_tests/{test_sparse_ordening.cpp => test_sparse_ordering.cpp} (89%) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp similarity index 98% rename from power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp rename to power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp index 25bc36804..683369cda 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordening.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MPL-2.0 #pragma once -#ifndef POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ORDENING_HPP -#define POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ORDENING_HPP +#ifndef POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ORDERING_HPP +#define POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ORDERING_HPP #include "power_grid_model.hpp" diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index ffb837080..cb99d0843 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -11,7 +11,7 @@ #include "exception.hpp" #include "index_mapping.hpp" #include "power_grid_model.hpp" -#include "sparse_ordening.hpp" +#include "sparse_ordering.hpp" #include #include diff --git a/tests/cpp_unit_tests/CMakeLists.txt b/tests/cpp_unit_tests/CMakeLists.txt index 4fe97b532..db2fcacd9 100644 --- a/tests/cpp_unit_tests/CMakeLists.txt +++ b/tests/cpp_unit_tests/CMakeLists.txt @@ -25,7 +25,7 @@ set(PROJECT_SOURCES "test_math_solver.cpp" "test_measured_values.cpp" "test_topology.cpp" - "test_sparse_ordening.cpp" + "test_sparse_ordering.cpp" "test_grouped_index_vector.cpp" "test_container.cpp" "test_index_mapping.cpp" diff --git a/tests/cpp_unit_tests/test_sparse_ordening.cpp b/tests/cpp_unit_tests/test_sparse_ordering.cpp similarity index 89% rename from tests/cpp_unit_tests/test_sparse_ordening.cpp rename to tests/cpp_unit_tests/test_sparse_ordering.cpp index cdd61ded0..d88328ff6 100644 --- a/tests/cpp_unit_tests/test_sparse_ordening.cpp +++ b/tests/cpp_unit_tests/test_sparse_ordering.cpp @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: MPL-2.0 -#include +#include #include @@ -14,8 +14,8 @@ namespace { using power_grid_model::Idx; } // namespace -TEST_CASE("Test sparse ordening") { - SUBCASE("minimum_degree_ordening") { +TEST_CASE("Test sparse ordering") { + SUBCASE("minimum_degree_ordering") { std::map> graph{{0, {3, 5}}, {1, {4, 5, 8}}, {2, {4, 5, 6}}, {3, {6, 7}}, {4, {6, 8}}, {6, {7, 8, 9}}, {7, {8, 9}}, {8, {9}}}; From 26ca1bf07eecd59fc2df752bcea0e40750fe512d Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Fri, 16 Feb 2024 17:32:26 +0100 Subject: [PATCH 32/66] remove test code Signed-off-by: Martijn Govers --- tests/cpp_validation_tests/test_validation.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tests/cpp_validation_tests/test_validation.cpp b/tests/cpp_validation_tests/test_validation.cpp index 6d55a01b8..84bfb798a 100644 --- a/tests/cpp_validation_tests/test_validation.cpp +++ b/tests/cpp_validation_tests/test_validation.cpp @@ -608,15 +608,14 @@ TEST_CASE("Validation test single") { TEST_CASE("Validation test batch") { std::vector const& all_cases = get_all_batch_cases(); for (CaseParam const& param : all_cases) { - if (param.case_name == - "power_flow/pandapower/networks/asymmetric/distribution-case-asym-newton_raphson_batch") { - SUBCASE(param.case_name.c_str()) { - try { - validate_batch_case(param); - } catch (std::exception& e) { - auto const msg = std::string("Unexpected exception with message: ") + e.what(); - FAIL_CHECK(msg); - } + SUBCASE(param.case_name.c_str()) { + try { + validate_batch_case(param); + } catch (std::exception& e) { + using namespace std::string_literals; + + auto const msg = "Unexpected exception with message: "s + e.what(); + FAIL_CHECK(msg); } } } From 9fd6e9fecf759fd0a965ad710f866f3ee621145a Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 20 Feb 2024 09:21:44 +0100 Subject: [PATCH 33/66] [skip ci] minor Signed-off-by: Martijn Govers --- tests/cpp_validation_tests/test_validation.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/cpp_validation_tests/test_validation.cpp b/tests/cpp_validation_tests/test_validation.cpp index 84bfb798a..486d9a253 100644 --- a/tests/cpp_validation_tests/test_validation.cpp +++ b/tests/cpp_validation_tests/test_validation.cpp @@ -598,7 +598,9 @@ TEST_CASE("Validation test single") { try { validate_single_case(param); } catch (std::exception& e) { - auto const msg = std::string("Unexpected exception with message: ") + e.what(); + using namespace std::string_literals; + + auto const msg = "Unexpected exception with message: "s + e.what(); FAIL_CHECK(msg); } } From 9caf62d6255407b0212f32dd87b9b2565173b78b Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 13 Mar 2024 18:09:20 +0100 Subject: [PATCH 34/66] minor fix Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordering.hpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp index 683369cda..4ffbe9866 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp @@ -3,14 +3,11 @@ // SPDX-License-Identifier: MPL-2.0 #pragma once -#ifndef POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ORDERING_HPP -#define POWER_GRID_MODEL_MATH_SOLVER_SPARSE_ORDERING_HPP -#include "power_grid_model.hpp" +#include "common/common.hpp" -#include // remove and remove_if +#include #include -#include #include #include @@ -200,5 +197,3 @@ inline std::pair>> minimum_degree_ord return {alpha, fills}; } } // namespace power_grid_model - -#endif From feb075546db826f604b0c79449b4107911d48f72 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Thu, 14 Mar 2024 07:55:10 +0100 Subject: [PATCH 35/66] fix benchmark Signed-off-by: Martijn Govers --- .../include/power_grid_model/topology.hpp | 12 +++++++----- tests/cpp_unit_tests/test_topology.cpp | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index 666203cba..f62b31853 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -325,15 +325,17 @@ class Topology { } auto [reordered, fills] = minimum_degree_ordering(unique_nearest_neighbours); - std::ranges::copy(reordered, std::back_inserter(dfs_node)); - auto const permuted_node_idx = [&dfs_node](Idx node_idx) { - return narrow_cast(std::distance(dfs_node.begin(), std::ranges::find(dfs_node, node_idx))); + const auto n_non_cyclic_nodes = static_cast(dfs_node.size()); + auto const permuted_node_idx = [n_non_cyclic_nodes, &reordered](Idx node_idx) { + return n_non_cyclic_nodes + + narrow_cast(std::distance(reordered.begin(), std::ranges::find(reordered, node_idx))); }; + std::ranges::copy(reordered, std::back_inserter(dfs_node)); for (auto [from, to] : fills) { - auto from_reordered = permuted_node_idx(reordered[from]); - auto to_reordered = permuted_node_idx(reordered[to]); + auto from_reordered = permuted_node_idx(from); + auto to_reordered = permuted_node_idx(to); fill_in.push_back({from_reordered, to_reordered}); } diff --git a/tests/cpp_unit_tests/test_topology.cpp b/tests/cpp_unit_tests/test_topology.cpp index 70592def9..4b707415a 100644 --- a/tests/cpp_unit_tests/test_topology.cpp +++ b/tests/cpp_unit_tests/test_topology.cpp @@ -259,7 +259,7 @@ TEST_CASE("Test topology") { // sensor 0 is connected to branch 0 // sensor 1 and 2 are connected to branch 1 math0.power_sensors_per_branch_to = {from_dense, {0, 1, 1}, 7}; - math0.fill_in = {{4, 2}}; + math0.fill_in = {{3, 2}}; // Sub graph / math model 1 MathModelTopology math1; @@ -395,7 +395,7 @@ TEST_CASE("Test cycle reorder") { // result TopologicalComponentToMathCoupling comp_coup_ref{}; comp_coup_ref.node = {{0, 0}, {0, 3}, {0, 1}, {0, 2}, {0, 4}, {0, 5}, {0, 6}}; - std::vector const fill_in_ref{{5, 6}, {3, 6}, {6, 4}}; + std::vector const fill_in_ref{{5, 6}, {2, 6}, {6, 4}}; Topology topo{comp_topo, comp_conn}; auto pair = topo.build_topology(); From f9d42163f5e8654c658184997a5595bafc006453 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Fri, 22 Mar 2024 08:27:25 +0100 Subject: [PATCH 36/66] capturing structured bindings will be supported starting Clang16 Signed-off-by: Martijn Govers --- .../power_grid_model/include/power_grid_model/topology.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index f62b31853..78dac0fa3 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -327,7 +327,7 @@ class Topology { auto [reordered, fills] = minimum_degree_ordering(unique_nearest_neighbours); const auto n_non_cyclic_nodes = static_cast(dfs_node.size()); - auto const permuted_node_idx = [n_non_cyclic_nodes, &reordered](Idx node_idx) { + auto const permuted_node_idx = [n_non_cyclic_nodes, &reordered = reordered](Idx node_idx) { return n_non_cyclic_nodes + narrow_cast(std::distance(reordered.begin(), std::ranges::find(reordered, node_idx))); }; From d6293a351be427095c87505c435f42bee02c7a84 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Fri, 22 Mar 2024 08:42:44 +0100 Subject: [PATCH 37/66] fix sonar cloud Signed-off-by: Martijn Govers --- .../power_grid_model/include/power_grid_model/topology.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index 78dac0fa3..ac30029af 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -327,9 +327,9 @@ class Topology { auto [reordered, fills] = minimum_degree_ordering(unique_nearest_neighbours); const auto n_non_cyclic_nodes = static_cast(dfs_node.size()); - auto const permuted_node_idx = [n_non_cyclic_nodes, &reordered = reordered](Idx node_idx) { + auto const permuted_node_idx = [n_non_cyclic_nodes, &reordered_ = reordered](Idx node_idx) { return n_non_cyclic_nodes + - narrow_cast(std::distance(reordered.begin(), std::ranges::find(reordered, node_idx))); + narrow_cast(std::distance(reordered_.begin(), std::ranges::find(reordered_, node_idx))); }; std::ranges::copy(reordered, std::back_inserter(dfs_node)); From 7f65dc9c6ec43a1cde30714cb97e26bc52096980 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 4 Jun 2024 10:39:33 +0200 Subject: [PATCH 38/66] trafo tap_pos optional + test Signed-off-by: petersalemink95 --- .../component/transformer.hpp | 20 +++++++++---------- tests/cpp_unit_tests/test_transformer.cpp | 12 +++++++++++ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp index 19c91a987..f3357ebe2 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp @@ -37,7 +37,9 @@ class Transformer : public Branch { winding_to_{transformer_input.winding_to}, clock_{transformer_input.clock}, tap_side_{transformer_input.tap_side}, - tap_pos_{transformer_input.tap_pos}, + tap_pos_{transformer_input.tap_pos == na_IntS + ? (transformer_input.tap_nom == na_IntS ? (IntS)0 : transformer_input.tap_nom) + : transformer_input.tap_pos}, tap_min_{transformer_input.tap_min}, tap_max_{transformer_input.tap_max}, tap_nom_{transformer_input.tap_nom == na_IntS ? (IntS)0 : transformer_input.tap_nom}, @@ -71,14 +73,14 @@ class Transformer : public Branch { double phase_shift() const final { return clock_ * deg_30; } bool is_param_mutable() const final { return true; } // getters - constexpr IntS tap_pos() const { return tap_pos_; } - constexpr BranchSide tap_side() const { return tap_side_; } - constexpr IntS tap_min() const { return tap_min_; } - constexpr IntS tap_max() const { return tap_max_; } - constexpr IntS tap_nom() const { return tap_nom_; } + IntS tap_pos() const { return tap_pos_; } + BranchSide tap_side() const { return tap_side_; } + IntS tap_min() const { return tap_min_; } + IntS tap_max() const { return tap_max_; } + IntS tap_nom() const { return tap_nom_; } // setter - constexpr bool set_tap(IntS new_tap) { + bool set_tap(IntS new_tap) { if (new_tap == na_IntS || new_tap == tap_pos_) { return false; } @@ -142,7 +144,7 @@ class Transformer : public Branch { return {r / base_z, x / base_z}; } - constexpr IntS tap_limit(IntS new_tap) const { + IntS tap_limit(IntS new_tap) const { new_tap = std::min(new_tap, std::max(tap_max_, tap_min_)); new_tap = std::max(new_tap, std::min(tap_max_, tap_min_)); return new_tap; @@ -265,6 +267,4 @@ class Transformer : public Branch { } }; -static_assert(transformer_c); - } // namespace power_grid_model diff --git a/tests/cpp_unit_tests/test_transformer.cpp b/tests/cpp_unit_tests/test_transformer.cpp index 833577f40..282552aba 100644 --- a/tests/cpp_unit_tests/test_transformer.cpp +++ b/tests/cpp_unit_tests/test_transformer.cpp @@ -58,6 +58,18 @@ TEST_CASE("Test transformer") { .r_grounding_to = nan, .x_grounding_to = nan}; + SUBCASE("Test optional inputs") { + input.tap_nom = 1; + input.tap_pos = na_IntS; + std::vector vec; + vec.emplace_back(input, 150e3, 10e3); + input.tap_nom = na_IntS; + vec.emplace_back(input, 150e3, 10e3); + CHECK(vec[0].tap_pos() == 1); + CHECK(vec[1].tap_pos() == 0); + CHECK(vec[1].tap_nom() == 0); + } + std::vector vec; // 0 YNyn12 vec.emplace_back(input, 150e3, 10e3); From 01048963ddffd8180a9305f999f15da04355b873 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 4 Jun 2024 12:33:35 +0200 Subject: [PATCH 39/66] revert weird changes Signed-off-by: petersalemink95 --- .../power_grid_model/component/transformer.hpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp index f3357ebe2..ab5d36191 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp @@ -73,14 +73,14 @@ class Transformer : public Branch { double phase_shift() const final { return clock_ * deg_30; } bool is_param_mutable() const final { return true; } // getters - IntS tap_pos() const { return tap_pos_; } - BranchSide tap_side() const { return tap_side_; } - IntS tap_min() const { return tap_min_; } - IntS tap_max() const { return tap_max_; } - IntS tap_nom() const { return tap_nom_; } + constexpr IntS tap_pos() const { return tap_pos_; } + constexpr BranchSide tap_side() const { return tap_side_; } + constexpr IntS tap_min() const { return tap_min_; } + constexpr IntS tap_max() const { return tap_max_; } + constexpr IntS tap_nom() const { return tap_nom_; } // setter - bool set_tap(IntS new_tap) { + constexpr bool set_tap(IntS new_tap) { if (new_tap == na_IntS || new_tap == tap_pos_) { return false; } @@ -144,7 +144,7 @@ class Transformer : public Branch { return {r / base_z, x / base_z}; } - IntS tap_limit(IntS new_tap) const { + constexpr IntS tap_limit(IntS new_tap) const { new_tap = std::min(new_tap, std::max(tap_max_, tap_min_)); new_tap = std::max(new_tap, std::min(tap_max_, tap_min_)); return new_tap; @@ -267,4 +267,6 @@ class Transformer : public Branch { } }; +static_assert(transformer_c); + } // namespace power_grid_model From adf188727fb23308b27ece940fc3c28f84cc6f5b Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 4 Jun 2024 12:57:45 +0200 Subject: [PATCH 40/66] 3w trafo tap pos optional Signed-off-by: petersalemink95 --- .../power_grid_model/component/three_winding_transformer.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/three_winding_transformer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/three_winding_transformer.hpp index 8284d9e7d..cbb549821 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/three_winding_transformer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/three_winding_transformer.hpp @@ -42,7 +42,10 @@ class ThreeWindingTransformer : public Branch3 { clock_12_{three_winding_transformer_input.clock_12}, clock_13_{three_winding_transformer_input.clock_13}, tap_side_{three_winding_transformer_input.tap_side}, - tap_pos_{three_winding_transformer_input.tap_pos}, + tap_pos_{three_winding_transformer_input.tap_pos == na_IntS + ? (three_winding_transformer_input.tap_nom == na_IntS ? (IntS)0 + : three_winding_transformer_input.tap_nom) + : three_winding_transformer_input.tap_pos}, tap_min_{three_winding_transformer_input.tap_min}, tap_max_{three_winding_transformer_input.tap_max}, tap_nom_{three_winding_transformer_input.tap_nom == na_IntS ? (IntS)0 From 72722a15312962c69a66be2540015010ccdc53f0 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 4 Jun 2024 13:48:56 +0200 Subject: [PATCH 41/66] 3w trafo test Signed-off-by: petersalemink95 --- .../test_three_winding_transformer.cpp | 13 ++++++++++- tests/cpp_unit_tests/test_transformer.cpp | 23 +++++++++---------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/tests/cpp_unit_tests/test_three_winding_transformer.cpp b/tests/cpp_unit_tests/test_three_winding_transformer.cpp index 75cdb1487..1191ee998 100644 --- a/tests/cpp_unit_tests/test_three_winding_transformer.cpp +++ b/tests/cpp_unit_tests/test_three_winding_transformer.cpp @@ -583,6 +583,17 @@ TEST_CASE("Test three winding transformer") { CHECK(inv.status_3 == expected.status_3); CHECK(inv.tap_pos == expected.tap_pos); } -} // namespace power_grid_model + SUBCASE("Test optional tap pos/nom") { + input.tap_nom = 1; + input.tap_pos = na_IntS; + std::vector vec; + vec.emplace_back(input, 138e3, 69e3, 13.8e3); + input.tap_nom = na_IntS; + vec.emplace_back(input, 138e3, 69e3, 13.8e3); + CHECK(vec[0].tap_pos() == 1); + CHECK(vec[1].tap_pos() == 0); + CHECK(vec[1].tap_nom() == 0); + } +} } // namespace power_grid_model diff --git a/tests/cpp_unit_tests/test_transformer.cpp b/tests/cpp_unit_tests/test_transformer.cpp index 282552aba..9e5b7d3b5 100644 --- a/tests/cpp_unit_tests/test_transformer.cpp +++ b/tests/cpp_unit_tests/test_transformer.cpp @@ -58,18 +58,6 @@ TEST_CASE("Test transformer") { .r_grounding_to = nan, .x_grounding_to = nan}; - SUBCASE("Test optional inputs") { - input.tap_nom = 1; - input.tap_pos = na_IntS; - std::vector vec; - vec.emplace_back(input, 150e3, 10e3); - input.tap_nom = na_IntS; - vec.emplace_back(input, 150e3, 10e3); - CHECK(vec[0].tap_pos() == 1); - CHECK(vec[1].tap_pos() == 0); - CHECK(vec[1].tap_nom() == 0); - } - std::vector vec; // 0 YNyn12 vec.emplace_back(input, 150e3, 10e3); @@ -278,6 +266,17 @@ TEST_CASE("Test transformer") { CHECK(inv.to_status == expected.to_status); CHECK(inv.tap_pos == expected.tap_pos); } + SUBCASE("Test optional tap pos/nom") { + input.tap_nom = 1; + input.tap_pos = na_IntS; + std::vector vec; + vec.emplace_back(input, 150e3, 10e3); + input.tap_nom = na_IntS; + vec.emplace_back(input, 150e3, 10e3); + CHECK(vec[0].tap_pos() == 1); + CHECK(vec[1].tap_pos() == 0); + CHECK(vec[1].tap_nom() == 0); + } } TEST_CASE("Test Transfomer - Test 0 YNyn12") { From ca6a41a0e923d19c5bb32bb789045b4349a4c7b2 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Fri, 7 Jun 2024 15:08:50 +0200 Subject: [PATCH 42/66] update docs Signed-off-by: petersalemink95 --- docs/user_manual/components.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user_manual/components.md b/docs/user_manual/components.md index e4ebb3bf2..9f90a2675 100644 --- a/docs/user_manual/components.md +++ b/docs/user_manual/components.md @@ -181,7 +181,7 @@ levels. An example of usage of transformer is given in [Transformer Examples](.. | `winding_to` | {py:class}`WindingType ` | - | to-side winding type | ✔ | ❌ | | | `clock` | `int8_t` | - | clock number of phase shift.
Even number is not possible if one side is Y(N) winding and the other side is not Y(N) winding.
Odd number is not possible, if both sides are Y(N) winding or both sides are not Y(N) winding. | ✔ | ❌ | `>= 0` and `<= 12` | | `tap_side` | {py:class}`BranchSide ` | - | side of tap changer | ✔ | ❌ | | -| `tap_pos` | `int8_t` | - | current position of tap changer | ✔ | ✔ | `(tap_min <= tap_pos <= tap_max)` or `(tap_min >= tap_pos >= tap_max)` | +| `tap_pos` | `int8_t` | - | current position of tap changer | ❌ default `tap_nom`, if no `tap_nom` default `0` | ✔ | `(tap_min <= tap_pos <= tap_max)` or `(tap_min >= tap_pos >= tap_max)` | | `tap_min` | `int8_t` | - | position of tap changer at minimum voltage | ✔ | ❌ | | | `tap_max` | `int8_t` | - | position of tap changer at maximum voltage | ✔ | ❌ | | | `tap_nom` | `int8_t` | - | nominal position of tap changer | ❌ default `0` | ❌ | `(tap_min <= tap_nom <= tap_max)` or `(tap_min >= tap_nom >= tap_max)` | @@ -301,7 +301,7 @@ voltage levels. An example of usage of three-winding transformer is given in [Tr | `clock_12` | `int8_t` | - | clock number of phase shift across side 1-2, odd number is only allowed for Dy(n) or Y(N)d configuration. | ✔ | ❌ | `>= 0` and `<= 12` | | `clock_13` | `int8_t` | - | clock number of phase shift across side 1-3, odd number is only allowed for Dy(n) or Y(N)d configuration. | ✔ | ❌ | `>= 0` and `<= 12` | | `tap_side` | {py:class}`Branch3Side ` | - | side of tap changer | ✔ | ❌ | `side_1` or `side_2` or `side_3` | -| `tap_pos` | `int8_t` | - | current position of tap changer | ✔ | ✔ | `(tap_min <= tap_pos <= tap_max)` or `(tap_min >= tap_pos >= tap_max)` | +| `tap_pos` | `int8_t` | - | current position of tap changer | ❌ default `tap_nom`, if no `tap_nom` default `0` | ✔ | `(tap_min <= tap_pos <= tap_max)` or `(tap_min >= tap_pos >= tap_max)` | | `tap_min` | `int8_t` | - | position of tap changer at minimum voltage | ✔ | ❌ | | | `tap_max` | `int8_t` | - | position of tap changer at maximum voltage | ✔ | ❌ | | | `tap_nom` | `int8_t` | - | nominal position of tap changer | ❌ default `0` | ❌ | `(tap_min <= tap_nom <= tap_max)` or `(tap_min >= tap_nom >= tap_max)` | From 30d4853917beb451e7b1550f7831a19cc844b9f5 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Fri, 7 Jun 2024 15:27:49 +0200 Subject: [PATCH 43/66] remove tap_pos from required Signed-off-by: petersalemink95 --- src/power_grid_model/validation/validation.py | 2 -- tests/unit/validation/test_validation_functions.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/power_grid_model/validation/validation.py b/src/power_grid_model/validation/validation.py index 0483fab8e..3edcd6127 100644 --- a/src/power_grid_model/validation/validation.py +++ b/src/power_grid_model/validation/validation.py @@ -295,7 +295,6 @@ def validate_required_values( "winding_to", "clock", "tap_side", - "tap_pos", "tap_min", "tap_max", "tap_size", @@ -323,7 +322,6 @@ def validate_required_values( "clock_12", "clock_13", "tap_side", - "tap_pos", "tap_min", "tap_max", "tap_size", diff --git a/tests/unit/validation/test_validation_functions.py b/tests/unit/validation/test_validation_functions.py index 3e07b13d7..7d0967599 100644 --- a/tests/unit/validation/test_validation_functions.py +++ b/tests/unit/validation/test_validation_functions.py @@ -240,7 +240,6 @@ def test_validate_required_values_sym_calculation(calculation_type, symmetric): assert MissingValueError("transformer", "winding_to", [NaN]) in required_values_errors assert MissingValueError("transformer", "clock", [NaN]) in required_values_errors assert MissingValueError("transformer", "tap_side", [NaN]) in required_values_errors - assert MissingValueError("transformer", "tap_pos", [NaN]) in required_values_errors assert MissingValueError("transformer", "tap_min", [NaN]) in required_values_errors assert MissingValueError("transformer", "tap_max", [NaN]) in required_values_errors assert MissingValueError("transformer", "tap_size", [NaN]) in required_values_errors @@ -272,7 +271,6 @@ def test_validate_required_values_sym_calculation(calculation_type, symmetric): assert MissingValueError("three_winding_transformer", "clock_12", [NaN]) in required_values_errors assert MissingValueError("three_winding_transformer", "clock_13", [NaN]) in required_values_errors assert MissingValueError("three_winding_transformer", "tap_side", [NaN]) in required_values_errors - assert MissingValueError("three_winding_transformer", "tap_pos", [NaN]) in required_values_errors assert MissingValueError("three_winding_transformer", "tap_min", [NaN]) in required_values_errors assert MissingValueError("three_winding_transformer", "tap_max", [NaN]) in required_values_errors assert MissingValueError("three_winding_transformer", "tap_size", [NaN]) in required_values_errors From 4a6ab1fd762b1269e6ec0e249f6b172938bf8574 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Fri, 7 Jun 2024 15:45:39 +0200 Subject: [PATCH 44/66] update all_between_or_at_rules Signed-off-by: petersalemink95 --- src/power_grid_model/validation/rules.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/power_grid_model/validation/rules.py b/src/power_grid_model/validation/rules.py index bc21878d3..337a02946 100644 --- a/src/power_grid_model/validation/rules.py +++ b/src/power_grid_model/validation/rules.py @@ -278,6 +278,7 @@ def all_between_or_at( # pylint: disable=too-many-arguments ref_value_1: Union[int, float, str], ref_value_2: Union[int, float, str], default_value: Optional[Union[np.ndarray, int, float]] = None, + default_value_2: Optional[Union[np.ndarray, int, float]] = None, ) -> List[NotBetweenOrAtError]: """ Check that for all records of a particular type of component, the values in the 'field' column are inclusively @@ -297,6 +298,8 @@ def all_between_or_at( # pylint: disable=too-many-arguments default_value: Some values are not required, but will receive a default value in the C++ core. To do a proper input validation, these default values should be included in the validation. It can be a fixed value for the entire column (int/float) or be different for each element (np.ndarray). + default_value_2: Some values can have a double default: the default will be set to another attribute of the + component, but if that attribute is missing, the default will be set to a fixed value. Returns: A list containing zero or one NotBetweenOrAtErrors, listing all ids where the value in the field of interest was @@ -307,7 +310,7 @@ def outside(val: np.ndarray, *ref: np.ndarray) -> np.ndarray: return np.logical_or(np.less(val, np.minimum(*ref)), np.greater(val, np.maximum(*ref))) return none_match_comparison( - data, component, field, outside, (ref_value_1, ref_value_2), NotBetweenOrAtError, default_value + data, component, field, outside, (ref_value_1, ref_value_2), NotBetweenOrAtError, default_value, default_value_2 ) @@ -319,6 +322,7 @@ def none_match_comparison( ref_value: ComparisonError.RefType, error: Type[CompError] = ComparisonError, # type: ignore default_value: Optional[Union[np.ndarray, int, float]] = None, + default_value_2: Optional[Union[np.ndarray, int, float]] = None, ) -> List[CompError]: # pylint: disable=too-many-arguments """ @@ -338,6 +342,8 @@ def none_match_comparison( default_value: Some values are not required, but will receive a default value in the C++ core. To do a proper input validation, these default values should be included in the validation. It can be a fixed value for the entire column (int/float) or be different for each element (np.ndarray). + default_value_2: Some values can have a double default: the default will be set to another attribute of the + component, but if that attribute is missing, the default will be set to a fixed value. Returns: A list containing zero or one comparison errors (should be a subclass of ComparisonError), listing all ids @@ -345,6 +351,9 @@ def none_match_comparison( """ if default_value is not None: set_default_value(data=data, component=component, field=field, default_value=default_value) + if default_value_2 is not None: + set_default_value(data=data, component=component, field=field, default_value=default_value_2) + # if default 2 not None -> set_default_value component_data = data[component] if isinstance(ref_value, tuple): ref = tuple(eval_expression(component_data, v) for v in ref_value) From 4b0ee0556118866463e3420f341db5431d72ca8c Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Fri, 7 Jun 2024 15:48:18 +0200 Subject: [PATCH 45/66] update all_between_or_at input Signed-off-by: petersalemink95 --- src/power_grid_model/validation/validation.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/power_grid_model/validation/validation.py b/src/power_grid_model/validation/validation.py index 3edcd6127..22f46f081 100644 --- a/src/power_grid_model/validation/validation.py +++ b/src/power_grid_model/validation/validation.py @@ -525,7 +525,7 @@ def validate_transformer(data: SingleDataset) -> List[ValidationError]: errors += all_between_or_at(data, "transformer", "clock", 0, 12) errors += all_valid_clocks(data, "transformer", "clock", "winding_from", "winding_to") errors += all_valid_enum_values(data, "transformer", "tap_side", BranchSide) - errors += all_between_or_at(data, "transformer", "tap_pos", "tap_min", "tap_max") + errors += all_between_or_at(data, "transformer", "tap_pos", "tap_min", "tap_max", data["transformer"]["tap_nom"], 0) errors += all_between_or_at(data, "transformer", "tap_nom", "tap_min", "tap_max", 0) errors += all_greater_than_or_equal_to_zero(data, "transformer", "tap_size") errors += all_greater_or_equal(data, "transformer", "uk_min", "pk_min/sn", data["transformer"]["uk"]) @@ -583,7 +583,15 @@ def validate_three_winding_transformer(data: SingleDataset) -> List[ValidationEr errors += all_valid_clocks(data, "three_winding_transformer", "clock_12", "winding_1", "winding_2") errors += all_valid_clocks(data, "three_winding_transformer", "clock_13", "winding_1", "winding_3") errors += all_valid_enum_values(data, "three_winding_transformer", "tap_side", Branch3Side) - errors += all_between_or_at(data, "three_winding_transformer", "tap_pos", "tap_min", "tap_max") + errors += all_between_or_at( + data, + "three_winding_transformer", + "tap_pos", + "tap_min", + "tap_max", + data["three_winding_transformer"]["tap_nom"], + 0, + ) errors += all_between_or_at(data, "three_winding_transformer", "tap_nom", "tap_min", "tap_max", 0) errors += all_greater_than_or_equal_to_zero(data, "three_winding_transformer", "tap_size") errors += all_greater_or_equal( From 80eef43a43c4a828e3a333bdf467858a24ae03bd Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Fri, 7 Jun 2024 16:57:28 +0200 Subject: [PATCH 46/66] test all_between_or_at Signed-off-by: petersalemink95 --- tests/unit/validation/test_rules.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/unit/validation/test_rules.py b/tests/unit/validation/test_rules.py index 6440b7d49..50fb99592 100644 --- a/tests/unit/validation/test_rules.py +++ b/tests/unit/validation/test_rules.py @@ -7,7 +7,7 @@ import numpy as np import pytest -from power_grid_model import LoadGenType, initialize_array +from power_grid_model import LoadGenType, initialize_array, power_grid_meta_data from power_grid_model.enum import FaultPhase, FaultType from power_grid_model.validation.errors import ( ComparisonError, @@ -143,6 +143,19 @@ def test_all_between_or_at(): assert len(errors) == 1 assert NotBetweenOrAtError("test", "value", [1, 4, 5, 6], (0.2, -0.2)) in errors + int8_nan = power_grid_meta_data["input"]["transformer"].nans["tap_pos"] + transformer_array = initialize_array("input", "transformer", 3) + transformer_array["id"] = [1, 2, 3] + transformer_array["tap_pos"] = [int8_nan, 1, int8_nan] + transformer_array["tap_nom"] = [2, 1, int8_nan] + valid = {"transformer": transformer_array} + errors = all_between_or_at(valid, "transformer", "tap_pos", 0, 2, transformer_array["tap_nom"], 0) + assert not errors + + errors = all_between_or_at(valid, "transformer", "tap_pos", 1, 2, transformer_array["tap_nom"], 0) + assert len(errors) == 1 + assert NotBetweenOrAtError("transformer", "tap_pos", [3], (1, 2)) in errors + def test_all_greater_than(): valid = {"test": np.array([(1, 0.0), (2, 0.2), (3, 0.5), (4, np.nan)], dtype=[("id", "i4"), ("value", "f8")])} From 500d1a8298b82d43c58a44d59754f892b69bfa77 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Fri, 7 Jun 2024 17:10:36 +0200 Subject: [PATCH 47/66] test none_match_comparisson Signed-off-by: petersalemink95 --- tests/unit/validation/test_rules.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/unit/validation/test_rules.py b/tests/unit/validation/test_rules.py index 50fb99592..7691c2e5a 100644 --- a/tests/unit/validation/test_rules.py +++ b/tests/unit/validation/test_rules.py @@ -230,6 +230,19 @@ def test_none_match_comparison(): assert len(errors) == 1 assert ComparisonError("test", "value", [2], 0.2) in errors + int8_nan = power_grid_meta_data["input"]["transformer"].nans["tap_pos"] + transformer_array = initialize_array("input", "transformer", 3) + transformer_array["id"] = [1, 2, 3] + transformer_array["tap_pos"] = [int8_nan, 0, int8_nan] + transformer_array["tap_nom"] = [1, 1, int8_nan] + valid = {"transformer": transformer_array} + + errors = none_match_comparison( + valid, "transformer", "tap_pos", np.equal, 0, ComparisonError, transformer_array["tap_nom"], 0 + ) + assert len(errors) == 1 + assert ComparisonError("transformer", "tap_pos", [2, 3], 0) in errors + def test_all_identical(): dtype = [("id", "i4"), ("foo", "i4")] From 7679c0ba48ac55f0b4bb2f1f993a37da61e10556 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Wed, 12 Jun 2024 16:50:34 +0200 Subject: [PATCH 48/66] check default validation Signed-off-by: petersalemink95 --- .../validation/test_validation_functions.py | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/tests/unit/validation/test_validation_functions.py b/tests/unit/validation/test_validation_functions.py index 7d0967599..3001e1971 100644 --- a/tests/unit/validation/test_validation_functions.py +++ b/tests/unit/validation/test_validation_functions.py @@ -715,3 +715,87 @@ def test_power_sigma_or_p_q_sigma(): } assert_valid_input_data(input_data=input_data, calculation_type=CalculationType.state_estimation) + + +def test_all_default_values(): + """ + Initialize all components that have attributes that have default values, without setting values for + those attributes. + """ + node = initialize_array("input", "node", 3) + node["id"] = [0, 1, 2] + node["u_rated"] = [50.0e3, 20.0e3, 10.5e3] + + source = initialize_array("input", "source", 1) + source["id"] = [3] + source["node"] = [2] + source["status"] = [1] + source["u_ref"] = [1.0] + + transformer = initialize_array("input", "transformer", 1) + transformer["id"] = [4] + transformer["from_node"] = [0] + transformer["to_node"] = [2] + transformer["from_status"] = [1] + transformer["to_status"] = [1] + transformer["u1"] = [50e3] + transformer["u2"] = [10.5e3] + transformer["sn"] = [1e5] + transformer["uk"] = [0.1] + transformer["pk"] = [1e3] + transformer["i0"] = [1.0e-6] + transformer["p0"] = [0.1] + transformer["winding_from"] = [2] + transformer["winding_to"] = [1] + transformer["clock"] = [5] + transformer["tap_side"] = [0] + transformer["tap_min"] = [-11] + transformer["tap_max"] = [9] + transformer["tap_size"] = [100] + + three_winding_transformer = initialize_array("input", "three_winding_transformer", 1) + three_winding_transformer["id"] = [6] + three_winding_transformer["node_1"] = [0] + three_winding_transformer["node_2"] = [1] + three_winding_transformer["node_3"] = [2] + three_winding_transformer["status_1"] = [1] + three_winding_transformer["status_2"] = [1] + three_winding_transformer["status_3"] = [1] + three_winding_transformer["u1"] = [50.0e3] + three_winding_transformer["u2"] = [20.0e3] + three_winding_transformer["u3"] = [10.5e3] + three_winding_transformer["sn_1"] = [1e5] + three_winding_transformer["sn_2"] = [1e5] + three_winding_transformer["sn_3"] = [1e5] + three_winding_transformer["uk_12"] = [0.09] + three_winding_transformer["uk_13"] = [0.06] + three_winding_transformer["uk_23"] = [0.06] + three_winding_transformer["pk_12"] = [1e3] + three_winding_transformer["pk_13"] = [1e3] + three_winding_transformer["pk_23"] = [1e3] + three_winding_transformer["i0"] = [0] + three_winding_transformer["p0"] = [0] + three_winding_transformer["winding_1"] = [2] + three_winding_transformer["winding_2"] = [1] + three_winding_transformer["winding_3"] = [1] + three_winding_transformer["clock_12"] = [5] + three_winding_transformer["clock_13"] = [5] + three_winding_transformer["tap_side"] = [0] + three_winding_transformer["tap_min"] = [-10] + three_winding_transformer["tap_max"] = [10] + three_winding_transformer["tap_size"] = [1380] + + fault = initialize_array("input", "fault", 1) + fault["id"] = [5] + fault["status"] = [1] + fault["fault_object"] = [0] + + input_data = { + "node": node, + "transformer": transformer, + "three_winding_transformer": three_winding_transformer, + "source": source, + "fault": fault, + } + + assert_valid_input_data(input_data=input_data, calculation_type=CalculationType.power_flow) From 6f37818f0d6fd6b788b5b0cfad0da536254397a1 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Wed, 12 Jun 2024 17:01:17 +0200 Subject: [PATCH 49/66] IntS logic Signed-off-by: petersalemink95 --- .../component/three_winding_transformer.hpp | 6 +++--- .../include/power_grid_model/component/transformer.hpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/three_winding_transformer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/three_winding_transformer.hpp index cbb549821..5f7cb3b90 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/three_winding_transformer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/three_winding_transformer.hpp @@ -43,14 +43,14 @@ class ThreeWindingTransformer : public Branch3 { clock_13_{three_winding_transformer_input.clock_13}, tap_side_{three_winding_transformer_input.tap_side}, tap_pos_{three_winding_transformer_input.tap_pos == na_IntS - ? (three_winding_transformer_input.tap_nom == na_IntS ? (IntS)0 + ? (three_winding_transformer_input.tap_nom == na_IntS ? IntS{0} : three_winding_transformer_input.tap_nom) : three_winding_transformer_input.tap_pos}, tap_min_{three_winding_transformer_input.tap_min}, tap_max_{three_winding_transformer_input.tap_max}, - tap_nom_{three_winding_transformer_input.tap_nom == na_IntS ? (IntS)0 + tap_nom_{three_winding_transformer_input.tap_nom == na_IntS ? IntS{0} : three_winding_transformer_input.tap_nom}, - tap_direction_{tap_max_ > tap_min_ ? (IntS)1 : (IntS)-1}, + tap_direction_{tap_max_ > tap_min_ ? IntS{1} : IntS{-1}}, tap_size_{three_winding_transformer_input.tap_size}, uk_12_min_{is_nan(three_winding_transformer_input.uk_12_min) ? uk_12_ : three_winding_transformer_input.uk_12_min}, diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp index ab5d36191..da11f5b67 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp @@ -38,12 +38,12 @@ class Transformer : public Branch { clock_{transformer_input.clock}, tap_side_{transformer_input.tap_side}, tap_pos_{transformer_input.tap_pos == na_IntS - ? (transformer_input.tap_nom == na_IntS ? (IntS)0 : transformer_input.tap_nom) + ? (transformer_input.tap_nom == na_IntS ? IntS{0} : transformer_input.tap_nom) : transformer_input.tap_pos}, tap_min_{transformer_input.tap_min}, tap_max_{transformer_input.tap_max}, - tap_nom_{transformer_input.tap_nom == na_IntS ? (IntS)0 : transformer_input.tap_nom}, - tap_direction_{tap_max_ > tap_min_ ? (IntS)1 : (IntS)-1}, + tap_nom_{transformer_input.tap_nom == na_IntS ? IntS{0} : transformer_input.tap_nom}, + tap_direction_{tap_max_ > tap_min_ ? IntS{1} : IntS{-1}}, uk_min_{is_nan(transformer_input.uk_min) ? uk_ : transformer_input.uk_min}, uk_max_{is_nan(transformer_input.uk_max) ? uk_ : transformer_input.uk_max}, pk_min_{is_nan(transformer_input.pk_min) ? pk_ : transformer_input.pk_min}, From 60870ad1b76bf5731f23e9708b9e6777a079c95c Mon Sep 17 00:00:00 2001 From: Peter Salemink <66305765+petersalemink95@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:04:59 +0200 Subject: [PATCH 50/66] Update src/power_grid_model/validation/rules.py Co-authored-by: Jerry Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com> Signed-off-by: Peter Salemink <66305765+petersalemink95@users.noreply.github.com> --- src/power_grid_model/validation/rules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/power_grid_model/validation/rules.py b/src/power_grid_model/validation/rules.py index fa23b5d80..8fbef2a83 100644 --- a/src/power_grid_model/validation/rules.py +++ b/src/power_grid_model/validation/rules.py @@ -319,7 +319,7 @@ def outside(val: np.ndarray, *ref: np.ndarray) -> np.ndarray: return np.logical_or(np.less(val, np.minimum(*ref)), np.greater(val, np.maximum(*ref))) return none_match_comparison( - data, component, field, outside, (ref_value_1, ref_value_2), NotBetweenOrAtError, default_value, default_value_2 + data, component, field, outside, (ref_value_1, ref_value_2), NotBetweenOrAtError, default_value_1, default_value_2 ) From 3a506170dc3133169253fbd1a0b54ab49a87dca0 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Thu, 13 Jun 2024 17:12:33 +0200 Subject: [PATCH 51/66] default -> default_1 Signed-off-by: petersalemink95 --- src/power_grid_model/validation/rules.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/power_grid_model/validation/rules.py b/src/power_grid_model/validation/rules.py index 8fbef2a83..a1f629075 100644 --- a/src/power_grid_model/validation/rules.py +++ b/src/power_grid_model/validation/rules.py @@ -286,7 +286,7 @@ def all_between_or_at( # pylint: disable=too-many-arguments field: str, ref_value_1: Union[int, float, str], ref_value_2: Union[int, float, str], - default_value: Optional[Union[np.ndarray, int, float]] = None, + default_value_1: Optional[Union[np.ndarray, int, float]] = None, default_value_2: Optional[Union[np.ndarray, int, float]] = None, ) -> List[NotBetweenOrAtError]: """ @@ -319,7 +319,14 @@ def outside(val: np.ndarray, *ref: np.ndarray) -> np.ndarray: return np.logical_or(np.less(val, np.minimum(*ref)), np.greater(val, np.maximum(*ref))) return none_match_comparison( - data, component, field, outside, (ref_value_1, ref_value_2), NotBetweenOrAtError, default_value_1, default_value_2 + data, + component, + field, + outside, + (ref_value_1, ref_value_2), + NotBetweenOrAtError, + default_value_1, + default_value_2, ) @@ -330,7 +337,7 @@ def none_match_comparison( compare_fn: Callable, ref_value: ComparisonError.RefType, error: Type[CompError] = ComparisonError, # type: ignore - default_value: Optional[Union[np.ndarray, int, float]] = None, + default_value_1: Optional[Union[np.ndarray, int, float]] = None, default_value_2: Optional[Union[np.ndarray, int, float]] = None, ) -> List[CompError]: # pylint: disable=too-many-arguments @@ -358,8 +365,8 @@ def none_match_comparison( A list containing zero or one comparison errors (should be a subclass of ComparisonError), listing all ids where the value in the field of interest matched the comparison. """ - if default_value is not None: - set_default_value(data=data, component=component, field=field, default_value=default_value) + if default_value_1 is not None: + set_default_value(data=data, component=component, field=field, default_value=default_value_1) if default_value_2 is not None: set_default_value(data=data, component=component, field=field, default_value=default_value_2) # if default 2 not None -> set_default_value From 3f9a5d37a9c8f3f809252fdcfe2ee5ade2013f9e Mon Sep 17 00:00:00 2001 From: Peter Salemink <66305765+petersalemink95@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:20:23 +0200 Subject: [PATCH 52/66] Update src/power_grid_model/validation/rules.py Co-authored-by: Martijn Govers Signed-off-by: Peter Salemink <66305765+petersalemink95@users.noreply.github.com> --- src/power_grid_model/validation/rules.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/power_grid_model/validation/rules.py b/src/power_grid_model/validation/rules.py index a1f629075..c15507a8c 100644 --- a/src/power_grid_model/validation/rules.py +++ b/src/power_grid_model/validation/rules.py @@ -369,7 +369,6 @@ def none_match_comparison( set_default_value(data=data, component=component, field=field, default_value=default_value_1) if default_value_2 is not None: set_default_value(data=data, component=component, field=field, default_value=default_value_2) - # if default 2 not None -> set_default_value component_data = data[component] if isinstance(ref_value, tuple): ref = tuple(eval_expression(component_data, v) for v in ref_value) From 0ab9c42ce3851b9ac9c6be17949d04e7c73052c4 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Thu, 13 Jun 2024 17:22:50 +0200 Subject: [PATCH 53/66] rename int8_nan Signed-off-by: petersalemink95 --- tests/unit/validation/test_rules.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/unit/validation/test_rules.py b/tests/unit/validation/test_rules.py index d05540564..c21ee785f 100644 --- a/tests/unit/validation/test_rules.py +++ b/tests/unit/validation/test_rules.py @@ -143,11 +143,11 @@ def test_all_between_or_at(): assert len(errors) == 1 assert NotBetweenOrAtError("test", "value", [1, 4, 5, 6], (0.2, -0.2)) in errors - int8_nan = power_grid_meta_data["input"]["transformer"].nans["tap_pos"] + nan_value = power_grid_meta_data["input"]["transformer"].nans["tap_pos"] transformer_array = initialize_array("input", "transformer", 3) transformer_array["id"] = [1, 2, 3] - transformer_array["tap_pos"] = [int8_nan, 1, int8_nan] - transformer_array["tap_nom"] = [2, 1, int8_nan] + transformer_array["tap_pos"] = [nan_value, 1, nan_value] + transformer_array["tap_nom"] = [2, 1, nan_value] valid = {"transformer": transformer_array} errors = all_between_or_at(valid, "transformer", "tap_pos", 0, 2, transformer_array["tap_nom"], 0) assert not errors @@ -230,11 +230,11 @@ def test_none_match_comparison(): assert len(errors) == 1 assert ComparisonError("test", "value", [2], 0.2) in errors - int8_nan = power_grid_meta_data["input"]["transformer"].nans["tap_pos"] + nan_value = power_grid_meta_data["input"]["transformer"].nans["tap_pos"] transformer_array = initialize_array("input", "transformer", 3) transformer_array["id"] = [1, 2, 3] - transformer_array["tap_pos"] = [int8_nan, 0, int8_nan] - transformer_array["tap_nom"] = [1, 1, int8_nan] + transformer_array["tap_pos"] = [nan_value, 0, nan_value] + transformer_array["tap_nom"] = [1, 1, nan_value] valid = {"transformer": transformer_array} errors = none_match_comparison( From 49b87a047d446c99b50303017ce095490295e3e9 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 17 Jun 2024 14:20:24 +0200 Subject: [PATCH 54/66] minor fix to the fictional grid Signed-off-by: Martijn Govers --- tests/benchmark_cpp/fictional_grid_generator.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/benchmark_cpp/fictional_grid_generator.hpp b/tests/benchmark_cpp/fictional_grid_generator.hpp index 25da2beb7..60393a010 100644 --- a/tests/benchmark_cpp/fictional_grid_generator.hpp +++ b/tests/benchmark_cpp/fictional_grid_generator.hpp @@ -116,7 +116,9 @@ class FictionalGridGenerator { option_.n_mv_feeder = option_.n_lv_grid / option_.n_node_per_mv_feeder + 1; } total_mv_connection = option_.n_mv_feeder * option_.n_node_per_mv_feeder; - option_.ratio_lv_grid = static_cast(option_.n_lv_grid) / static_cast(total_mv_connection); + option_.ratio_lv_grid = total_mv_connection > 0 + ? static_cast(option_.n_lv_grid) / static_cast(total_mv_connection) + : 1.0; // each mv feeder 10 MVA, each transformer 60 MVA, scaled up by 10% option_.n_parallel_hv_mv_transformer = static_cast(static_cast(option.n_mv_feeder) * 10.0 * 1.1 / 60.0) + 1; From d38417b864a8c744e0cd4e17f1b8a68f72e46fe0 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 17 Jun 2024 15:22:14 +0200 Subject: [PATCH 55/66] remove TODO Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordering.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp index 4ffbe9866..6ed1703e6 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp @@ -141,7 +141,7 @@ inline IdxVector remove_vertices_update_degrees(Idx const u, std::map Date: Tue, 18 Jun 2024 12:05:39 +0200 Subject: [PATCH 56/66] minor Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordering.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp index 6ed1703e6..49f837757 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp @@ -84,11 +84,11 @@ inline std::vector> check_indistguishable(Idx co auto l = adj(u, d); auto lu = l; lu.push_back(u); + std::ranges::sort(lu); for (auto const& v : l) { auto lv = adj(v, d); lv.push_back(v); - std::ranges::sort(lu); std::ranges::sort(lv); if (lu == lv) { rl.push_back(v); From 094526ffc09845214d33f3c5c381698e245ea7fb Mon Sep 17 00:00:00 2001 From: Jerry Guo Date: Tue, 18 Jun 2024 13:55:56 +0200 Subject: [PATCH 57/66] remove code smells Signed-off-by: Jerry Guo --- .../component/three_winding_transformer.hpp | 12 ++++++++---- .../power_grid_model/component/transformer.hpp | 10 +++++++--- .../test_three_winding_transformer.cpp | 12 ++++++------ tests/cpp_unit_tests/test_transformer.cpp | 12 ++++++------ 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/three_winding_transformer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/three_winding_transformer.hpp index 5f7cb3b90..0f644b3e6 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/three_winding_transformer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/three_winding_transformer.hpp @@ -42,10 +42,6 @@ class ThreeWindingTransformer : public Branch3 { clock_12_{three_winding_transformer_input.clock_12}, clock_13_{three_winding_transformer_input.clock_13}, tap_side_{three_winding_transformer_input.tap_side}, - tap_pos_{three_winding_transformer_input.tap_pos == na_IntS - ? (three_winding_transformer_input.tap_nom == na_IntS ? IntS{0} - : three_winding_transformer_input.tap_nom) - : three_winding_transformer_input.tap_pos}, tap_min_{three_winding_transformer_input.tap_min}, tap_max_{three_winding_transformer_input.tap_max}, tap_nom_{three_winding_transformer_input.tap_nom == na_IntS ? IntS{0} @@ -82,6 +78,14 @@ class ThreeWindingTransformer : public Branch3 { z_grounding_1_{three_winding_transformer_input.r_grounding_1, three_winding_transformer_input.x_grounding_1}, z_grounding_2_{three_winding_transformer_input.r_grounding_2, three_winding_transformer_input.x_grounding_2}, z_grounding_3_{three_winding_transformer_input.r_grounding_3, three_winding_transformer_input.x_grounding_3} { + // init tap_pos_ linter smell + if (three_winding_transformer_input.tap_pos == na_IntS) { + tap_pos_ = + three_winding_transformer_input.tap_nom == na_IntS ? IntS{0} : three_winding_transformer_input.tap_nom; + } else { + tap_pos_ = three_winding_transformer_input.tap_pos; + } + if (!is_valid_clock(clock_12_, winding_1_, winding_2_)) { throw InvalidTransformerClock{id(), clock_12_}; } diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp index da11f5b67..d3aaddd25 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/transformer.hpp @@ -37,9 +37,6 @@ class Transformer : public Branch { winding_to_{transformer_input.winding_to}, clock_{transformer_input.clock}, tap_side_{transformer_input.tap_side}, - tap_pos_{transformer_input.tap_pos == na_IntS - ? (transformer_input.tap_nom == na_IntS ? IntS{0} : transformer_input.tap_nom) - : transformer_input.tap_pos}, tap_min_{transformer_input.tap_min}, tap_max_{transformer_input.tap_max}, tap_nom_{transformer_input.tap_nom == na_IntS ? IntS{0} : transformer_input.tap_nom}, @@ -55,6 +52,13 @@ class Transformer : public Branch { calculate_z_pu(transformer_input.r_grounding_from, transformer_input.x_grounding_from, u1_rated)}, z_grounding_to_{ calculate_z_pu(transformer_input.r_grounding_to, transformer_input.x_grounding_to, u2_rated)} { + // init tap_pos_ linter smell + if (transformer_input.tap_pos == na_IntS) { + tap_pos_ = transformer_input.tap_nom == na_IntS ? IntS{0} : transformer_input.tap_nom; + } else { + tap_pos_ = transformer_input.tap_pos; + } + if (!is_valid_clock(clock_, winding_from_, winding_to_)) { throw InvalidTransformerClock{id(), clock_}; } diff --git a/tests/cpp_unit_tests/test_three_winding_transformer.cpp b/tests/cpp_unit_tests/test_three_winding_transformer.cpp index 1191ee998..5d96e826a 100644 --- a/tests/cpp_unit_tests/test_three_winding_transformer.cpp +++ b/tests/cpp_unit_tests/test_three_winding_transformer.cpp @@ -586,13 +586,13 @@ TEST_CASE("Test three winding transformer") { SUBCASE("Test optional tap pos/nom") { input.tap_nom = 1; input.tap_pos = na_IntS; - std::vector vec; - vec.emplace_back(input, 138e3, 69e3, 13.8e3); + std::vector trafo_vec; + trafo_vec.emplace_back(input, 138e3, 69e3, 13.8e3); input.tap_nom = na_IntS; - vec.emplace_back(input, 138e3, 69e3, 13.8e3); - CHECK(vec[0].tap_pos() == 1); - CHECK(vec[1].tap_pos() == 0); - CHECK(vec[1].tap_nom() == 0); + trafo_vec.emplace_back(input, 138e3, 69e3, 13.8e3); + CHECK(trafo_vec[0].tap_pos() == 1); + CHECK(trafo_vec[1].tap_pos() == 0); + CHECK(trafo_vec[1].tap_nom() == 0); } } diff --git a/tests/cpp_unit_tests/test_transformer.cpp b/tests/cpp_unit_tests/test_transformer.cpp index 9e5b7d3b5..06c92d0bb 100644 --- a/tests/cpp_unit_tests/test_transformer.cpp +++ b/tests/cpp_unit_tests/test_transformer.cpp @@ -269,13 +269,13 @@ TEST_CASE("Test transformer") { SUBCASE("Test optional tap pos/nom") { input.tap_nom = 1; input.tap_pos = na_IntS; - std::vector vec; - vec.emplace_back(input, 150e3, 10e3); + std::vector trafo_vec; + trafo_vec.emplace_back(input, 150e3, 10e3); input.tap_nom = na_IntS; - vec.emplace_back(input, 150e3, 10e3); - CHECK(vec[0].tap_pos() == 1); - CHECK(vec[1].tap_pos() == 0); - CHECK(vec[1].tap_nom() == 0); + trafo_vec.emplace_back(input, 150e3, 10e3); + CHECK(trafo_vec[0].tap_pos() == 1); + CHECK(trafo_vec[1].tap_pos() == 0); + CHECK(trafo_vec[1].tap_nom() == 0); } } From b38e813a4d084bd444d9a6c2ee8de54214d1472f Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 18 Jun 2024 14:07:42 +0200 Subject: [PATCH 58/66] minor improvements Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordering.hpp | 2 +- .../power_grid_model/include/power_grid_model/topology.hpp | 3 +-- tests/cpp_unit_tests/test_sparse_ordering.cpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp index 49f837757..8d47463f0 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp @@ -172,7 +172,7 @@ inline IdxVector remove_vertices_update_degrees(Idx const u, std::map>> minimum_degree_ordering(std::map& d) { +inline std::pair>> minimum_degree_ordering(std::map d) { auto data = detail::comp_size_degrees_graph(d); auto& [n, dgd] = data[0]; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index ac30029af..88b82af6c 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -15,7 +15,6 @@ #include #include #include -#include // build topology of the grid // divide grid into several math models @@ -324,7 +323,7 @@ class Topology { } } - auto [reordered, fills] = minimum_degree_ordering(unique_nearest_neighbours); + auto [reordered, fills] = minimum_degree_ordering(std::move(unique_nearest_neighbours)); const auto n_non_cyclic_nodes = static_cast(dfs_node.size()); auto const permuted_node_idx = [n_non_cyclic_nodes, &reordered_ = reordered](Idx node_idx) { diff --git a/tests/cpp_unit_tests/test_sparse_ordering.cpp b/tests/cpp_unit_tests/test_sparse_ordering.cpp index d88328ff6..16c81eb43 100644 --- a/tests/cpp_unit_tests/test_sparse_ordering.cpp +++ b/tests/cpp_unit_tests/test_sparse_ordering.cpp @@ -20,7 +20,7 @@ TEST_CASE("Test sparse ordering") { {4, {6, 8}}, {6, {7, 8, 9}}, {7, {8, 9}}, {8, {9}}}; auto const start = std::chrono::high_resolution_clock::now(); - auto const [alpha, fills] = power_grid_model::minimum_degree_ordering(graph); + auto const [alpha, fills] = power_grid_model::minimum_degree_ordering(std::move(graph)); auto const stop = std::chrono::high_resolution_clock::now(); auto const duration = duration_cast(stop - start); From c97877470b46ab10705e5f2888b6755aaef2cfb3 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 18 Jun 2024 16:14:48 +0200 Subject: [PATCH 59/66] significant improvements to sparse ordering Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordering.hpp | 89 ++++++++----------- tests/benchmark_cpp/benchmark.cpp | 70 +++++++-------- tests/cpp_unit_tests/test_sparse_ordering.cpp | 2 +- tests/cpp_unit_tests/test_topology.cpp | 18 ++-- 4 files changed, 83 insertions(+), 96 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp index 8d47463f0..ff847d6b2 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp @@ -7,6 +7,7 @@ #include "common/common.hpp" #include +#include #include #include #include @@ -14,63 +15,47 @@ namespace power_grid_model { namespace detail { -inline void remove_element_vector_pair(Idx u, std::vector>& dgd) { +inline void remove_element_degree(Idx u, std::vector>& dgd) { std::erase_if(dgd, [u](auto const& v) { return v.first == u; }); } -inline void set_element_vector_pair(Idx u, Idx v, std::vector>& dgd) { +inline void set_element_degree(Idx u, Idx degree, std::vector>& dgd) { if (auto it = std::ranges::find_if(dgd, [u](auto const& value) { return value.first == u; }); it != dgd.end()) { - it->second = v; + it->second = degree; } } -inline IdxVector adj(Idx const u, std::map const& d) { - IdxVector l; - - for (const auto& [k, adjacent] : d) { - if (k == u) { - l.insert(l.end(), adjacent.cbegin(), adjacent.cend()); - } else if (std::ranges::find(adjacent, u) != adjacent.cend()) { - l.push_back(k); - } +inline Idx num_adjacent(Idx const u, std::map const& d) { + if (auto it = d.find(u); it != d.end()) { + return static_cast(it->second.size()); } - - return l; + return 0; } +inline IdxVector const& adj(Idx const u, std::map const& d) { return d.at(u); } + inline std::vector>>> comp_size_degrees_graph(std::map const& d) { std::vector> dd; IdxVector v; - Idx n = 0; for (auto const& [k, adjacent] : d) { - if (std::ranges::find(v, k) == v.end()) { - ++n; - v.push_back(k); - dd.emplace_back(k, adj(k, d).size()); - } - for (Idx const e : adjacent) { - if (std::ranges::find(v, e) == v.end()) { - ++n; - v.push_back(e); - dd.emplace_back(e, adj(e, d).size()); - } - } + v.push_back(k); + dd.emplace_back(k, adjacent.size()); } std::ranges::sort(dd); - return {{n, dd}}; + return {{d.size(), dd}}; } inline std::map make_clique(IdxVector& l) { std::map d; - for (Idx i = 0; i < static_cast(l.size()) - 1; i++) { - Idx const idx = i + 1; - IdxVector sl(l.size() - idx); - std::copy(l.begin() + idx, l.end(), sl.begin()); + for (Idx i = 0; i < static_cast(l.size()); i++) { + IdxVector sl(l.size() - 1); + std::copy(l.begin(), l.begin() + i, sl.begin()); + std::copy(l.begin() + i + 1, l.end(), sl.begin() + i); d[l[i]] = std::move(sl); } @@ -103,10 +88,6 @@ inline bool in_graph(std::pair const& e, std::map cons edges_it != d.cend() && std::ranges::find(edges_it->second, e.second) != edges_it->second.cend()) { return true; } - if (auto edges_it = d.find(e.second); - edges_it != d.cend() && std::ranges::find(edges_it->second, e.first) != edges_it->second.cend()) { - return true; - } return false; } @@ -125,7 +106,7 @@ inline IdxVector remove_vertices_update_degrees(Idx const u, std::mapsecond); - } else if (auto e_it = d.find(e); e_it != d.end()) { - add_element(e, k, e_it->second); - } else { + if (it == d.end()) { std::tie(it, std::ignore) = d.try_emplace(k); - add_element(k, e, it->second); } + it->second.push_back(e); + d[e].push_back(k); + fills.emplace_back(k, e); } } } for (auto const& e : nbs) { - set_element_vector_pair(e, static_cast(adj(e, d).size()), dgd); + set_element_degree(e, num_adjacent(e, d), dgd); } return alpha; } } // namespace detail -inline std::pair>> minimum_degree_ordering(std::map d) { +inline std::pair>> minimum_degree_ordering(std::map d_) { + // make symmetric + auto d = d_; + for (auto& [k, adjacent] : d_) { + for (auto a : adjacent) { + d[a].push_back(k); + } + } + for (auto& [k, adjacent] : d) { + std::ranges::sort(adjacent); + } + auto data = detail::comp_size_degrees_graph(d); auto& [n, dgd] = data[0]; @@ -183,7 +168,9 @@ inline std::pair>> minimum_degree_ord Idx const u = get<0>(*std::ranges::min_element(dgd, [](auto lhs, auto rhs) { return get<1>(lhs) < get<1>(rhs); })); alpha.push_back(u); - if ((d.size() == 1) && d.begin()->second.size() == 1) { + if (d.size() == 2) { + assert(d.begin()->second.size() == 1); + Idx const from = d.begin()->first; Idx const to = d.begin()->second[0]; alpha.push_back(alpha.back() == from ? to : from); diff --git a/tests/benchmark_cpp/benchmark.cpp b/tests/benchmark_cpp/benchmark.cpp index 9065a0d5d..748c11633 100644 --- a/tests/benchmark_cpp/benchmark.cpp +++ b/tests/benchmark_cpp/benchmark.cpp @@ -72,21 +72,21 @@ struct PowerGridBenchmark { run_pf(calculation_method, info); } print(info); - info.clear(); - { - std::cout << "\n*****Run without initialization*****\n"; - Timer const t_total(info, 0000, "Total"); - run_pf(calculation_method, info); - } - print(info); - - if (batch_size > 0) { - info.clear(); - std::cout << "\n*****Run with batch calculation*****\n"; - Timer const t_total(info, 0000, "Total"); - run_pf(calculation_method, info, batch_size, threading); - } - print(info); + // info.clear(); + // { + // std::cout << "\n*****Run without initialization*****\n"; + // Timer const t_total(info, 0000, "Total"); + // run_pf(calculation_method, info); + // } + // print(info); + + // if (batch_size > 0) { + // info.clear(); + // std::cout << "\n*****Run with batch calculation*****\n"; + // Timer const t_total(info, 0000, "Total"); + // run_pf(calculation_method, info, batch_size, threading); + // } + // print(info); std::cout << "\n\n"; } @@ -114,41 +114,41 @@ int main(int /* argc */, char** /* argv */) { power_grid_model::benchmark::PowerGridBenchmark benchmarker{}; power_grid_model::benchmark::Option option{}; -#ifndef NDEBUG - option.n_node_total_specified = 200; - option.n_mv_feeder = 3; - option.n_node_per_mv_feeder = 6; - option.n_lv_feeder = 2; - option.n_connection_per_lv_feeder = 4; - power_grid_model::Idx constexpr batch_size = 10; -#else - option.n_node_total_specified = 1500; +// #ifndef NDEBUG +// option.n_node_total_specified = 200; +// option.n_mv_feeder = 3; +// option.n_node_per_mv_feeder = 6; +// option.n_lv_feeder = 2; +// option.n_connection_per_lv_feeder = 4; +// power_grid_model::Idx constexpr batch_size = 10; +// #else + option.n_node_total_specified = 15000; option.n_mv_feeder = 20; option.n_node_per_mv_feeder = 10; option.n_lv_feeder = 10; option.n_connection_per_lv_feeder = 40; power_grid_model::Idx constexpr batch_size = 1000; -#endif +// #endif // radial option.has_mv_ring = false; option.has_lv_ring = false; - benchmarker.run_benchmark(option, newton_raphson, batch_size); - benchmarker.run_benchmark(option, newton_raphson, batch_size, 6); - benchmarker.run_benchmark(option, linear); - benchmarker.run_benchmark(option, iterative_current); - benchmarker.run_benchmark(option, newton_raphson); - benchmarker.run_benchmark(option, linear); + // benchmarker.run_benchmark(option, newton_raphson, batch_size); + // benchmarker.run_benchmark(option, newton_raphson, batch_size, 6); + // benchmarker.run_benchmark(option, linear); + // benchmarker.run_benchmark(option, iterative_current); + // benchmarker.run_benchmark(option, newton_raphson); + // benchmarker.run_benchmark(option, linear); // benchmarker.run_benchmark(option, iterative_current); // with meshed ring option.has_mv_ring = true; option.has_lv_ring = true; - benchmarker.run_benchmark(option, newton_raphson); + // benchmarker.run_benchmark(option, newton_raphson); benchmarker.run_benchmark(option, linear); - benchmarker.run_benchmark(option, iterative_current); - benchmarker.run_benchmark(option, newton_raphson); - benchmarker.run_benchmark(option, linear); + // benchmarker.run_benchmark(option, iterative_current); + // benchmarker.run_benchmark(option, newton_raphson); + // benchmarker.run_benchmark(option, linear); // benchmarker.run_benchmark(option, iterative_current); return 0; } diff --git a/tests/cpp_unit_tests/test_sparse_ordering.cpp b/tests/cpp_unit_tests/test_sparse_ordering.cpp index 16c81eb43..99c15fd91 100644 --- a/tests/cpp_unit_tests/test_sparse_ordering.cpp +++ b/tests/cpp_unit_tests/test_sparse_ordering.cpp @@ -27,6 +27,6 @@ TEST_CASE("Test sparse ordering") { std::cout << "Time taken by function: " << duration.count() << " microseconds\n"; CHECK(alpha == std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); - CHECK(fills == std::vector>{{3, 5}, {4, 5}, {8, 5}, {6, 5}, {7, 5}}); + CHECK(fills == std::vector>{{3, 5}, {4, 5}, {5, 8}, {5, 6}, {5, 7}}); } } diff --git a/tests/cpp_unit_tests/test_topology.cpp b/tests/cpp_unit_tests/test_topology.cpp index 4b707415a..6a5e8e3a6 100644 --- a/tests/cpp_unit_tests/test_topology.cpp +++ b/tests/cpp_unit_tests/test_topology.cpp @@ -179,7 +179,7 @@ TEST_CASE("Test topology") { {0, 1}, // Topological node 0 has become node 4 in mathematical model (group) 0 {0, 2}, {0, 0}, - {0, 3}, + {0, 4}, // 4 5 6 {1, 2}, // Topological node 4 has become node 2 in mathematical model (group) 1 {1, 3}, @@ -192,7 +192,7 @@ TEST_CASE("Test topology") { {-1, -1}, {-1, -1}, // b0, b1, b2 - {0, 4}, // Branch3 b0 is replaced by a virtual node 3, in mathematical model 0 + {0, 3}, // Branch3 b0 is replaced by a virtual node 3, in mathematical model 0 {-1, -1}, {1, 1}}; comp_coup_ref.source = { @@ -244,12 +244,12 @@ TEST_CASE("Test topology") { MathModelTopology math0; math0.slack_bus = 1; math0.sources_per_bus = {from_dense, {1}, 5}; - math0.branch_bus_idx = {{1, 2}, {1, 3}, {3, -1}, {-1, 0}, {2, 4}, {3, 4}, {0, 4}}; - math0.phase_shift = {0.0, 0.0, 0.0, -1.0, 0.0}; + math0.branch_bus_idx = {{1, 2}, {1, 4}, {4, -1}, {-1, 0}, {2, 3}, {4, 3}, {0, 3}}; + math0.phase_shift = {0.0, 0.0, 0.0, 0.0, -1.0}; math0.load_gens_per_bus = {from_dense, {1, 2}, 5}; math0.load_gen_type = {LoadGenType::const_pq, LoadGenType::const_y}; - math0.shunts_per_bus = {from_dense, {3}, 5}; - math0.voltage_sensors_per_bus = {from_dense, {0, 0, 2, 3}, 5}; + math0.shunts_per_bus = {from_dense, {4}, 5}; + math0.voltage_sensors_per_bus = {from_dense, {0, 0, 2, 4}, 5}; math0.power_sensors_per_bus = {from_dense, {}, 5}; math0.power_sensors_per_source = {from_dense, {}, 1}; math0.power_sensors_per_shunt = {from_dense, {}, 1}; @@ -259,7 +259,7 @@ TEST_CASE("Test topology") { // sensor 0 is connected to branch 0 // sensor 1 and 2 are connected to branch 1 math0.power_sensors_per_branch_to = {from_dense, {0, 1, 1}, 7}; - math0.fill_in = {{3, 2}}; + math0.fill_in = {{2, 4}}; // Sub graph / math model 1 MathModelTopology math1; @@ -349,7 +349,7 @@ TEST_CASE("Test cycle reorder") { // result TopologicalComponentToMathCoupling comp_coup_ref{}; comp_coup_ref.node = {{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}, {0, 9}}; - std::vector const fill_in_ref{{5, 3}, {4, 5}, {5, 8}, {6, 5}, {5, 7}}; + std::vector const fill_in_ref{{3, 5}, {4, 5}, {5, 8}, {5, 6}, {5, 7}}; Topology topo{comp_topo, comp_conn}; auto pair = topo.build_topology(); @@ -395,7 +395,7 @@ TEST_CASE("Test cycle reorder") { // result TopologicalComponentToMathCoupling comp_coup_ref{}; comp_coup_ref.node = {{0, 0}, {0, 3}, {0, 1}, {0, 2}, {0, 4}, {0, 5}, {0, 6}}; - std::vector const fill_in_ref{{5, 6}, {2, 6}, {6, 4}}; + std::vector const fill_in_ref{{5, 6}, {2, 6}, {4, 6}}; Topology topo{comp_topo, comp_conn}; auto pair = topo.build_topology(); From 36afc79db8cd04402db2c28c4cdd28ee7e3848f3 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 19 Jun 2024 10:47:57 +0200 Subject: [PATCH 60/66] major speedup in obtaining minimum degree vertex Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordering.hpp | 70 ++++++++++++++----- tests/benchmark_cpp/benchmark.cpp | 20 +++--- 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp index ff847d6b2..9c189e590 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp @@ -8,23 +8,59 @@ #include #include +#include #include +#include #include #include namespace power_grid_model { namespace detail { -inline void remove_element_degree(Idx u, std::vector>& dgd) { - std::erase_if(dgd, [u](auto const& v) { return v.first == u; }); -} +class DegreeLookup { + public: + void set(Idx u, Idx degree) { + if (auto it = vertex_to_degree.find(u); it != vertex_to_degree.end()) { + degrees_to_vertex[it->second].erase(u); + it->second = degree; + } else { + vertex_to_degree.try_emplace(u, degree); + } + degrees_to_vertex[degree].insert(u); + } -inline void set_element_degree(Idx u, Idx degree, std::vector>& dgd) { - if (auto it = std::ranges::find_if(dgd, [u](auto const& value) { return value.first == u; }); it != dgd.end()) { - it->second = degree; + void erase(Idx u) { + auto vertex_it = vertex_to_degree.find(u); + if (vertex_it == vertex_to_degree.end()) { + return; + } + Idx const degree = vertex_it->second; + vertex_to_degree.erase(vertex_it); + + if (auto degree_it = degrees_to_vertex.find(degree); degree_it != degrees_to_vertex.end()) { + degree_it->second.erase(u); + if (degree_it->second.empty()) { + degrees_to_vertex.erase(degree_it); + } + } } + + friend auto min_element(DegreeLookup const& dgd); + + private: + std::map> degrees_to_vertex; + std::map vertex_to_degree; +}; + +inline auto min_element(DegreeLookup const& dgd) { + Idx const vertex = *dgd.degrees_to_vertex.begin()->second.begin(); + return dgd.vertex_to_degree.find(vertex); } +inline void remove_element_degree(Idx u, DegreeLookup& dgd) { dgd.erase(u); } + +inline void set_element_degree(Idx u, Idx degree, DegreeLookup& dgd) { dgd.set(u, degree); } + inline Idx num_adjacent(Idx const u, std::map const& d) { if (auto it = d.find(u); it != d.end()) { return static_cast(it->second.size()); @@ -34,18 +70,15 @@ inline Idx num_adjacent(Idx const u, std::map const& d) { inline IdxVector const& adj(Idx const u, std::map const& d) { return d.at(u); } -inline std::vector>>> -comp_size_degrees_graph(std::map const& d) { - std::vector> dd; +inline std::vector> comp_size_degrees_graph(std::map const& d) { + DegreeLookup dd; IdxVector v; for (auto const& [k, adjacent] : d) { v.push_back(k); - dd.emplace_back(k, adjacent.size()); + set_element_degree(k, adjacent.size(), dd); } - std::ranges::sort(dd); - return {{d.size(), dd}}; } @@ -91,8 +124,7 @@ inline bool in_graph(std::pair const& e, std::map cons return false; } -inline IdxVector remove_vertices_update_degrees(Idx const u, std::map& d, - std::vector>& dgd, +inline IdxVector remove_vertices_update_degrees(Idx const u, std::map& d, DegreeLookup& dgd, std::vector>& fills) { std::vector> nbsrl = check_indistguishable(u, d); auto& [nbs, rl] = nbsrl[0]; @@ -108,9 +140,10 @@ inline IdxVector remove_vertices_update_degrees(Idx const u, std::map>> minimum_degree_ord std::vector> fills; for (Idx k = 0; k < n; ++k) { - Idx const u = - get<0>(*std::ranges::min_element(dgd, [](auto lhs, auto rhs) { return get<1>(lhs) < get<1>(rhs); })); + Idx const u = get<0>(*detail::min_element(dgd)); alpha.push_back(u); if (d.size() == 2) { assert(d.begin()->second.size() == 1); diff --git a/tests/benchmark_cpp/benchmark.cpp b/tests/benchmark_cpp/benchmark.cpp index 748c11633..62fbb6fb4 100644 --- a/tests/benchmark_cpp/benchmark.cpp +++ b/tests/benchmark_cpp/benchmark.cpp @@ -114,21 +114,21 @@ int main(int /* argc */, char** /* argv */) { power_grid_model::benchmark::PowerGridBenchmark benchmarker{}; power_grid_model::benchmark::Option option{}; -// #ifndef NDEBUG -// option.n_node_total_specified = 200; -// option.n_mv_feeder = 3; -// option.n_node_per_mv_feeder = 6; -// option.n_lv_feeder = 2; -// option.n_connection_per_lv_feeder = 4; -// power_grid_model::Idx constexpr batch_size = 10; -// #else - option.n_node_total_specified = 15000; + // #ifndef NDEBUG + // option.n_node_total_specified = 200; + // option.n_mv_feeder = 3; + // option.n_node_per_mv_feeder = 6; + // option.n_lv_feeder = 2; + // option.n_connection_per_lv_feeder = 4; + // power_grid_model::Idx constexpr batch_size = 10; + // #else + option.n_node_total_specified = 150000; option.n_mv_feeder = 20; option.n_node_per_mv_feeder = 10; option.n_lv_feeder = 10; option.n_connection_per_lv_feeder = 40; power_grid_model::Idx constexpr batch_size = 1000; -// #endif + // #endif // radial option.has_mv_ring = false; From 07220f51bb97ed701b353a08196f2f801288e340 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Date: Wed, 19 Jun 2024 11:02:36 +0200 Subject: [PATCH 61/66] Added missing component in config file Signed-off-by: Santiago Figueroa --- .../data/dataset_class_maps/dataset_definitions.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/code_generation/data/dataset_class_maps/dataset_definitions.json b/code_generation/data/dataset_class_maps/dataset_definitions.json index 9f38a8ee8..5574337d5 100644 --- a/code_generation/data/dataset_class_maps/dataset_definitions.json +++ b/code_generation/data/dataset_class_maps/dataset_definitions.json @@ -20,6 +20,10 @@ "names": ["transformer"], "class_name": "TransformerInput" }, + { + "names": ["transformer_tap_regulator"], + "class_name": "TransformerTapRegulatorInput" + }, { "names": ["three_winding_transformer"], "class_name": "ThreeWindingTransformerInput" @@ -62,6 +66,10 @@ "names": ["line", "link", "transformer"], "class_name": "BranchOutput" }, + { + "names": ["transformer_tap_regulator"], + "class_name": "TransformerTapRegulatorOutput" + }, { "names": ["three_winding_transformer"], "class_name": "Branch3Output" @@ -104,6 +112,10 @@ "names": ["transformer"], "class_name": "TransformerUpdate" }, + { + "names": ["transformer_tap_regulator"], + "class_name": "TransformerTapRegulatorUpdate" + }, { "names": ["three_winding_transformer"], "class_name": "ThreeWindingTransformerUpdate" From b4595cab3fde2433c0783bb7cf9933039f489e47 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Date: Wed, 19 Jun 2024 11:38:20 +0200 Subject: [PATCH 62/66] Generated code for component: transformer_tap_regulator Signed-off-by: Santiago Figueroa --- .../power_grid_model_c/dataset_definitions.h | 32 +++++++++++++++++++ .../src/dataset_definitions.cpp | 32 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/power_grid_model_c/power_grid_model_c/include/power_grid_model_c/dataset_definitions.h b/power_grid_model_c/power_grid_model_c/include/power_grid_model_c/dataset_definitions.h index 10624ca82..4ebd40e85 100644 --- a/power_grid_model_c/power_grid_model_c/include/power_grid_model_c/dataset_definitions.h +++ b/power_grid_model_c/power_grid_model_c/include/power_grid_model_c/dataset_definitions.h @@ -87,6 +87,17 @@ PGM_API extern PGM_MetaAttribute const* const PGM_def_input_transformer_r_ground PGM_API extern PGM_MetaAttribute const* const PGM_def_input_transformer_x_grounding_from; PGM_API extern PGM_MetaAttribute const* const PGM_def_input_transformer_r_grounding_to; PGM_API extern PGM_MetaAttribute const* const PGM_def_input_transformer_x_grounding_to; +// component transformer_tap_regulator +PGM_API extern PGM_MetaComponent const* const PGM_def_input_transformer_tap_regulator; +// attributes of input transformer_tap_regulator +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_id; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_regulated_object; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_status; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_control_side; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_u_set; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_u_band; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_line_drop_compensation_r; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_line_drop_compensation_x; // component three_winding_transformer PGM_API extern PGM_MetaComponent const* const PGM_def_input_three_winding_transformer; // attributes of input three_winding_transformer @@ -300,6 +311,12 @@ PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_transformer_p_t PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_transformer_q_to; PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_transformer_i_to; PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_transformer_s_to; +// component transformer_tap_regulator +PGM_API extern PGM_MetaComponent const* const PGM_def_sym_output_transformer_tap_regulator; +// attributes of sym_output transformer_tap_regulator +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_transformer_tap_regulator_id; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_transformer_tap_regulator_energized; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_transformer_tap_regulator_tap_pos; // component three_winding_transformer PGM_API extern PGM_MetaComponent const* const PGM_def_sym_output_three_winding_transformer; // attributes of sym_output three_winding_transformer @@ -466,6 +483,12 @@ PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_transformer_p_ PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_transformer_q_to; PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_transformer_i_to; PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_transformer_s_to; +// component transformer_tap_regulator +PGM_API extern PGM_MetaComponent const* const PGM_def_asym_output_transformer_tap_regulator; +// attributes of asym_output transformer_tap_regulator +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_transformer_tap_regulator_id; +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_transformer_tap_regulator_energized; +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_transformer_tap_regulator_tap_pos; // component three_winding_transformer PGM_API extern PGM_MetaComponent const* const PGM_def_asym_output_three_winding_transformer; // attributes of asym_output three_winding_transformer @@ -603,6 +626,15 @@ PGM_API extern PGM_MetaAttribute const* const PGM_def_update_transformer_id; PGM_API extern PGM_MetaAttribute const* const PGM_def_update_transformer_from_status; PGM_API extern PGM_MetaAttribute const* const PGM_def_update_transformer_to_status; PGM_API extern PGM_MetaAttribute const* const PGM_def_update_transformer_tap_pos; +// component transformer_tap_regulator +PGM_API extern PGM_MetaComponent const* const PGM_def_update_transformer_tap_regulator; +// attributes of update transformer_tap_regulator +PGM_API extern PGM_MetaAttribute const* const PGM_def_update_transformer_tap_regulator_id; +PGM_API extern PGM_MetaAttribute const* const PGM_def_update_transformer_tap_regulator_status; +PGM_API extern PGM_MetaAttribute const* const PGM_def_update_transformer_tap_regulator_u_set; +PGM_API extern PGM_MetaAttribute const* const PGM_def_update_transformer_tap_regulator_u_band; +PGM_API extern PGM_MetaAttribute const* const PGM_def_update_transformer_tap_regulator_line_drop_compensation_r; +PGM_API extern PGM_MetaAttribute const* const PGM_def_update_transformer_tap_regulator_line_drop_compensation_x; // component three_winding_transformer PGM_API extern PGM_MetaComponent const* const PGM_def_update_three_winding_transformer; // attributes of update three_winding_transformer diff --git a/power_grid_model_c/power_grid_model_c/src/dataset_definitions.cpp b/power_grid_model_c/power_grid_model_c/src/dataset_definitions.cpp index 250963b82..70bd343b9 100644 --- a/power_grid_model_c/power_grid_model_c/src/dataset_definitions.cpp +++ b/power_grid_model_c/power_grid_model_c/src/dataset_definitions.cpp @@ -76,6 +76,17 @@ PGM_MetaAttribute const* const PGM_def_input_transformer_r_grounding_from = PGM_ PGM_MetaAttribute const* const PGM_def_input_transformer_x_grounding_from = PGM_meta_get_attribute_by_name(nullptr, "input", "transformer", "x_grounding_from"); PGM_MetaAttribute const* const PGM_def_input_transformer_r_grounding_to = PGM_meta_get_attribute_by_name(nullptr, "input", "transformer", "r_grounding_to"); PGM_MetaAttribute const* const PGM_def_input_transformer_x_grounding_to = PGM_meta_get_attribute_by_name(nullptr, "input", "transformer", "x_grounding_to"); +// component transformer_tap_regulator +PGM_MetaComponent const* const PGM_def_input_transformer_tap_regulator = PGM_meta_get_component_by_name(nullptr, "input", "transformer_tap_regulator"); +// attributes of input transformer_tap_regulator +PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_id = PGM_meta_get_attribute_by_name(nullptr, "input", "transformer_tap_regulator", "id"); +PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_regulated_object = PGM_meta_get_attribute_by_name(nullptr, "input", "transformer_tap_regulator", "regulated_object"); +PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_status = PGM_meta_get_attribute_by_name(nullptr, "input", "transformer_tap_regulator", "status"); +PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_control_side = PGM_meta_get_attribute_by_name(nullptr, "input", "transformer_tap_regulator", "control_side"); +PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_u_set = PGM_meta_get_attribute_by_name(nullptr, "input", "transformer_tap_regulator", "u_set"); +PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_u_band = PGM_meta_get_attribute_by_name(nullptr, "input", "transformer_tap_regulator", "u_band"); +PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_line_drop_compensation_r = PGM_meta_get_attribute_by_name(nullptr, "input", "transformer_tap_regulator", "line_drop_compensation_r"); +PGM_MetaAttribute const* const PGM_def_input_transformer_tap_regulator_line_drop_compensation_x = PGM_meta_get_attribute_by_name(nullptr, "input", "transformer_tap_regulator", "line_drop_compensation_x"); // component three_winding_transformer PGM_MetaComponent const* const PGM_def_input_three_winding_transformer = PGM_meta_get_component_by_name(nullptr, "input", "three_winding_transformer"); // attributes of input three_winding_transformer @@ -289,6 +300,12 @@ PGM_MetaAttribute const* const PGM_def_sym_output_transformer_p_to = PGM_meta_ge PGM_MetaAttribute const* const PGM_def_sym_output_transformer_q_to = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "transformer", "q_to"); PGM_MetaAttribute const* const PGM_def_sym_output_transformer_i_to = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "transformer", "i_to"); PGM_MetaAttribute const* const PGM_def_sym_output_transformer_s_to = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "transformer", "s_to"); +// component transformer_tap_regulator +PGM_MetaComponent const* const PGM_def_sym_output_transformer_tap_regulator = PGM_meta_get_component_by_name(nullptr, "sym_output", "transformer_tap_regulator"); +// attributes of sym_output transformer_tap_regulator +PGM_MetaAttribute const* const PGM_def_sym_output_transformer_tap_regulator_id = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "transformer_tap_regulator", "id"); +PGM_MetaAttribute const* const PGM_def_sym_output_transformer_tap_regulator_energized = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "transformer_tap_regulator", "energized"); +PGM_MetaAttribute const* const PGM_def_sym_output_transformer_tap_regulator_tap_pos = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "transformer_tap_regulator", "tap_pos"); // component three_winding_transformer PGM_MetaComponent const* const PGM_def_sym_output_three_winding_transformer = PGM_meta_get_component_by_name(nullptr, "sym_output", "three_winding_transformer"); // attributes of sym_output three_winding_transformer @@ -455,6 +472,12 @@ PGM_MetaAttribute const* const PGM_def_asym_output_transformer_p_to = PGM_meta_g PGM_MetaAttribute const* const PGM_def_asym_output_transformer_q_to = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "transformer", "q_to"); PGM_MetaAttribute const* const PGM_def_asym_output_transformer_i_to = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "transformer", "i_to"); PGM_MetaAttribute const* const PGM_def_asym_output_transformer_s_to = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "transformer", "s_to"); +// component transformer_tap_regulator +PGM_MetaComponent const* const PGM_def_asym_output_transformer_tap_regulator = PGM_meta_get_component_by_name(nullptr, "asym_output", "transformer_tap_regulator"); +// attributes of asym_output transformer_tap_regulator +PGM_MetaAttribute const* const PGM_def_asym_output_transformer_tap_regulator_id = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "transformer_tap_regulator", "id"); +PGM_MetaAttribute const* const PGM_def_asym_output_transformer_tap_regulator_energized = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "transformer_tap_regulator", "energized"); +PGM_MetaAttribute const* const PGM_def_asym_output_transformer_tap_regulator_tap_pos = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "transformer_tap_regulator", "tap_pos"); // component three_winding_transformer PGM_MetaComponent const* const PGM_def_asym_output_three_winding_transformer = PGM_meta_get_component_by_name(nullptr, "asym_output", "three_winding_transformer"); // attributes of asym_output three_winding_transformer @@ -592,6 +615,15 @@ PGM_MetaAttribute const* const PGM_def_update_transformer_id = PGM_meta_get_attr PGM_MetaAttribute const* const PGM_def_update_transformer_from_status = PGM_meta_get_attribute_by_name(nullptr, "update", "transformer", "from_status"); PGM_MetaAttribute const* const PGM_def_update_transformer_to_status = PGM_meta_get_attribute_by_name(nullptr, "update", "transformer", "to_status"); PGM_MetaAttribute const* const PGM_def_update_transformer_tap_pos = PGM_meta_get_attribute_by_name(nullptr, "update", "transformer", "tap_pos"); +// component transformer_tap_regulator +PGM_MetaComponent const* const PGM_def_update_transformer_tap_regulator = PGM_meta_get_component_by_name(nullptr, "update", "transformer_tap_regulator"); +// attributes of update transformer_tap_regulator +PGM_MetaAttribute const* const PGM_def_update_transformer_tap_regulator_id = PGM_meta_get_attribute_by_name(nullptr, "update", "transformer_tap_regulator", "id"); +PGM_MetaAttribute const* const PGM_def_update_transformer_tap_regulator_status = PGM_meta_get_attribute_by_name(nullptr, "update", "transformer_tap_regulator", "status"); +PGM_MetaAttribute const* const PGM_def_update_transformer_tap_regulator_u_set = PGM_meta_get_attribute_by_name(nullptr, "update", "transformer_tap_regulator", "u_set"); +PGM_MetaAttribute const* const PGM_def_update_transformer_tap_regulator_u_band = PGM_meta_get_attribute_by_name(nullptr, "update", "transformer_tap_regulator", "u_band"); +PGM_MetaAttribute const* const PGM_def_update_transformer_tap_regulator_line_drop_compensation_r = PGM_meta_get_attribute_by_name(nullptr, "update", "transformer_tap_regulator", "line_drop_compensation_r"); +PGM_MetaAttribute const* const PGM_def_update_transformer_tap_regulator_line_drop_compensation_x = PGM_meta_get_attribute_by_name(nullptr, "update", "transformer_tap_regulator", "line_drop_compensation_x"); // component three_winding_transformer PGM_MetaComponent const* const PGM_def_update_three_winding_transformer = PGM_meta_get_component_by_name(nullptr, "update", "three_winding_transformer"); // attributes of update three_winding_transformer From 74b9d5299638cfa23bdaf022df0480be6f8329e4 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 19 Jun 2024 13:19:17 +0200 Subject: [PATCH 63/66] improve current most expensive step Signed-off-by: Martijn Govers --- .../power_grid_model/sparse_ordering.hpp | 17 ++++++++++------- .../include/power_grid_model/topology.hpp | 12 ++++++------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp index 9c189e590..0b7c063d2 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp @@ -20,9 +20,9 @@ namespace detail { class DegreeLookup { public: void set(Idx u, Idx degree) { - if (auto it = vertex_to_degree.find(u); it != vertex_to_degree.end()) { - degrees_to_vertex[it->second].erase(u); - it->second = degree; + if (auto degree_it = vertex_to_degree.find(u); degree_it != vertex_to_degree.end()) { + remove_degree(u, degree_it->second); + degree_it->second = degree; } else { vertex_to_degree.try_emplace(u, degree); } @@ -36,7 +36,13 @@ class DegreeLookup { } Idx const degree = vertex_it->second; vertex_to_degree.erase(vertex_it); + remove_degree(u, degree); + } + + friend auto min_element(DegreeLookup const& dgd); + private: + void remove_degree(Idx u, Idx degree) { if (auto degree_it = degrees_to_vertex.find(degree); degree_it != degrees_to_vertex.end()) { degree_it->second.erase(u); if (degree_it->second.empty()) { @@ -45,11 +51,8 @@ class DegreeLookup { } } - friend auto min_element(DegreeLookup const& dgd); - - private: - std::map> degrees_to_vertex; std::map vertex_to_degree; + std::map> degrees_to_vertex; }; inline auto min_element(DegreeLookup const& dgd) { diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp index 88b82af6c..f5d019796 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/topology.hpp @@ -326,15 +326,15 @@ class Topology { auto [reordered, fills] = minimum_degree_ordering(std::move(unique_nearest_neighbours)); const auto n_non_cyclic_nodes = static_cast(dfs_node.size()); - auto const permuted_node_idx = [n_non_cyclic_nodes, &reordered_ = reordered](Idx node_idx) { - return n_non_cyclic_nodes + - narrow_cast(std::distance(reordered_.begin(), std::ranges::find(reordered_, node_idx))); - }; + std::map permuted_node_indices; + for (Idx idx = 0; idx < static_cast(reordered.size()); ++idx) { + permuted_node_indices[reordered[idx]] = n_non_cyclic_nodes + idx; + } std::ranges::copy(reordered, std::back_inserter(dfs_node)); for (auto [from, to] : fills) { - auto from_reordered = permuted_node_idx(from); - auto to_reordered = permuted_node_idx(to); + auto from_reordered = permuted_node_indices[from]; + auto to_reordered = permuted_node_indices[to]; fill_in.push_back({from_reordered, to_reordered}); } From 986a29473a92298f498c7e16512a3164f3c90c4f Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 19 Jun 2024 14:51:39 +0200 Subject: [PATCH 64/66] fix ci Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordering.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp index 0b7c063d2..baf66de88 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp @@ -79,7 +79,7 @@ inline std::vector> comp_size_degrees_graph(std::ma for (auto const& [k, adjacent] : d) { v.push_back(k); - set_element_degree(k, adjacent.size(), dd); + set_element_degree(k, static_cast(adjacent.size()), dd); } return {{d.size(), dd}}; @@ -182,16 +182,16 @@ inline IdxVector remove_vertices_update_degrees(Idx const u, std::map>> minimum_degree_ordering(std::map d_) { +inline std::pair>> minimum_degree_ordering(std::map d) { // make symmetric - auto d = d_; - for (auto& [k, adjacent] : d_) { + for (auto& [k, adjacent] : d) { for (auto a : adjacent) { d[a].push_back(k); } } for (auto& [k, adjacent] : d) { - std::ranges::sort(adjacent); + std::set const unique_sorted_adjacent{adjacent.begin(), adjacent.end()}; + adjacent = IdxVector{unique_sorted_adjacent.begin(), unique_sorted_adjacent.end()}; } auto data = detail::comp_size_degrees_graph(d); From cd55f73125817310e13ba257ab0adcf27511b093 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 19 Jun 2024 15:00:11 +0200 Subject: [PATCH 65/66] fix Signed-off-by: Martijn Govers --- tests/benchmark_cpp/benchmark.cpp | 70 +++++++++++++++---------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/tests/benchmark_cpp/benchmark.cpp b/tests/benchmark_cpp/benchmark.cpp index 62fbb6fb4..9065a0d5d 100644 --- a/tests/benchmark_cpp/benchmark.cpp +++ b/tests/benchmark_cpp/benchmark.cpp @@ -72,21 +72,21 @@ struct PowerGridBenchmark { run_pf(calculation_method, info); } print(info); - // info.clear(); - // { - // std::cout << "\n*****Run without initialization*****\n"; - // Timer const t_total(info, 0000, "Total"); - // run_pf(calculation_method, info); - // } - // print(info); - - // if (batch_size > 0) { - // info.clear(); - // std::cout << "\n*****Run with batch calculation*****\n"; - // Timer const t_total(info, 0000, "Total"); - // run_pf(calculation_method, info, batch_size, threading); - // } - // print(info); + info.clear(); + { + std::cout << "\n*****Run without initialization*****\n"; + Timer const t_total(info, 0000, "Total"); + run_pf(calculation_method, info); + } + print(info); + + if (batch_size > 0) { + info.clear(); + std::cout << "\n*****Run with batch calculation*****\n"; + Timer const t_total(info, 0000, "Total"); + run_pf(calculation_method, info, batch_size, threading); + } + print(info); std::cout << "\n\n"; } @@ -114,41 +114,41 @@ int main(int /* argc */, char** /* argv */) { power_grid_model::benchmark::PowerGridBenchmark benchmarker{}; power_grid_model::benchmark::Option option{}; - // #ifndef NDEBUG - // option.n_node_total_specified = 200; - // option.n_mv_feeder = 3; - // option.n_node_per_mv_feeder = 6; - // option.n_lv_feeder = 2; - // option.n_connection_per_lv_feeder = 4; - // power_grid_model::Idx constexpr batch_size = 10; - // #else - option.n_node_total_specified = 150000; +#ifndef NDEBUG + option.n_node_total_specified = 200; + option.n_mv_feeder = 3; + option.n_node_per_mv_feeder = 6; + option.n_lv_feeder = 2; + option.n_connection_per_lv_feeder = 4; + power_grid_model::Idx constexpr batch_size = 10; +#else + option.n_node_total_specified = 1500; option.n_mv_feeder = 20; option.n_node_per_mv_feeder = 10; option.n_lv_feeder = 10; option.n_connection_per_lv_feeder = 40; power_grid_model::Idx constexpr batch_size = 1000; - // #endif +#endif // radial option.has_mv_ring = false; option.has_lv_ring = false; - // benchmarker.run_benchmark(option, newton_raphson, batch_size); - // benchmarker.run_benchmark(option, newton_raphson, batch_size, 6); - // benchmarker.run_benchmark(option, linear); - // benchmarker.run_benchmark(option, iterative_current); - // benchmarker.run_benchmark(option, newton_raphson); - // benchmarker.run_benchmark(option, linear); + benchmarker.run_benchmark(option, newton_raphson, batch_size); + benchmarker.run_benchmark(option, newton_raphson, batch_size, 6); + benchmarker.run_benchmark(option, linear); + benchmarker.run_benchmark(option, iterative_current); + benchmarker.run_benchmark(option, newton_raphson); + benchmarker.run_benchmark(option, linear); // benchmarker.run_benchmark(option, iterative_current); // with meshed ring option.has_mv_ring = true; option.has_lv_ring = true; - // benchmarker.run_benchmark(option, newton_raphson); + benchmarker.run_benchmark(option, newton_raphson); benchmarker.run_benchmark(option, linear); - // benchmarker.run_benchmark(option, iterative_current); - // benchmarker.run_benchmark(option, newton_raphson); - // benchmarker.run_benchmark(option, linear); + benchmarker.run_benchmark(option, iterative_current); + benchmarker.run_benchmark(option, newton_raphson); + benchmarker.run_benchmark(option, linear); // benchmarker.run_benchmark(option, iterative_current); return 0; } From ca040d566b132bfa352e3bf2a250916e5056bb9f Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Wed, 19 Jun 2024 15:25:12 +0200 Subject: [PATCH 66/66] resolve sonar cloud Signed-off-by: Martijn Govers --- .../include/power_grid_model/sparse_ordering.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp index baf66de88..41c9622fd 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/sparse_ordering.hpp @@ -143,7 +143,7 @@ inline IdxVector remove_vertices_update_degrees(Idx const u, std::map>> minimum_degree_ordering(std::map d) { // make symmetric - for (auto& [k, adjacent] : d) { - for (auto a : adjacent) { - d[a].push_back(k); + for (auto const& [k, adjacent] : d) { + for (auto e : adjacent) { + d[e].push_back(k); } } for (auto& [k, adjacent] : d) {