Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,26 @@ namespace detail {

template <typename Tuple, class Functor, std::size_t... Indices>
constexpr void run_functor_with_tuple_index_return_void(Functor&& functor, std::index_sequence<Indices...> /*unused*/) {
(std::forward<Functor>(functor).template operator()<std::tuple_element_t<Indices, Tuple>>(), ...);
if constexpr (sizeof...(Indices) == 1) {
(std::forward<Functor>(functor).template operator()<std::tuple_element_t<Indices, Tuple>>(), ...);
} else {
(functor.template operator()<std::tuple_element_t<Indices, Tuple>>(), ...);
capturing::into_the_void(std::forward<Functor>(functor));
Comment on lines +18 to +19
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i did try to see whether i could make this of the form

        functor.template operator()<std::tuple_element_t<A, Tuple>>();
        functor.template operator()<std::tuple_element_t<B, Tuple>>();
        ...
        std::forward<Functor>.template operator()<std::tuple_element_t<Last, Tuple>>();

but that turned out to be too difficult (tried multiple things but there's no nice way to do things.... only ugly ones)

}
}

template <typename Tuple, class Functor, std::size_t... Indices>
constexpr auto run_functor_with_tuple_index_return_array(Functor&& functor,
std::index_sequence<Indices...> /*unused*/) {
if constexpr (sizeof...(Indices) == 1) {
return std::array {
std::forward<Functor>(functor).template operator()<std::tuple_element_t<Indices, Tuple>>()...
};
} else {
auto result = std::array { functor.template operator()<std::tuple_element_t<Indices, Tuple>>()... };
capturing::into_the_void(std::forward<Functor>(functor));
return result;
}
}

} // namespace detail
Expand All @@ -25,4 +44,9 @@ template <typename Tuple, class Functor> constexpr void run_functor_with_tuple_r
std::make_index_sequence<std::tuple_size_v<Tuple>>{});
}

template <typename Tuple, class Functor> constexpr auto run_functor_with_tuple_return_array(Functor&& functor) {
return detail::run_functor_with_tuple_index_return_array<Tuple>(
std::forward<Functor>(functor), std::make_index_sequence<std::tuple_size_v<Tuple>>{});
}

} // namespace power_grid_model::main_core::utils
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ concept validate_component_types_c =

template <class T, class U> class MainModelType;

// TODO: discussion on checking dependent types can also be done here.
template <class... ExtraRetrievableType, class... ComponentType>
requires detail::validate_component_types_c<ComponentList<ComponentType...>>
class MainModelType<ExtraRetrievableTypes<ExtraRetrievableType...>, ComponentList<ComponentType...>> {
Expand Down Expand Up @@ -111,11 +110,11 @@ class MainModelType<ExtraRetrievableTypes<ExtraRetrievableType...>, ComponentLis
using ComponentFlags = std::array<bool, n_types>;

template <class Functor> static constexpr void run_functor_with_all_component_types_return_void(Functor&& functor) {
(std::forward<Functor>(functor).template operator()<ComponentType>(), ...);
return utils::run_functor_with_tuple_return_void<ComponentTypesTuple>(std::forward<Functor>(functor));
}
template <class Functor>
static constexpr auto run_functor_with_all_component_types_return_array(Functor&& functor) {
return std::array { std::forward<Functor>(functor).template operator()<ComponentType>()... };
return utils::run_functor_with_tuple_return_array<ComponentTypesTuple>(std::forward<Functor>(functor));
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ ObservabilitySensorsResult scan_network_sensors(MeasuredValues<sym> const& measu
// we only need one flow sensor, so the loop will break
Idx const branch = element.idx;
Idx const neighbour_bus = y_bus_structure.col_indices[ybus_index];
BusNeighbourhoodInfo::neighbour const neighbour_info{neighbour_bus,
ConnectivityStatus::has_no_measurement};
BusNeighbourhoodInfo::neighbour const neighbour_info{.bus = neighbour_bus,
.status = ConnectivityStatus::has_no_measurement};
bus_neighbourhood_info[bus].direct_neighbours.push_back(neighbour_info);
if (has_flow_sensor(branch) && is_branch_connected(branch)) {
result.flow_sensors[ybus_index] = 1;
Expand Down Expand Up @@ -231,7 +231,7 @@ inline void complete_bidirectional_neighbourhood_info(std::vector<BusNeighbourho
auto it = std::ranges::find_if(
reverse_neighbour_list, [&bus](auto const& reverse_neighbour) { return reverse_neighbour.bus == bus; });
if (it == reverse_neighbour_list.end()) {
BusNeighbourhoodInfo::neighbour const reverse_neighbour_info{bus, neighbour.status};
BusNeighbourhoodInfo::neighbour const reverse_neighbour_info{.bus = bus, .status = neighbour.status};
reverse_neighbour_list.push_back(reverse_neighbour_info);
}
}
Expand Down
18 changes: 11 additions & 7 deletions tests/cpp_unit_tests/test_observability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,8 @@ TEST_CASE("Test Observability - complete_bidirectional_neighbourhood_info") {
// Initialize test data
neighbour_list[0].bus = 0;
neighbour_list[0].status = has_no_measurement;
neighbour_list[0].direct_neighbours = {{1, has_no_measurement}, {2, node_measured}};
neighbour_list[0].direct_neighbours = {{.bus = 1, .status = has_no_measurement},
{.bus = 2, .status = node_measured}};

neighbour_list[1].bus = 1;
neighbour_list[1].status = node_measured;
Expand Down Expand Up @@ -615,17 +616,18 @@ TEST_CASE("Test Observability - complete_bidirectional_neighbourhood_info") {
// Bus 0 connects to buses 1 and 3
neighbour_list[0].bus = 0;
neighbour_list[0].status = node_measured;
neighbour_list[0].direct_neighbours = {{1, branch_native_measurement_unused}, {3, has_no_measurement}};
neighbour_list[0].direct_neighbours = {{.bus = 1, .status = branch_native_measurement_unused},
{.bus = 3, .status = has_no_measurement}};

// Bus 1 connects to bus 2 (but not back to 0 yet)
neighbour_list[1].bus = 1;
neighbour_list[1].status = has_no_measurement;
neighbour_list[1].direct_neighbours = {{2, branch_discovered_with_from_node_sensor}};
neighbour_list[1].direct_neighbours = {{.bus = 2, .status = branch_discovered_with_from_node_sensor}};

// Bus 2 has existing connection to bus 3
neighbour_list[2].bus = 2;
neighbour_list[2].status = branch_discovered_with_to_node_sensor;
neighbour_list[2].direct_neighbours = {{3, branch_native_measurement_consumed}};
neighbour_list[2].direct_neighbours = {{.bus = 3, .status = branch_native_measurement_consumed}};

// Bus 3 initially has no connections
neighbour_list[3].bus = 3;
Expand Down Expand Up @@ -700,15 +702,17 @@ TEST_CASE("Test Observability - complete_bidirectional_neighbourhood_info") {
// Initialize with some connections already bidirectional
neighbour_list[0].bus = 0;
neighbour_list[0].status = has_no_measurement;
neighbour_list[0].direct_neighbours = {{1, has_no_measurement}, {2, node_measured}};
neighbour_list[0].direct_neighbours = {{.bus = 1, .status = has_no_measurement},
{.bus = 2, .status = node_measured}};

neighbour_list[1].bus = 1;
neighbour_list[1].status = node_measured;
neighbour_list[1].direct_neighbours = {{0, has_no_measurement}, {2, branch_native_measurement_unused}};
neighbour_list[1].direct_neighbours = {{.bus = 0, .status = has_no_measurement},
{.bus = 2, .status = branch_native_measurement_unused}};

neighbour_list[2].bus = 2;
neighbour_list[2].status = node_measured;
neighbour_list[2].direct_neighbours = {{1, branch_native_measurement_unused}};
neighbour_list[2].direct_neighbours = {{.bus = 1, .status = branch_native_measurement_unused}};

// Test the function
complete_bidirectional_neighbourhood_info(neighbour_list);
Expand Down
33 changes: 19 additions & 14 deletions tests/cpp_unit_tests/test_y_bus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,13 +434,13 @@ TEST_CASE("Test counting_sort_element") {
SUBCASE("Test basic sorting") {
// Create test data: elements at various matrix positions
std::vector<YBusElementMap> vec = {
{{2, 1}, {bft, 5}}, // pos (2,1)
{{0, 0}, {bff, 0}}, // pos (0,0)
{{1, 2}, {btf, 3}}, // pos (1,2)
{{0, 1}, {bft, 1}}, // pos (0,1)
{{2, 1}, {shunt, 6}}, // pos (2,1) - same position as first
{{1, 0}, {btf, 2}}, // pos (1,0)
{{2, 2}, {btt, 7}}, // pos (2,2)
{.pos = {2, 1}, .element = {.element_type = bft, .idx = 5}}, // pos (2,1)
{.pos = {0, 0}, .element = {.element_type = bff, .idx = 0}}, // pos (0,0)
{.pos = {1, 2}, .element = {.element_type = btf, .idx = 3}}, // pos (1,2)
{.pos = {0, 1}, .element = {.element_type = bft, .idx = 1}}, // pos (0,1)
{.pos = {2, 1}, .element = {.element_type = shunt, .idx = 6}}, // pos (2,1) - same position as first
{.pos = {1, 0}, .element = {.element_type = btf, .idx = 2}}, // pos (1,0)
{.pos = {2, 2}, .element = {.element_type = btt, .idx = 7}}, // pos (2,2)
};

// Expected sorted order: by row first, then by column
Expand All @@ -465,7 +465,7 @@ TEST_CASE("Test counting_sort_element") {
}

SUBCASE("Test with single bus") {
std::vector<YBusElementMap> vec = {{{0, 0}, {shunt, 10}}};
std::vector<YBusElementMap> vec = {{.pos = {0, 0}, .element = {.element_type = shunt, .idx = 10}}};

counting_sort_element(vec, 1);

Expand All @@ -483,9 +483,9 @@ TEST_CASE("Test counting_sort_element") {

SUBCASE("Test stability - elements with same position maintain relative order") {
std::vector<YBusElementMap> vec = {
{{1, 1}, {bff, 100}},
{{1, 1}, {bft, 200}},
{{1, 1}, {shunt, 300}},
{.pos = {1, 1}, .element = {.element_type = bff, .idx = 100}},
{.pos = {1, 1}, .element = {.element_type = bft, .idx = 200}},
{.pos = {1, 1}, .element = {.element_type = shunt, .idx = 300}},
};

counting_sort_element(vec, 2);
Expand All @@ -510,7 +510,7 @@ TEST_CASE("Test counting_sort_element") {
Idx const row = i / n_bus;
Idx const col = i % n_bus;
if ((row + col) % 3 == 0) { // Sparse pattern
vec.push_back({{row, col}, {bff, row * n_bus + col}});
vec.push_back({.pos = {row, col}, .element = {.element_type = bff, .idx = row * n_bus + col}});
}
}

Expand All @@ -535,8 +535,13 @@ TEST_CASE("Test counting_sort_element") {

SUBCASE("Test all YBusElementType values") {
std::vector<YBusElementMap> vec = {
{{1, 1}, {fill_in_tf, 6}}, {{0, 1}, {bft, 1}}, {{1, 0}, {btf, 2}}, {{0, 0}, {bff, 0}},
{{1, 1}, {btt, 3}}, {{2, 2}, {shunt, 4}}, {{1, 2}, {fill_in_ft, 5}},
{.pos = {1, 1}, .element = {.element_type = fill_in_tf, .idx = 6}},
{.pos = {0, 1}, .element = {.element_type = bft, .idx = 1}},
{.pos = {1, 0}, .element = {.element_type = btf, .idx = 2}},
{.pos = {0, 0}, .element = {.element_type = bff, .idx = 0}},
{.pos = {1, 1}, .element = {.element_type = btt, .idx = 3}},
{.pos = {2, 2}, .element = {.element_type = shunt, .idx = 4}},
{.pos = {1, 2}, .element = {.element_type = fill_in_ft, .idx = 5}},
};

counting_sort_element(vec, 3);
Expand Down
Loading