From 3fcbb47f1be7d9e828e3482f6458bd7d018ebec9 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Thu, 5 Sep 2024 13:30:30 +0200 Subject: [PATCH 1/9] add columnar input data support to main model Signed-off-by: Martijn Govers --- .../power_grid_model/main_core/input.hpp | 7 +- .../power_grid_model/main_model_impl.hpp | 12 ++- .../cpp_integration_tests/test_main_model.cpp | 84 +++++++++++++++++++ 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/input.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/input.hpp index c604880b8..c2afebd57 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/input.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/input.hpp @@ -19,16 +19,19 @@ constexpr std::array const branch3_sides = {Branch3Side::side_1, // template to construct components // using forward interators // different selection based on component type -template Component, class ComponentContainer, std::forward_iterator ForwardIterator> +template Component, class ComponentContainer, typename ForwardIterator> requires model_component_state_c inline void add_component(MainModelState& state, ForwardIterator begin, ForwardIterator end, double system_frequency) { + using ComponentView = std::conditional_t, + typename Component::InputType const&, typename Component::InputType>; + reserve_component(state, std::distance(begin, end)); // do sanity check on the transformer tap regulator std::vector regulated_objects; // loop to add component for (auto it = begin; it != end; ++it) { - auto const& input = *it; + ComponentView input = *it; ID const id = input.id; // construct based on type of component if constexpr (std::derived_from) { diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp index 45dd6366c..61c1c5d34 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp @@ -200,11 +200,15 @@ class MainModelImpl, ComponentLis template void add_component(std::span components) { add_component(components.begin(), components.end()); } + template + void add_component(ConstDataset::RangeObject components) { + add_component(components.begin(), components.end()); + } // template to construct components // using forward interators // different selection based on component type - template CompType, std::forward_iterator ForwardIterator> + template CompType, typename ForwardIterator> void add_component(ForwardIterator begin, ForwardIterator end) { assert(!construction_complete_); main_core::add_component(state_, begin, end, system_frequency_); @@ -212,7 +216,11 @@ class MainModelImpl, ComponentLis void add_components(ConstDataset const& input_data, Idx pos = 0) { auto const add_func = [this, pos, &input_data]() { - this->add_component(input_data.get_buffer_span(pos)); + if (input_data.is_columnar(CT::name)) { + this->add_component(input_data.get_columnar_buffer_span(pos)); + } else { + this->add_component(input_data.get_buffer_span(pos)); + } }; run_functor_with_all_types_return_void(add_func); } diff --git a/tests/cpp_integration_tests/test_main_model.cpp b/tests/cpp_integration_tests/test_main_model.cpp index 891e1585b..85960005c 100644 --- a/tests/cpp_integration_tests/test_main_model.cpp +++ b/tests/cpp_integration_tests/test_main_model.cpp @@ -1229,6 +1229,90 @@ TEST_CASE("Test main model - runtime dispatch") { CHECK(sym_node_2[7].u_pu == doctest::Approx(0.67).epsilon(0.005)); CHECK(sym_node_2[8].u_pu == doctest::Approx(0.67).epsilon(0.005)); } + + SUBCASE("Columnar buffers in dataset") { + auto const options = get_default_options(symmetric, CalculationMethod::newton_raphson); + + SUBCASE("Columnar buffers in input data") { + std::vector node_ids; + std::vector node_u_rated; + std::ranges::transform(state.node_input, std::back_inserter(node_ids), + [](auto const& node) { return node.id; }); + std::ranges::transform(state.node_input, std::back_inserter(node_u_rated), + [](auto const& node) { return node.u_rated; }); + REQUIRE(node_ids.size() == node_u_rated.size()); + + ConstDataset input_data_with_columns{false, 1, "input", meta_data::meta_data_gen::meta_data}; + input_data_with_columns.add_buffer("node", state.node_input.size(), state.node_input.size(), nullptr, + nullptr); + input_data_with_columns.add_attribute_buffer("node", "id", node_ids.data()); + input_data_with_columns.add_attribute_buffer("node", "u_rated", node_u_rated.data()); + input_data_with_columns.add_buffer("line", state.line_input.size(), state.line_input.size(), nullptr, + state.line_input.data()); + input_data_with_columns.add_buffer("link", state.link_input.size(), state.link_input.size(), nullptr, + state.link_input.data()); + input_data_with_columns.add_buffer("source", state.source_input.size(), state.source_input.size(), nullptr, + state.source_input.data()); + input_data_with_columns.add_buffer("sym_load", state.sym_load_input.size(), state.sym_load_input.size(), + nullptr, state.sym_load_input.data()); + input_data_with_columns.add_buffer("asym_load", state.asym_load_input.size(), state.asym_load_input.size(), + nullptr, state.asym_load_input.data()); + input_data_with_columns.add_buffer("shunt", state.shunt_input.size(), state.shunt_input.size(), nullptr, + state.shunt_input.data()); + + MainModel row_based_model{50.0, input_data}; + MainModel columnar_model{50.0, input_data_with_columns}; + + std::vector node_output_from_row_based(state.node_input.size()); + std::vector node_output_from_columnar(node_ids.size()); + + MutableDataset sym_output_from_row_based{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; + sym_output_from_row_based.add_buffer("node", node_output_from_row_based.size(), + node_output_from_row_based.size(), nullptr, + node_output_from_row_based.data()); + MutableDataset sym_output_from_columnar{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; + sym_output_from_columnar.add_buffer("node", node_output_from_columnar.size(), + node_output_from_columnar.size(), nullptr, + node_output_from_columnar.data()); + + row_based_model.calculate(options, sym_output_from_row_based); + columnar_model.calculate(options, sym_output_from_columnar); + + REQUIRE(node_output_from_row_based.size() == node_output_from_columnar.size()); + + for (Idx idx = 0; idx < std::ssize(node_output_from_row_based); ++idx) { + CHECK(node_output_from_row_based[idx].id == node_output_from_columnar[idx].id); + CHECK(node_output_from_row_based[idx].u_pu == node_output_from_columnar[idx].u_pu); + } + } + SUBCASE("Columnar buffers in output data") { + MainModel model{50.0, input_data}; + + std::vector row_based_node_output(state.node_input.size()); + std::vector columnar_node_output_id(state.node_input.size()); + std::vector columnar_node_output_u_pu(state.node_input.size()); + + MutableDataset row_based_sym_output{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; + row_based_sym_output.add_buffer("node", row_based_node_output.size(), row_based_node_output.size(), nullptr, + row_based_node_output.data()); + MutableDataset columnar_sym_output{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; + columnar_sym_output.add_buffer("node", row_based_node_output.size(), row_based_node_output.size(), nullptr, + nullptr); + columnar_sym_output.add_attribute_buffer("node", "id", columnar_node_output_id.data()); + columnar_sym_output.add_attribute_buffer("node", "u_pu", columnar_node_output_u_pu.data()); + + model.calculate(options, row_based_sym_output); + model.calculate(options, columnar_sym_output); + + REQUIRE(row_based_node_output.size() == columnar_node_output_id.size()); + REQUIRE(row_based_node_output.size() == columnar_node_output_u_pu.size()); + + for (Idx idx = 0; idx < std::ssize(row_based_node_output); ++idx) { + CHECK(row_based_node_output[idx].id == columnar_node_output_id[idx]); + CHECK(row_based_node_output[idx].u_pu == columnar_node_output_u_pu[idx]); + } + } + } } namespace { From 93936159b79441f09684c645f1781d781fcf08e1 Mon Sep 17 00:00:00 2001 From: Jerry Guo Date: Thu, 5 Sep 2024 15:43:16 +0200 Subject: [PATCH 2/9] added columnar support for output Signed-off-by: Jerry Guo --- .../power_grid_model/main_core/output.hpp | 33 ++++++++++--------- .../power_grid_model/main_model_impl.hpp | 27 ++++++++++++--- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/output.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/output.hpp index 2e6948d4c..8b8766732 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/output.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/output.hpp @@ -13,6 +13,9 @@ namespace power_grid_model::main_core { namespace detail { +template +concept assignable_to = std::assignable_from; + template Component, class ComponentContainer> requires model_component_state_c constexpr auto comp_base_sequence_cbegin(MainModelState const& state) { @@ -75,12 +78,11 @@ constexpr auto comp_base_sequence_cbegin(MainModelState cons return state.comp_topo->regulated_object_idx.cbegin() + get_component_sequence_offset(state); } -template +template requires model_component_state_c && std::invocable, Component const&, IndexType> && - std::convertible_to, - std::iter_value_t> && + assignable_to, + std::add_lvalue_reference_t>> && std::convertible_to(MainModelState{}))> constexpr ResIt produce_output(MainModelState const& state, ResIt res_it, ResFunc&& func) { @@ -359,12 +361,12 @@ output_result(Component const& transformer_tap_regulator, MainModelState Component, class ComponentContainer, solver_output_type SolverOutputType, - std::forward_iterator ResIt> + typename ResIt> requires model_component_state_c && requires(Component const& component, std::vector const& solver_output, Idx2D math_id) { { output_result(component, solver_output, math_id) - } -> std::convertible_to>; + } -> detail::assignable_to>>; } constexpr ResIt output_result(MainModelState const& state, MathOutput> const& math_output, ResIt res_it) { @@ -374,13 +376,13 @@ constexpr ResIt output_result(MainModelState const& state, }); } template Component, class ComponentContainer, solver_output_type SolverOutputType, - std::forward_iterator ResIt> + typename ResIt> requires model_component_state_c && requires(Component const& component, MainModelState const& state, std::vector const& solver_output, Idx2D math_id) { { output_result(component, state, solver_output, math_id) - } -> std::convertible_to>; + } -> detail::assignable_to>>; } constexpr ResIt output_result(MainModelState const& state, MathOutput> const& math_output, ResIt res_it) { @@ -390,13 +392,13 @@ constexpr ResIt output_result(MainModelState const& state, }); } template Component, class ComponentContainer, solver_output_type SolverOutputType, - std::forward_iterator ResIt> + typename ResIt> requires model_component_state_c && requires(Component const& component, MainModelState const& state, std::vector const& solver_output, Idx obj_seq) { { output_result(component, state, solver_output, obj_seq) - } -> std::convertible_to>; + } -> detail::assignable_to>>; } constexpr ResIt output_result(MainModelState const& state, MathOutput> const& math_output, ResIt res_it) { @@ -406,13 +408,13 @@ constexpr ResIt output_result(MainModelState const& state, }); } template Component, class ComponentContainer, solver_output_type SolverOutputType, - std::forward_iterator ResIt> + typename ResIt> requires model_component_state_c && requires(Component const& component, std::vector const& solver_output, Idx2DBranch3 const& math_id) { { output_result(component, solver_output, math_id) - } -> std::convertible_to>; + } -> detail::assignable_to>>; } constexpr ResIt output_result(MainModelState const& state, MathOutput> const& math_output, ResIt res_it) { @@ -421,14 +423,13 @@ constexpr ResIt output_result(MainModelState const& state, return output_result(component, math_output.solver_output, math_id); }); } -template Component, class ComponentContainer, typename SolverOutputType, - std::forward_iterator ResIt> +template Component, class ComponentContainer, typename SolverOutputType, typename ResIt> requires model_component_state_c && requires(Component const& component, MainModelState const& state, MathOutput const& math_output, Idx const obj_seq) { { output_result(component, state, math_output, obj_seq) - } -> std::convertible_to>; + } -> detail::assignable_to>>; } constexpr ResIt output_result(MainModelState const& state, MathOutput const& math_output, ResIt res_it) { @@ -440,7 +441,7 @@ constexpr ResIt output_result(MainModelState const& state, // output source, load_gen, shunt individually template Component, class ComponentContainer, solver_output_type SolverOutputType, - std::forward_iterator ResIt> + typename ResIt> requires model_component_state_c constexpr ResIt output_result(MainModelState const& state, MathOutput> const& math_output, ResIt res_it) { diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp index 61c1c5d34..a1996a9f1 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp @@ -791,7 +791,14 @@ class MainModelImpl, ComponentLis result_data, update_data, options.threading); } - template + // template + // requires solver_output_type + // ResIt output_result(MathOutputType const& math_output, ResIt res_it) const { + // assert(construction_complete_); + // return main_core::output_result(state_, math_output, res_it); + // } + + template requires solver_output_type ResIt output_result(MathOutputType const& math_output, ResIt res_it) const { assert(construction_complete_); @@ -803,11 +810,21 @@ class MainModelImpl, ComponentLis Idx pos = 0) const { auto const output_func = [this, &math_output, &result_data, pos]() { // output - auto const span = result_data.get_buffer_span::type, CT>(pos); - if (span.empty()) { - return; + if (result_data.is_columnar(CT::name)) { + auto const span = + result_data.get_columnar_buffer_span::type, CT>(pos); + if (span.empty()) { + return; + } + this->output_result(math_output, span.begin()); + } else { + auto const span = + result_data.get_buffer_span::type, CT>(pos); + if (span.empty()) { + return; + } + this->output_result(math_output, span.begin()); } - this->output_result(math_output, span.begin()); }; Timer const t_output(calculation_info_, 3000, "Produce output"); run_functor_with_all_types_return_void(output_func); From 1fd5c367a3bd120989cff3d1623667e633baa02e Mon Sep 17 00:00:00 2001 From: Jerry Guo Date: Thu, 5 Sep 2024 16:44:25 +0200 Subject: [PATCH 3/9] fix clang tidy complains Signed-off-by: Jerry Guo --- .../include/power_grid_model/auxiliary/dataset.hpp | 4 ++-- .../include/power_grid_model/main_core/input.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp index cf9ca8cd8..cfef704a8 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp @@ -78,7 +78,7 @@ template class ColumnarAttributeRang ctype_func_selector( meta_attribute.ctype, [&value, &attribute_buffer, &meta_attribute, this] { AttributeType* buffer_ptr = reinterpret_cast(attribute_buffer.data) + idx_; - AttributeType const& attribute_ref = meta_attribute.template get_attribute( + auto const& attribute_ref = meta_attribute.template get_attribute( reinterpret_cast(&value)); *buffer_ptr = attribute_ref; }); @@ -95,7 +95,7 @@ template class ColumnarAttributeRang meta_attribute.ctype, [&result, &attribute_buffer, &meta_attribute, this] { AttributeType const* buffer_ptr = reinterpret_cast(attribute_buffer.data) + idx_; - AttributeType& attribute_ref = + auto& attribute_ref = meta_attribute.template get_attribute(reinterpret_cast(&result)); attribute_ref = *buffer_ptr; }); diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/input.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/input.hpp index c2afebd57..cad3c1e42 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/input.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/input.hpp @@ -31,7 +31,7 @@ inline void add_component(MainModelState& state, ForwardIter std::vector regulated_objects; // loop to add component for (auto it = begin; it != end; ++it) { - ComponentView input = *it; + ComponentView const input = *it; ID const id = input.id; // construct based on type of component if constexpr (std::derived_from) { From c4971005732099cdd58c5e94053f3fccde664858 Mon Sep 17 00:00:00 2001 From: Jerry Guo Date: Thu, 5 Sep 2024 18:03:01 +0200 Subject: [PATCH 4/9] [skip ci] added update data, not yet working Signed-off-by: Jerry Guo --- .../power_grid_model/main_core/update.hpp | 4 +- .../power_grid_model/main_model_impl.hpp | 49 +++++++++++-------- .../cpp_integration_tests/test_main_model.cpp | 30 ++++++++++++ 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp index a392fc0d6..8fb857d9f 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp @@ -27,7 +27,7 @@ inline void iterate_component_sequence(Func&& func, ForwardIterator begin, Forwa } } // namespace detail -template OutputIterator> requires model_component_state_c inline void get_component_sequence(MainModelState const& state, ForwardIterator begin, @@ -38,7 +38,7 @@ inline void get_component_sequence(MainModelState const& sta [&state](UpdateType const& update) { return get_component_idx_by_id(state, update.id); }); } -template +template requires model_component_state_c inline std::vector get_component_sequence(MainModelState const& state, ForwardIterator begin, ForwardIterator end) { diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp index a1996a9f1..6c98a0468 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp @@ -360,17 +360,30 @@ class MainModelImpl, ComponentLis // get sequence idx map of a certain batch scenario SequenceIdx get_sequence_idx_map(ConstDataset const& update_data, Idx scenario_idx) const { - - auto const get_seq_idx_func = [&state = this->state_, &update_data, - scenario_idx]() -> std::vector { - auto const buffer_span = update_data.get_buffer_span(scenario_idx); + auto const process_buffer_span = [](auto const& buffer_span, auto const& get_sequence) { auto const it_begin = buffer_span.begin(); auto const it_end = buffer_span.end(); - return main_core::get_component_sequence(state, it_begin, it_end); + return get_sequence(it_begin, it_end); + }; + + auto const get_seq_idx_func = [&state = this->state_, &update_data, scenario_idx, + &process_buffer_span]() -> std::vector { + auto const get_sequence = [&state](auto const& it_begin, auto const& it_end) { + return main_core::get_component_sequence(state, it_begin, it_end); + }; + + if (update_data.is_columnar(CT::name)) { + auto const buffer_span = + update_data.get_columnar_buffer_span(scenario_idx); + return process_buffer_span(buffer_span, get_sequence); + } else { + auto const buffer_span = update_data.get_buffer_span(scenario_idx); + return process_buffer_span(buffer_span, get_sequence); + } }; + return run_functor_with_all_types_return_array(get_seq_idx_func); } - // get sequence idx map of an entire batch for fast caching of component sequences // (only applicable for independent update dataset) SequenceIdx get_sequence_idx_map(ConstDataset const& update_data) const { @@ -791,13 +804,6 @@ class MainModelImpl, ComponentLis result_data, update_data, options.threading); } - // template - // requires solver_output_type - // ResIt output_result(MathOutputType const& math_output, ResIt res_it) const { - // assert(construction_complete_); - // return main_core::output_result(state_, math_output, res_it); - // } - template requires solver_output_type ResIt output_result(MathOutputType const& math_output, ResIt res_it) const { @@ -809,23 +815,24 @@ class MainModelImpl, ComponentLis void output_result(MathOutput> const& math_output, MutableDataset const& result_data, Idx pos = 0) const { auto const output_func = [this, &math_output, &result_data, pos]() { - // output - if (result_data.is_columnar(CT::name)) { - auto const span = - result_data.get_columnar_buffer_span::type, CT>(pos); + auto process_output = [this, &math_output](auto const& span) { if (span.empty()) { return; } this->output_result(math_output, span.begin()); + }; + + if (result_data.is_columnar(CT::name)) { + auto const span = + result_data.get_columnar_buffer_span::type, CT>(pos); + process_output(span); } else { auto const span = result_data.get_buffer_span::type, CT>(pos); - if (span.empty()) { - return; - } - this->output_result(math_output, span.begin()); + process_output(span); } }; + Timer const t_output(calculation_info_, 3000, "Produce output"); run_functor_with_all_types_return_void(output_func); } diff --git a/tests/cpp_integration_tests/test_main_model.cpp b/tests/cpp_integration_tests/test_main_model.cpp index 85960005c..d6ea50ecb 100644 --- a/tests/cpp_integration_tests/test_main_model.cpp +++ b/tests/cpp_integration_tests/test_main_model.cpp @@ -1312,6 +1312,36 @@ TEST_CASE("Test main model - runtime dispatch") { CHECK(row_based_node_output[idx].u_pu == columnar_node_output_u_pu[idx]); } } + SUBCASE("Columnar buffers in update data") { + std::vector node_ids; + std::vector node_u_rated; + std::ranges::transform(state.node_input, std::back_inserter(node_ids), + [](auto const& node) { return node.id; }); + std::ranges::transform(state.node_input, std::back_inserter(node_u_rated), + [](auto const& node) { return node.u_rated; }); + REQUIRE(node_ids.size() == node_u_rated.size()); + + ConstDataset update_data_with_columns{false, 1, "input", meta_data::meta_data_gen::meta_data}; + update_data_with_columns.add_buffer("node", state.node_input.size(), state.node_input.size(), nullptr, + nullptr); + update_data_with_columns.add_attribute_buffer("node", "id", node_ids.data()); + update_data_with_columns.add_attribute_buffer("node", "u_rated", node_u_rated.data()); + update_data_with_columns.add_buffer("line", state.line_input.size(), state.line_input.size(), nullptr, + state.line_input.data()); + update_data_with_columns.add_buffer("link", state.link_input.size(), state.link_input.size(), nullptr, + state.link_input.data()); + update_data_with_columns.add_buffer("source", state.source_input.size(), state.source_input.size(), nullptr, + state.source_input.data()); + update_data_with_columns.add_buffer("sym_load", state.sym_load_input.size(), state.sym_load_input.size(), + nullptr, state.sym_load_input.data()); + update_data_with_columns.add_buffer("asym_load", state.asym_load_input.size(), state.asym_load_input.size(), + nullptr, state.asym_load_input.data()); + update_data_with_columns.add_buffer("shunt", state.shunt_input.size(), state.shunt_input.size(), nullptr, + state.shunt_input.data()); + + MainModel row_based_model{50.0, input_data}; + row_based_model.update_component(update_data_with_columns); + } } } From 3193790b60787b9ffa0c61c18bcbfe3bf0f80894 Mon Sep 17 00:00:00 2001 From: Jerry Guo Date: Thu, 5 Sep 2024 20:55:51 +0200 Subject: [PATCH 5/9] [skip ci] `is_columnar` needs update Signed-off-by: Jerry Guo --- .../power_grid_model/main_core/update.hpp | 14 +++++++------- .../power_grid_model/main_model_impl.hpp | 19 ++++++++++++++++--- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp index 8fb857d9f..3703c6471 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp @@ -11,7 +11,7 @@ namespace power_grid_model::main_core { namespace detail { -template +template requires std::invocable, typename Component::UpdateType, Idx2D const&> inline void iterate_component_sequence(Func&& func, ForwardIterator begin, ForwardIterator end, std::vector const& sequence_idx) { @@ -27,7 +27,7 @@ inline void iterate_component_sequence(Func&& func, ForwardIterator begin, Forwa } } // namespace detail -template OutputIterator> requires model_component_state_c inline void get_component_sequence(MainModelState const& state, ForwardIterator begin, @@ -38,7 +38,7 @@ inline void get_component_sequence(MainModelState const& sta [&state](UpdateType const& update) { return get_component_idx_by_id(state, update.id); }); } -template +template requires model_component_state_c inline std::vector get_component_sequence(MainModelState const& state, ForwardIterator begin, ForwardIterator end) { @@ -52,7 +52,7 @@ inline std::vector get_component_sequence(MainModelState OutputIterator> requires model_component_state_c inline UpdateChange update_component(MainModelState& state, ForwardIterator begin, @@ -77,7 +77,7 @@ inline UpdateChange update_component(MainModelState& state, return state_changed; } -template OutputIterator> requires model_component_state_c inline UpdateChange update_component(MainModelState& state, ForwardIterator begin, @@ -90,7 +90,7 @@ inline UpdateChange update_component(MainModelState& state, // using forward interators // different selection based on component type // if sequence_idx is given, it will be used to load the object instead of using IDs via hash map. -template OutputIterator> requires model_component_state_c inline void update_inverse(MainModelState const& state, ForwardIterator begin, ForwardIterator end, @@ -104,7 +104,7 @@ inline void update_inverse(MainModelState const& state, Forw }, begin, end, sequence_idx); } -template OutputIterator> requires model_component_state_c inline void update_inverse(MainModelState const& state, ForwardIterator begin, ForwardIterator end, diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp index 6c98a0468..8f94048c2 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp @@ -229,7 +229,7 @@ class MainModelImpl, ComponentLis // using forward interators // different selection based on component type // if sequence_idx is given, it will be used to load the object instead of using IDs via hash map. - template + template void update_component(ForwardIterator begin, ForwardIterator end, std::vector const& sequence_idx) { constexpr auto comp_index = index_of_component; @@ -266,6 +266,13 @@ class MainModelImpl, ComponentLis update_component(components.begin(), components.end(), sequence_idx); } } + template + void update_component(ConstDataset::RangeObject components, + std::vector const& sequence_idx) { + if (!components.empty()) { + update_component(components.begin(), components.end(), sequence_idx); + } + } // update all components template @@ -273,8 +280,14 @@ class MainModelImpl, ComponentLis assert(construction_complete_); assert(update_data.get_description().dataset->name == std::string_view("update")); auto const update_func = [this, pos, &update_data, &sequence_idx_map]() { - this->update_component(update_data.get_buffer_span(pos), - sequence_idx_map[index_of_component]); + if (update_data.is_columnar(CT::name)) { + this->update_component( + update_data.get_columnar_buffer_span(pos), + sequence_idx_map[index_of_component]); + } else { + this->update_component(update_data.get_buffer_span(pos), + sequence_idx_map[index_of_component]); + } }; run_functor_with_all_types_return_void(update_func); } From 9bd4524d0d42f02eee69939c908007c3d2e2f716 Mon Sep 17 00:00:00 2001 From: Jerry Guo Date: Fri, 6 Sep 2024 11:37:58 +0200 Subject: [PATCH 6/9] [skip ci] commit before hand over: issue marked in comment Signed-off-by: Jerry Guo --- .../power_grid_model/main_model_impl.hpp | 1 + .../cpp_integration_tests/test_main_model.cpp | 32 ++++++------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp index 8f94048c2..4eae15d96 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp @@ -388,6 +388,7 @@ class MainModelImpl, ComponentLis if (update_data.is_columnar(CT::name)) { auto const buffer_span = update_data.get_columnar_buffer_span(scenario_idx); + // [JGUO] ISSUE here: buffer_span .begin() and .end() are 0 away return process_buffer_span(buffer_span, get_sequence); } else { auto const buffer_span = update_data.get_buffer_span(scenario_idx); diff --git a/tests/cpp_integration_tests/test_main_model.cpp b/tests/cpp_integration_tests/test_main_model.cpp index d6ea50ecb..caf0c3514 100644 --- a/tests/cpp_integration_tests/test_main_model.cpp +++ b/tests/cpp_integration_tests/test_main_model.cpp @@ -1313,31 +1313,19 @@ TEST_CASE("Test main model - runtime dispatch") { } } SUBCASE("Columnar buffers in update data") { - std::vector node_ids; - std::vector node_u_rated; - std::ranges::transform(state.node_input, std::back_inserter(node_ids), - [](auto const& node) { return node.id; }); - std::ranges::transform(state.node_input, std::back_inserter(node_u_rated), - [](auto const& node) { return node.u_rated; }); - REQUIRE(node_ids.size() == node_u_rated.size()); + std::vector source_ids; + std::vector source_u_ref; + std::ranges::transform(state.source_input, std::back_inserter(source_ids), + [](auto const& source) { return source.id; }); + std::ranges::transform(state.source_input, std::back_inserter(source_u_ref), + [](auto const& source) { return source.u_ref; }); + REQUIRE(source_ids.size() == source_u_ref.size()); ConstDataset update_data_with_columns{false, 1, "input", meta_data::meta_data_gen::meta_data}; - update_data_with_columns.add_buffer("node", state.node_input.size(), state.node_input.size(), nullptr, - nullptr); - update_data_with_columns.add_attribute_buffer("node", "id", node_ids.data()); - update_data_with_columns.add_attribute_buffer("node", "u_rated", node_u_rated.data()); - update_data_with_columns.add_buffer("line", state.line_input.size(), state.line_input.size(), nullptr, - state.line_input.data()); - update_data_with_columns.add_buffer("link", state.link_input.size(), state.link_input.size(), nullptr, - state.link_input.data()); update_data_with_columns.add_buffer("source", state.source_input.size(), state.source_input.size(), nullptr, - state.source_input.data()); - update_data_with_columns.add_buffer("sym_load", state.sym_load_input.size(), state.sym_load_input.size(), - nullptr, state.sym_load_input.data()); - update_data_with_columns.add_buffer("asym_load", state.asym_load_input.size(), state.asym_load_input.size(), - nullptr, state.asym_load_input.data()); - update_data_with_columns.add_buffer("shunt", state.shunt_input.size(), state.shunt_input.size(), nullptr, - state.shunt_input.data()); + nullptr); + update_data_with_columns.add_attribute_buffer("source", "id", source_ids.data()); + update_data_with_columns.add_attribute_buffer("source", "u_ref", source_u_ref.data()); MainModel row_based_model{50.0, input_data}; row_based_model.update_component(update_data_with_columns); From d92180dcbe5ccc4d66b1410ef898471249ab0fca Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 9 Sep 2024 15:25:39 +0200 Subject: [PATCH 7/9] add support for columnar update data Signed-off-by: Martijn Govers --- .../power_grid_model/main_model_impl.hpp | 1 - .../cpp_integration_tests/test_main_model.cpp | 126 ++++++++++++++---- tests/cpp_unit_tests/test_dataset.cpp | 1 + 3 files changed, 103 insertions(+), 25 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp index 4eae15d96..8f94048c2 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp @@ -388,7 +388,6 @@ class MainModelImpl, ComponentLis if (update_data.is_columnar(CT::name)) { auto const buffer_span = update_data.get_columnar_buffer_span(scenario_idx); - // [JGUO] ISSUE here: buffer_span .begin() and .end() are 0 away return process_buffer_span(buffer_span, get_sequence); } else { auto const buffer_span = update_data.get_buffer_span(scenario_idx); diff --git a/tests/cpp_integration_tests/test_main_model.cpp b/tests/cpp_integration_tests/test_main_model.cpp index caf0c3514..c88ca010d 100644 --- a/tests/cpp_integration_tests/test_main_model.cpp +++ b/tests/cpp_integration_tests/test_main_model.cpp @@ -1278,11 +1278,11 @@ TEST_CASE("Test main model - runtime dispatch") { row_based_model.calculate(options, sym_output_from_row_based); columnar_model.calculate(options, sym_output_from_columnar); - REQUIRE(node_output_from_row_based.size() == node_output_from_columnar.size()); + REQUIRE(node_output_from_columnar.size() == node_output_from_row_based.size()); - for (Idx idx = 0; idx < std::ssize(node_output_from_row_based); ++idx) { - CHECK(node_output_from_row_based[idx].id == node_output_from_columnar[idx].id); - CHECK(node_output_from_row_based[idx].u_pu == node_output_from_columnar[idx].u_pu); + for (Idx idx = 0; idx < std::ssize(node_output_from_columnar); ++idx) { + CHECK(node_output_from_columnar[idx].id == node_output_from_row_based[idx].id); + CHECK(node_output_from_columnar[idx].u_pu == node_output_from_row_based[idx].u_pu); } } SUBCASE("Columnar buffers in output data") { @@ -1304,31 +1304,109 @@ TEST_CASE("Test main model - runtime dispatch") { model.calculate(options, row_based_sym_output); model.calculate(options, columnar_sym_output); - REQUIRE(row_based_node_output.size() == columnar_node_output_id.size()); - REQUIRE(row_based_node_output.size() == columnar_node_output_u_pu.size()); + REQUIRE(columnar_node_output_id.size() == row_based_node_output.size()); + REQUIRE(columnar_node_output_u_pu.size() == row_based_node_output.size()); - for (Idx idx = 0; idx < std::ssize(row_based_node_output); ++idx) { - CHECK(row_based_node_output[idx].id == columnar_node_output_id[idx]); - CHECK(row_based_node_output[idx].u_pu == columnar_node_output_u_pu[idx]); + for (Idx idx = 0; idx < std::ssize(columnar_node_output_id); ++idx) { + CHECK(columnar_node_output_id[idx] == row_based_node_output[idx].id); + CHECK(columnar_node_output_u_pu[idx] == doctest::Approx(row_based_node_output[idx].u_pu)); } } SUBCASE("Columnar buffers in update data") { - std::vector source_ids; - std::vector source_u_ref; - std::ranges::transform(state.source_input, std::back_inserter(source_ids), - [](auto const& source) { return source.id; }); - std::ranges::transform(state.source_input, std::back_inserter(source_u_ref), - [](auto const& source) { return source.u_ref; }); - REQUIRE(source_ids.size() == source_u_ref.size()); - - ConstDataset update_data_with_columns{false, 1, "input", meta_data::meta_data_gen::meta_data}; - update_data_with_columns.add_buffer("source", state.source_input.size(), state.source_input.size(), nullptr, - nullptr); - update_data_with_columns.add_attribute_buffer("source", "id", source_ids.data()); - update_data_with_columns.add_attribute_buffer("source", "u_ref", source_u_ref.data()); + std::vector sym_load_ids; + std::vector sym_load_p_specified; + std::ranges::transform(state.sym_load_update, std::back_inserter(sym_load_ids), + [](auto const& sym_load) { return sym_load.id; }); + std::ranges::transform(state.sym_load_update, std::back_inserter(sym_load_p_specified), + [](auto const& sym_load) { return sym_load.p_specified; }); + REQUIRE(sym_load_ids.size() == sym_load_p_specified.size()); + REQUIRE(sym_load_ids.size() == state.sym_load_update.size()); + + ConstDataset update_data_with_rows{false, 1, "update", meta_data::meta_data_gen::meta_data}; + update_data_with_rows.add_buffer("sym_load", state.sym_load_update.size(), state.sym_load_update.size(), + nullptr, state.sym_load_update.data()); + + ConstDataset update_data_with_columns{false, 1, "update", meta_data::meta_data_gen::meta_data}; + update_data_with_columns.add_buffer("sym_load", sym_load_ids.size(), sym_load_ids.size(), nullptr, nullptr); + update_data_with_columns.add_attribute_buffer("sym_load", "id", sym_load_ids.data()); + update_data_with_columns.add_attribute_buffer("sym_load", "p_specified", sym_load_p_specified.data()); + + MainModel base_model{50.0, input_data}; + MainModel row_based_model{base_model}; + MainModel columnar_model{base_model}; + row_based_model.update_component(update_data_with_rows); + columnar_model.update_component(update_data_with_columns); + + std::vector node_output_from_base(state.node_input.size()); + std::vector node_output_from_row_based(state.node_input.size()); + std::vector node_output_from_columnar(state.node_input.size()); - MainModel row_based_model{50.0, input_data}; - row_based_model.update_component(update_data_with_columns); + MutableDataset sym_output_from_base{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; + sym_output_from_base.add_buffer("node", node_output_from_base.size(), node_output_from_base.size(), nullptr, + node_output_from_base.data()); + MutableDataset sym_output_from_row_based{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; + sym_output_from_row_based.add_buffer("node", node_output_from_row_based.size(), + node_output_from_row_based.size(), nullptr, + node_output_from_row_based.data()); + MutableDataset sym_output_from_columnar{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; + sym_output_from_columnar.add_buffer("node", node_output_from_columnar.size(), + node_output_from_columnar.size(), nullptr, + node_output_from_columnar.data()); + + base_model.calculate(options, sym_output_from_base); + row_based_model.calculate(options, sym_output_from_row_based); + columnar_model.calculate(options, sym_output_from_columnar); + + REQUIRE(node_output_from_columnar.size() == node_output_from_base.size()); + REQUIRE(node_output_from_columnar.size() == node_output_from_row_based.size()); + + for (Idx idx = 0; idx < std::ssize(node_output_from_columnar); ++idx) { + // check columnar updates work same way as row-based updates + CHECK(node_output_from_columnar[idx].id == doctest::Approx(node_output_from_row_based[idx].id)); + CHECK(node_output_from_columnar[idx].u_pu == doctest::Approx(node_output_from_row_based[idx].u_pu)); + // check update actually changed something + CHECK(node_output_from_columnar[idx].id == doctest::Approx(node_output_from_base[idx].id)); + if (idx == 0) { // sym_load node + CHECK(node_output_from_columnar[idx].u_pu == doctest::Approx(node_output_from_base[idx].u_pu)); + } else { + CHECK(node_output_from_columnar[idx].u_pu != doctest::Approx(node_output_from_base[idx].u_pu)); + } + } + } + SUBCASE("Empty columnar update data") { + std::vector sym_load_ids; + std::vector sym_load_p_specified; + REQUIRE(sym_load_ids.size() == sym_load_p_specified.size()); + + ConstDataset update_data_with_columns{false, 1, "update", meta_data::meta_data_gen::meta_data}; + update_data_with_columns.add_buffer("sym_load", sym_load_ids.size(), sym_load_ids.size(), nullptr, nullptr); + update_data_with_columns.add_attribute_buffer("sym_load", "id", sym_load_ids.data()); + update_data_with_columns.add_attribute_buffer("sym_load", "p_specified", sym_load_p_specified.data()); + + MainModel base_model{50.0, input_data}; + MainModel columnar_model{base_model}; + columnar_model.update_component(update_data_with_columns); + + std::vector node_output_from_base(state.node_input.size()); + std::vector node_output_from_columnar(state.node_input.size()); + + MutableDataset sym_output_from_base{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; + sym_output_from_base.add_buffer("node", node_output_from_base.size(), node_output_from_base.size(), nullptr, + node_output_from_base.data()); + MutableDataset sym_output_from_columnar{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; + sym_output_from_columnar.add_buffer("node", node_output_from_columnar.size(), + node_output_from_columnar.size(), nullptr, + node_output_from_columnar.data()); + + base_model.calculate(options, sym_output_from_base); + columnar_model.calculate(options, sym_output_from_columnar); + + REQUIRE(node_output_from_columnar.size() == node_output_from_base.size()); + + for (Idx idx = 0; idx < std::ssize(node_output_from_base); ++idx) { + CHECK(node_output_from_columnar[idx].id == doctest::Approx(node_output_from_base[idx].id)); + CHECK(node_output_from_columnar[idx].u_pu == doctest::Approx(node_output_from_base[idx].u_pu)); + } } } } diff --git a/tests/cpp_unit_tests/test_dataset.cpp b/tests/cpp_unit_tests/test_dataset.cpp index 94caafb61..aceec0b06 100644 --- a/tests/cpp_unit_tests/test_dataset.cpp +++ b/tests/cpp_unit_tests/test_dataset.cpp @@ -190,6 +190,7 @@ void check_row_span(BufferSpan const& buffer_span, Idx const& total_elements, CHECK(std::size(buffer_span) == total_elements); CHECK(std::data(buffer_span) == a_buffer.data()); } + } // namespace TEST_CASE_TEMPLATE("Test range object", RangeObjectType, const_range_object, From 60a7be333f4dba8c75883c84071dd1496179b53a Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Mon, 9 Sep 2024 16:28:56 +0200 Subject: [PATCH 8/9] resolve sonar-cloud + clang-tidy Signed-off-by: Martijn Govers --- .../common/grouped_index_vector.hpp | 40 ++----------- .../common/iterator_like_concepts.hpp | 56 +++++++++++++++++++ .../power_grid_model/main_core/input.hpp | 4 +- .../power_grid_model/main_core/update.hpp | 21 ++++--- .../power_grid_model/main_model_impl.hpp | 14 ++--- 5 files changed, 84 insertions(+), 51 deletions(-) create mode 100644 power_grid_model_c/power_grid_model/include/power_grid_model/common/iterator_like_concepts.hpp diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/common/grouped_index_vector.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/common/grouped_index_vector.hpp index 194b3145d..054ec3bee 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/common/grouped_index_vector.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/common/grouped_index_vector.hpp @@ -6,6 +6,7 @@ #include "common.hpp" #include "counting_iterator.hpp" +#include "iterator_like_concepts.hpp" #include "typing.hpp" #include @@ -36,6 +37,9 @@ namespace power_grid_model { using IdxRange = boost::iterator_range; namespace detail { +// TODO(mgovers): replace the below relevant iterator concepts with the STD equivalent when we have index ranges. +// boost::counting_iterator does not satisfy all requirements std::*_iterator concepts: +static_assert(!std::random_access_iterator); inline auto sparse_encode(IdxVector const& element_groups, Idx num_groups) { IdxVector result(num_groups + 1); @@ -55,42 +59,6 @@ inline auto sparse_decode(IdxVector const& indptr) { return result; } -// TODO(mgovers): replace the below relevant subset here ourselves with the STD equivalent when we have std::ranges. -// boost::counting_iterator does not satisfy all requirements std::*_iterator concepts: -static_assert(!std::random_access_iterator); -// we have to declare the relevant subset here ourselves. -template -concept iterator_like = requires(T const t) { - { *t } -> std::convertible_to const&>; - }; - -template -concept random_access_iterator_like = - std::regular && iterator_like && std::totally_ordered && requires(T t, Idx n) { - { t++ } -> std::same_as; - { t-- } -> std::same_as; - { ++t } -> std::same_as; - { --t } -> std::same_as; - - { t + n } -> std::same_as; - { t - n } -> std::same_as; - { t += n } -> std::same_as; - { t -= n } -> std::same_as; - }; - -template -concept random_access_iterable_like = requires(T const t) { - { t.begin() } -> random_access_iterator_like; - { t.end() } -> random_access_iterator_like; - }; - -template -concept index_range_iterator = - random_access_iterator_like && requires(T const t) { - typename T::iterator; - { *t } -> random_access_iterable_like; - }; - template concept grouped_index_vector_type = std::default_initializable && requires(T const t, Idx const idx) { typename T::iterator; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/common/iterator_like_concepts.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/common/iterator_like_concepts.hpp new file mode 100644 index 000000000..6e2a48e39 --- /dev/null +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/common/iterator_like_concepts.hpp @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: Contributors to the Power Grid Model project +// +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +namespace power_grid_model { +// TODO(mgovers): replace the below relevant iterator concepts with the STD equivalent when we have index ranges. +// e.g.: boost::counting_iterator does not satisfy all requirements std::*_iterator concepts: +// we have to declare the relevant subset here ourselves. + +template +concept iterator_like = requires(T const t) { + { *t } -> std::convertible_to const&>; + }; + +template +concept forward_iterator_like = std::regular && iterator_like && requires(T t) { + { t++ } -> std::same_as; + { ++t } -> std::same_as; + }; + +template +concept bidirectional_iterator_like = forward_iterator_like && requires(T t) { + { t-- } -> std::same_as; + { --t } -> std::same_as; + }; + +template +concept random_access_iterator_like = + bidirectional_iterator_like && std::totally_ordered && requires(T t, Idx n) { + { t++ } -> std::same_as; + { t-- } -> std::same_as; + { ++t } -> std::same_as; + { --t } -> std::same_as; + + { t + n } -> std::same_as; + { t - n } -> std::same_as; + { t += n } -> std::same_as; + { t -= n } -> std::same_as; + }; + +template +concept random_access_iterable_like = requires(T const t) { + { t.begin() } -> random_access_iterator_like; + { t.end() } -> random_access_iterator_like; + }; + +template +concept index_range_iterator = + random_access_iterator_like && requires(T const t) { + typename T::iterator; + { *t } -> random_access_iterable_like; + }; + +} // namespace power_grid_model diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/input.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/input.hpp index cad3c1e42..67a2124fb 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/input.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/input.hpp @@ -8,6 +8,7 @@ #include "state_queries.hpp" #include "../all_components.hpp" +#include "../common/iterator_like_concepts.hpp" #include @@ -19,7 +20,8 @@ constexpr std::array const branch3_sides = {Branch3Side::side_1, // template to construct components // using forward interators // different selection based on component type -template Component, class ComponentContainer, typename ForwardIterator> +template Component, class ComponentContainer, + forward_iterator_like ForwardIterator> requires model_component_state_c inline void add_component(MainModelState& state, ForwardIterator begin, ForwardIterator end, double system_frequency) { diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp index 3703c6471..71ee3f7c4 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp @@ -7,11 +7,12 @@ #include "state.hpp" #include "../all_components.hpp" +#include "../common/iterator_like_concepts.hpp" namespace power_grid_model::main_core { namespace detail { -template +template ForwardIterator, typename Func> requires std::invocable, typename Component::UpdateType, Idx2D const&> inline void iterate_component_sequence(Func&& func, ForwardIterator begin, ForwardIterator end, std::vector const& sequence_idx) { @@ -27,7 +28,8 @@ inline void iterate_component_sequence(Func&& func, ForwardIterator begin, Forwa } } // namespace detail -template ForwardIterator, std::output_iterator OutputIterator> requires model_component_state_c inline void get_component_sequence(MainModelState const& state, ForwardIterator begin, @@ -38,7 +40,8 @@ inline void get_component_sequence(MainModelState const& sta [&state](UpdateType const& update) { return get_component_idx_by_id(state, update.id); }); } -template +template ForwardIterator> requires model_component_state_c inline std::vector get_component_sequence(MainModelState const& state, ForwardIterator begin, ForwardIterator end) { @@ -52,7 +55,8 @@ inline std::vector get_component_sequence(MainModelState ForwardIterator, std::output_iterator OutputIterator> requires model_component_state_c inline UpdateChange update_component(MainModelState& state, ForwardIterator begin, @@ -77,7 +81,8 @@ inline UpdateChange update_component(MainModelState& state, return state_changed; } -template ForwardIterator, std::output_iterator OutputIterator> requires model_component_state_c inline UpdateChange update_component(MainModelState& state, ForwardIterator begin, @@ -90,7 +95,8 @@ inline UpdateChange update_component(MainModelState& state, // using forward interators // different selection based on component type // if sequence_idx is given, it will be used to load the object instead of using IDs via hash map. -template ForwardIterator, std::output_iterator OutputIterator> requires model_component_state_c inline void update_inverse(MainModelState const& state, ForwardIterator begin, ForwardIterator end, @@ -104,7 +110,8 @@ inline void update_inverse(MainModelState const& state, Forw }, begin, end, sequence_idx); } -template ForwardIterator, std::output_iterator OutputIterator> requires model_component_state_c inline void update_inverse(MainModelState const& state, ForwardIterator begin, ForwardIterator end, diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp index 8f94048c2..c1705a8ef 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp @@ -208,7 +208,7 @@ class MainModelImpl, ComponentLis // template to construct components // using forward interators // different selection based on component type - template CompType, typename ForwardIterator> + template CompType, forward_iterator_like ForwardIterator> void add_component(ForwardIterator begin, ForwardIterator end) { assert(!construction_complete_); main_core::add_component(state_, begin, end, system_frequency_); @@ -229,7 +229,8 @@ class MainModelImpl, ComponentLis // using forward interators // different selection based on component type // if sequence_idx is given, it will be used to load the object instead of using IDs via hash map. - template + template ForwardIterator> void update_component(ForwardIterator begin, ForwardIterator end, std::vector const& sequence_idx) { constexpr auto comp_index = index_of_component; @@ -389,10 +390,9 @@ class MainModelImpl, ComponentLis auto const buffer_span = update_data.get_columnar_buffer_span(scenario_idx); return process_buffer_span(buffer_span, get_sequence); - } else { - auto const buffer_span = update_data.get_buffer_span(scenario_idx); - return process_buffer_span(buffer_span, get_sequence); } + auto const buffer_span = update_data.get_buffer_span(scenario_idx); + return process_buffer_span(buffer_span, get_sequence); }; return run_functor_with_all_types_return_array(get_seq_idx_func); @@ -829,10 +829,10 @@ class MainModelImpl, ComponentLis Idx pos = 0) const { auto const output_func = [this, &math_output, &result_data, pos]() { auto process_output = [this, &math_output](auto const& span) { - if (span.empty()) { + if (std::empty(span)) { return; } - this->output_result(math_output, span.begin()); + this->output_result(math_output, std::begin(span)); }; if (result_data.is_columnar(CT::name)) { From 8e9effa193a36a5c620e2f8a5209fa5c41aa95d2 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 10 Sep 2024 10:16:37 +0200 Subject: [PATCH 9/9] minor cleanup Signed-off-by: Martijn Govers --- .../power_grid_model/common/iterator_like_concepts.hpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/common/iterator_like_concepts.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/common/iterator_like_concepts.hpp index 6e2a48e39..b347c4487 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/common/iterator_like_concepts.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/common/iterator_like_concepts.hpp @@ -29,11 +29,6 @@ concept bidirectional_iterator_like = forward_iterator_like && r template concept random_access_iterator_like = bidirectional_iterator_like && std::totally_ordered && requires(T t, Idx n) { - { t++ } -> std::same_as; - { t-- } -> std::same_as; - { ++t } -> std::same_as; - { --t } -> std::same_as; - { t + n } -> std::same_as; { t - n } -> std::same_as; { t += n } -> std::same_as;