From 981032244cca8b731b1da68edba4a50f64044558 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Mon, 11 Nov 2024 09:25:56 +0100 Subject: [PATCH 01/30] Removed hardoded -1s Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_model_impl.hpp | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 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 8f0e00780..91705677f 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 @@ -171,6 +171,9 @@ class MainModelImpl, ComponentLis static constexpr Idx ignore_output{-1}; static constexpr Idx invalid_index{-1}; + static constexpr Idx isolated_component{-1}; + static constexpr Idx not_connected{-1}; + static constexpr Idx sequential{-1}; protected: // run functors with all component types @@ -552,7 +555,7 @@ class MainModelImpl, ComponentLis template requires std::invocable, MainModelImpl&, MutableDataset const&, Idx> BatchParameter batch_calculation_(Calculate&& calculation_fn, MutableDataset const& result_data, - ConstDataset const& update_data, Idx threading = -1) { + ConstDataset const& update_data, Idx threading = sequential) { // if the update dataset is empty without any component // execute one power flow in the current instance, no batch calculation is needed if (update_data.empty()) { @@ -1080,7 +1083,7 @@ class MainModelImpl, ComponentLis // loop all branch for (Idx i = 0; i != static_cast(state_.comp_topo->branch_node_idx.size()); ++i) { Idx2D const math_idx = state_.topo_comp_coup->branch[i]; - if (math_idx.group == -1) { + if (math_idx.group == isolated_component) { continue; } // assign parameters @@ -1090,7 +1093,7 @@ class MainModelImpl, ComponentLis // loop all branch3 for (Idx i = 0; i != static_cast(state_.comp_topo->branch3_node_idx.size()); ++i) { Idx2DBranch3 const math_idx = state_.topo_comp_coup->branch3[i]; - if (math_idx.group == -1) { + if (math_idx.group == isolated_component) { continue; } // assign parameters, branch3 param consists of three branch parameters @@ -1103,7 +1106,7 @@ class MainModelImpl, ComponentLis // loop all shunt for (Idx i = 0; i != static_cast(state_.comp_topo->shunt_node_idx.size()); ++i) { Idx2D const math_idx = state_.topo_comp_coup->shunt[i]; - if (math_idx.group == -1) { + if (math_idx.group == isolated_component) { continue; } // assign parameters @@ -1113,7 +1116,7 @@ class MainModelImpl, ComponentLis // loop all source for (Idx i = 0; i != static_cast(state_.comp_topo->source_node_idx.size()); ++i) { Idx2D const math_idx = state_.topo_comp_coup->source[i]; - if (math_idx.group == -1) { + if (math_idx.group == isolated_component) { continue; } // assign parameters @@ -1132,7 +1135,7 @@ class MainModelImpl, ComponentLis Idx2D const math_idx = state.topo_comp_coup ->branch[main_core::get_component_sequence(state, changed_component_idx)]; - if (math_idx.group == -1) { + if (math_idx.group == isolated_component) { return; } // assign parameters @@ -1141,7 +1144,7 @@ class MainModelImpl, ComponentLis Idx2DBranch3 const math_idx = state.topo_comp_coup ->branch3[main_core::get_component_sequence(state, changed_component_idx)]; - if (math_idx.group == -1) { + if (math_idx.group == isolated_component) { return; } // assign parameters, branch3 param consists of three branch parameters @@ -1154,7 +1157,7 @@ class MainModelImpl, ComponentLis Idx2D const math_idx = state.topo_comp_coup ->shunt[main_core::get_component_sequence(state, changed_component_idx)]; - if (math_idx.group == -1) { + if (math_idx.group == isolated_component) { return; } // assign parameters @@ -1236,7 +1239,7 @@ class MainModelImpl, ComponentLis for (Idx i = 0, n = narrow_cast(components.size()); i != n; ++i) { if (include(i)) { Idx2D const math_idx = components[i]; - if (math_idx.group != -1) { + if (math_idx.group != isolated_component) { auto const& component = get_component_by_sequence(state, i); CalcStructOut& math_model_input = calc_input[math_idx.group]; std::vector& math_model_input_vect = math_model_input.*comp_vect; @@ -1256,7 +1259,7 @@ class MainModelImpl, ComponentLis for (Idx i = 0, n = narrow_cast(components.size()); i != n; ++i) { if (include(i)) { Idx2D const math_idx = components[i]; - if (math_idx.group != -1) { + if (math_idx.group != isolated_component) { auto const& component = get_component_by_sequence(state, i); CalcStructOut& math_model_input = calc_input[math_idx.group]; std::vector& math_model_input_vect = math_model_input.*comp_vect; @@ -1290,7 +1293,7 @@ class MainModelImpl, ComponentLis std::vector>& input) { for (Idx i = 0, n = narrow_cast(objects.size()); i != n; ++i) { Idx2D const math_idx = objects[i]; - if (math_idx.group == -1) { + if (math_idx.group == isolated_component) { continue; } (input[math_idx.group].*component)[math_idx.pos] = @@ -1398,7 +1401,7 @@ class MainModelImpl, ComponentLis } } - auto fault_coup = std::vector(state_.components.template size(), Idx2D{-1, -1}); + auto fault_coup = std::vector(state_.components.template size(), Idx2D{isolated_component, not_connected}); std::vector sc_input(n_math_solvers_); for (Idx i = 0; i != n_math_solvers_; ++i) { From 56534a8999e147f054b8c3009d370465ce61c2a5 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Mon, 11 Nov 2024 09:39:15 +0100 Subject: [PATCH 02/30] Nipick renaming Signed-off-by: Santiago Figueroa Manrique --- .../include/power_grid_model/main_model_impl.hpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 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 91705677f..0f13882d4 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 @@ -169,6 +169,7 @@ class MainModelImpl, ComponentLis using ComponentFlags = std::array; using ComponentCountInBase = std::pair; + // TODO: (figueroa1395) probably move to common.hpp or somewhere else static constexpr Idx ignore_output{-1}; static constexpr Idx invalid_index{-1}; static constexpr Idx isolated_component{-1}; @@ -706,21 +707,21 @@ class MainModelImpl, ComponentLis } static auto scenario_update_restore(MainModelImpl& model, ConstDataset const& update_data, - ComponentFlags const& is_independent, SequenceIdx const& all_scenario_sequence, + ComponentFlags const& independence_flags, SequenceIdx const& all_scenario_sequence, SequenceIdx& current_scenario_sequence_cache, std::vector& infos) noexcept { - auto do_update_cache = [&is_independent] { + auto do_update_cache = [&independence_flags] { ComponentFlags result; - std::ranges::transform(is_independent, result.begin(), std::logical_not<>{}); + std::ranges::transform(independence_flags, result.begin(), std::logical_not<>{}); return result; }(); auto const scenario_sequence = [&all_scenario_sequence, ¤t_scenario_sequence_cache, - &is_independent]() -> SequenceIdxView { + &independence_flags]() -> SequenceIdxView { return run_functor_with_all_types_return_array( - [&all_scenario_sequence, ¤t_scenario_sequence_cache, &is_independent]() { + [&all_scenario_sequence, ¤t_scenario_sequence_cache, &independence_flags]() { constexpr auto comp_idx = index_of_component; - if (std::get(is_independent)) { + if (std::get(independence_flags)) { return std::span{std::get(all_scenario_sequence)}; } return std::span{std::get(current_scenario_sequence_cache)}; From e7e734cf925d64dbf6a2f8c0cc60368fe29e5696 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Mon, 11 Nov 2024 12:59:57 +0100 Subject: [PATCH 03/30] refactor check_components_independence Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_model_impl.hpp | 171 +++++++++--------- 1 file changed, 85 insertions(+), 86 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 0f13882d4..1e5a5185e 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 @@ -439,7 +439,7 @@ class MainModelImpl, ComponentLis if (!std::get>(to_store)) { return std::vector{}; } - auto const independence = check_components_independence(update_data); + auto const independence = check_component_independence(update_data); validate_update_data_independence(independence); return get_component_sequence(update_data, scenario_idx, independence); }); @@ -707,7 +707,8 @@ class MainModelImpl, ComponentLis } static auto scenario_update_restore(MainModelImpl& model, ConstDataset const& update_data, - ComponentFlags const& independence_flags, SequenceIdx const& all_scenario_sequence, + ComponentFlags const& independence_flags, + SequenceIdx const& all_scenario_sequence, SequenceIdx& current_scenario_sequence_cache, std::vector& infos) noexcept { auto do_update_cache = [&independence_flags] { @@ -782,79 +783,76 @@ class MainModelImpl, ComponentLis public: template using UpdateType = typename Component::UpdateType; - template - UpdateCompProperties check_components_independence(ConstDataset const& update_data) const { - auto const comp_count_in_base = this->component_count(); - - auto const check_id_na = [](auto const& obj) -> bool { - if constexpr (requires { obj.id; }) { - return is_nan(obj.id); - } else if constexpr (requires { obj.get().id; }) { - return is_nan(obj.get().id); - } else { - throw UnreachableHit{"check_components_independence", "Only components with id are supported"}; - } - }; - - auto const process_buffer_span = [check_id_na](auto const& all_spans, UpdateCompProperties& result) { - result.ids_all_na = std::ranges::all_of( - all_spans, [&check_id_na](auto const& vec) { return std::ranges::all_of(vec, check_id_na); }); - result.ids_part_na = - std::ranges::any_of( - all_spans, [&check_id_na](auto const& vec) { return std::ranges::any_of(vec, check_id_na); }) && - !result.ids_all_na; + template bool check_id_na(T const& obj) const { + if constexpr (requires { obj.id; }) { + return is_nan(obj.id); + } else if constexpr (requires { obj.get().id; }) { + return is_nan(obj.get().id); + } else { + throw UnreachableHit{"check_component_independence", "Only components with id are supported"}; + } + } - if (all_spans.empty()) { - result.update_ids_match = true; - } else { - // Remember the begin iterator of the first scenario, then loop over the remaining scenarios and - // check the ids - auto const first_span = all_spans[0]; - // check the subsequent scenarios - // only return true if all scenarios match the ids of the first batch - result.update_ids_match = std::ranges::all_of( - all_spans.cbegin() + 1, all_spans.cend(), [&first_span](auto const& current_span) { - return std::ranges::equal(current_span, first_span, - [](UpdateType const& obj, - UpdateType const& first) { return obj.id == first.id; }); - }); - } - }; + template + void process_buffer_span(auto const& all_spans, UpdateCompProperties& properties) const { + properties.ids_all_na = std::ranges::all_of(all_spans, [this](auto const& vec) { + return std::ranges::all_of(vec, [this](auto const& item) { return this->template check_id_na(item); }); + }); + properties.ids_part_na = std::ranges::any_of(all_spans, + [this](auto const& vec) { + return std::ranges::any_of(vec, [this](auto const& item) { + return this->template check_id_na(item); + }); + }) && + !properties.ids_all_na; + + if (all_spans.empty()) { + properties.update_ids_match = true; + } else { + // Remember the begin iterator of the first scenario, then loop over the remaining scenarios and + // check the ids + auto const first_span = all_spans[0]; + // check the subsequent scenarios + // only return true if all scenarios match the ids of the first batch + properties.update_ids_match = + std::ranges::all_of(all_spans.cbegin() + 1, all_spans.cend(), [&first_span](auto const& current_span) { + return std::ranges::equal(current_span, first_span, + [](UpdateType const& obj, UpdateType const& first) { + return obj.id == first.id; + }); + }); + } + } - auto const check_each_component = [&update_data, &process_buffer_span, - &comp_count_in_base]() -> UpdateCompProperties { - // get span of all the update data - auto const comp_index = update_data.find_component(CompType::name, false); - UpdateCompProperties result; - result.name = CompType::name; - result.is_columnar = update_data.is_columnar(result.name); - result.dense = update_data.is_dense(result.name); - result.uniform = update_data.is_uniform(result.name); - result.has_any_elements = - comp_index != invalid_index && update_data.get_component_info(comp_index).total_elements > 0; - - result.elements_ps_in_update = - result.uniform ? update_data.uniform_elements_per_scenario(result.name) : invalid_index; - - result.elements_in_base = comp_count_in_base; - - if (result.is_columnar) { - process_buffer_span( - update_data.get_columnar_buffer_span_all_scenarios(), result); - } else { - process_buffer_span(update_data.get_buffer_span_all_scenarios(), - result); - } - return result; - }; + template UpdateCompProperties check_component_independence(ConstDataset const& update_data) const { + UpdateCompProperties properties; + properties.name = CompType::name; + auto const component_idx = update_data.find_component(properties.name, false); + properties.is_columnar = update_data.is_columnar(properties.name); + properties.dense = update_data.is_dense(properties.name); + properties.uniform = update_data.is_uniform(properties.name); + properties.has_any_elements = + component_idx != invalid_index && update_data.get_component_info(component_idx).total_elements > 0; + properties.elements_ps_in_update = + properties.uniform ? update_data.uniform_elements_per_scenario(properties.name) : invalid_index; + properties.elements_in_base = this->component_count(); + + if (properties.is_columnar) { + process_buffer_span( + update_data.template get_columnar_buffer_span_all_scenarios(), + properties); + } else { + process_buffer_span( + update_data.template get_buffer_span_all_scenarios(), properties); + } - return check_each_component(); + return properties; } UpdateCompIndependence check_components_independence(ConstDataset const& update_data) const { // check and return indenpendence of all components return run_functor_with_all_types_return_array( - [this, &update_data]() { return this->check_components_independence(update_data); }); + [this, &update_data]() { return this->check_component_independence(update_data); }); } ComponentFlags is_update_independent(ConstDataset const& update_data) { @@ -1271,24 +1269,6 @@ class MainModelImpl, ComponentLis } } - template - static auto calculate_param(auto const& c, auto const&... extra_args) - requires requires { - { c.calc_param(extra_args...) }; - } - { - return c.calc_param(extra_args...); - } - - template - static auto calculate_param(auto const& c, auto const&... extra_args) - requires requires { - { c.template calc_param(extra_args...) }; - } - { - return c.template calc_param(extra_args...); - } - template ::*component), class Component> static void prepare_input_status(MainModelState const& state, std::vector const& objects, std::vector>& input) { @@ -1402,7 +1382,8 @@ class MainModelImpl, ComponentLis } } - auto fault_coup = std::vector(state_.components.template size(), Idx2D{isolated_component, not_connected}); + auto fault_coup = + std::vector(state_.components.template size(), Idx2D{isolated_component, not_connected}); std::vector sc_input(n_math_solvers_); for (Idx i = 0; i != n_math_solvers_; ++i) { @@ -1502,4 +1483,22 @@ class MainModelImpl, ComponentLis } }; +template +static auto calculate_param(auto const& c, auto const&... extra_args) + requires requires { + { c.calc_param(extra_args...) }; + } +{ + return c.calc_param(extra_args...); +} + +template +static auto calculate_param(auto const& c, auto const&... extra_args) + requires requires { + { c.template calc_param(extra_args...) }; + } +{ + return c.template calc_param(extra_args...); +} + } // namespace power_grid_model From 4640a904da0fd4e366ebd012468545dcbca81a1f Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Mon, 11 Nov 2024 13:42:57 +0100 Subject: [PATCH 04/30] make MSVC happy Signed-off-by: Santiago Figueroa Manrique --- .../include/power_grid_model/main_model_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 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 1e5a5185e..857bf9c31 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 @@ -796,12 +796,12 @@ class MainModelImpl, ComponentLis template void process_buffer_span(auto const& all_spans, UpdateCompProperties& properties) const { properties.ids_all_na = std::ranges::all_of(all_spans, [this](auto const& vec) { - return std::ranges::all_of(vec, [this](auto const& item) { return this->template check_id_na(item); }); + return std::ranges::all_of(vec, [this](auto const& item) { return this->check_id_na(item); }); }); properties.ids_part_na = std::ranges::any_of(all_spans, [this](auto const& vec) { return std::ranges::any_of(vec, [this](auto const& item) { - return this->template check_id_na(item); + return this->check_id_na(item); }); }) && !properties.ids_all_na; From 9cdb0d6e35f3837d2f78c1d4f20632c41dbc981e Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Tue, 12 Nov 2024 10:57:20 +0100 Subject: [PATCH 05/30] minor update_component refactor Signed-off-by: Santiago Figueroa Manrique --- .../include/power_grid_model/main_model.hpp | 5 ++-- .../power_grid_model/main_model_impl.hpp | 30 +++++++++---------- .../power_grid_model_c/src/model.cpp | 2 +- .../cpp_integration_tests/test_main_model.cpp | 30 +++++++++---------- .../test_main_model_se.cpp | 2 +- 5 files changed, 34 insertions(+), 35 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp index 642e8d5d2..0d3c9d291 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp @@ -5,6 +5,7 @@ #pragma once #include "main_model_impl.hpp" +#include namespace power_grid_model { @@ -66,8 +67,8 @@ class MainModel { impl().add_component(components); } - template void update_component(ConstDataset const& update_data) { - impl().update_component(update_data); + template void update_components(ConstDataset const& update_data) { + impl().update_components(update_data); } template 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 857bf9c31..b0fad854b 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 @@ -281,7 +281,7 @@ class MainModelImpl, ComponentLis } } - // helper function to update vectors of components + // update all components of a single type across all scenarios template void update_component(std::vector const& components, std::span sequence_idx) { @@ -304,8 +304,9 @@ class MainModelImpl, ComponentLis } } + // helper for row or columnar-based components template - void update_component(ConstDataset const& update_data, Idx pos, std::span sequence_idx) { + void update_component_row_col(ConstDataset const& update_data, Idx pos, std::span sequence_idx) { assert(construction_complete_); assert(update_data.get_description().dataset->name == std::string_view("update")); @@ -318,21 +319,18 @@ class MainModelImpl, ComponentLis } } - // update all components - template - void update_component(ConstDataset const& update_data, Idx pos, SequenceIdxView const& sequence_idx_map) { + // update all components across all scenarios + template + requires(std::same_as || std::same_as) + void update_components(ConstDataset const& update_data, Idx pos, SequenceIdxMap const& sequence_idx_map) { run_functor_with_all_types_return_void([this, pos, &update_data, &sequence_idx_map]() { - this->update_component(update_data, pos, std::get>(sequence_idx_map)); + this->update_component_row_col(update_data, pos, + std::get>(sequence_idx_map)); }); } - template - void update_component(ConstDataset const& update_data, Idx pos, SequenceIdx const& sequence_idx_map) { - run_functor_with_all_types_return_void([this, pos, &update_data, &sequence_idx_map]() { - this->update_component(update_data, pos, std::get>(sequence_idx_map)); - }); - } - template void update_component(ConstDataset const& update_data) { - update_component(update_data, 0, get_sequence_idx_map(update_data.get_individual_scenario(0))); + // update all components in the first scenario (e.g. permanent update) + template void update_components(ConstDataset const& update_data) { + update_components(update_data, 0, get_sequence_idx_map(update_data.get_individual_scenario(0))); } template void restore_component(SequenceIdxView const& sequence_idx) { @@ -736,7 +734,7 @@ class MainModelImpl, ComponentLis current_scenario_sequence_cache = model.get_sequence_idx_map(update_data, scenario_idx, do_update_cache_); - model.template update_component(update_data, scenario_idx, scenario_sequence()); + model.template update_components(update_data, scenario_idx, scenario_sequence()); }, [&model, scenario_sequence, ¤t_scenario_sequence_cache, &infos](Idx scenario_idx) { Timer const t_update_model(infos[scenario_idx], 1201, "Restore model"); @@ -904,7 +902,7 @@ class MainModelImpl, ComponentLis return optimizer::get_optimizer( options.optimizer_type, options.optimizer_strategy, calculator, - [this](ConstDataset update_data) { this->update_component(update_data); }, + [this](ConstDataset update_data) { this->update_components(update_data); }, *meta_data_, search_method) ->optimize(state_, options.calculation_method); } diff --git a/power_grid_model_c/power_grid_model_c/src/model.cpp b/power_grid_model_c/power_grid_model_c/src/model.cpp index d8741bf11..fa4f5c521 100644 --- a/power_grid_model_c/power_grid_model_c/src/model.cpp +++ b/power_grid_model_c/power_grid_model_c/src/model.cpp @@ -35,7 +35,7 @@ PGM_PowerGridModel* PGM_create_model(PGM_Handle* handle, double system_frequency // update model void PGM_update_model(PGM_Handle* handle, PGM_PowerGridModel* model, PGM_ConstDataset const* update_dataset) { call_with_catch( - handle, [model, update_dataset] { model->update_component(*update_dataset); }, + handle, [model, update_dataset] { model->update_components(*update_dataset); }, PGM_regular_error); } diff --git a/tests/cpp_integration_tests/test_main_model.cpp b/tests/cpp_integration_tests/test_main_model.cpp index baa07ccfa..baf63e3b3 100644 --- a/tests/cpp_integration_tests/test_main_model.cpp +++ b/tests/cpp_integration_tests/test_main_model.cpp @@ -808,7 +808,7 @@ TEST_CASE_TEMPLATE("Test main model - unknown id", settings, regular_update, cac std::vector const source_update2{SourceUpdate{100, true, nan, nan}}; ConstDataset update_data{false, 1, "update", meta_data::meta_data_gen::meta_data}; update_data.add_buffer("source", source_update2.size(), source_update2.size(), nullptr, source_update2.data()); - CHECK_THROWS_AS((main_model.update_component(update_data)), IDNotFound); + CHECK_THROWS_AS((main_model.update_components(update_data)), IDNotFound); } TEST_CASE_TEMPLATE("Test main model - update only load", settings, regular_update, cached_update) { @@ -820,7 +820,7 @@ TEST_CASE_TEMPLATE("Test main model - update only load", settings, regular_updat state.sym_load_update.data()); update_data.add_buffer("asym_load", state.asym_load_update.size(), state.asym_load_update.size(), nullptr, state.asym_load_update.data()); - main_model.update_component(update_data); + main_model.update_components(update_data); SUBCASE("Symmetrical") { auto const solver_output = @@ -868,7 +868,7 @@ TEST_CASE_TEMPLATE("Test main model - update load and shunt param", settings, re state.asym_load_update.data()); update_data.add_buffer("shunt", state.shunt_update.size(), state.shunt_update.size(), nullptr, state.shunt_update.data()); - main_model.update_component(update_data); + main_model.update_components(update_data); SUBCASE("Symmetrical") { auto const solver_output = @@ -923,7 +923,7 @@ TEST_CASE_TEMPLATE("Test main model - all updates", settings, regular_update, ca update_data.add_buffer("fault", state.fault_update.size(), state.fault_update.size(), nullptr, state.fault_update.data()); - main_model.update_component(update_data); + main_model.update_components(update_data); SUBCASE("Symmetrical") { auto const solver_output = @@ -974,7 +974,7 @@ TEST_CASE_TEMPLATE("Test main model - single permanent update from batch", setti update_data.add_buffer("link", 1, state.batch_link_update.size(), nullptr, state.batch_link_update.data()); update_data.add_buffer("fault", 1, state.batch_fault_update.size(), nullptr, state.batch_fault_update.data()); - main_model.update_component(update_data); + main_model.update_components(update_data); SUBCASE("Symmetrical") { auto const solver_output = @@ -1023,7 +1023,7 @@ TEST_CASE_TEMPLATE("Test main model - restore components", settings, regular_upd update_data.add_buffer("asym_load", state.asym_load_update.size(), state.asym_load_update.size(), nullptr, state.asym_load_update.data()); - main_model.update_component(update_data); + main_model.update_components(update_data); main_model.restore_components(update_data); SUBCASE("Symmetrical") { @@ -1119,7 +1119,7 @@ TEST_CASE_TEMPLATE("Test main model - updates w/ alternating compute mode", sett state.shunt_update.data()); // This will lead to no topo change but param change - main_model.update_component(update_data); + main_model.update_components(update_data); auto const math_output_sym_1 = main_model.calculate(get_default_options(symmetric, CalculationMethod::linear)); @@ -1135,13 +1135,13 @@ TEST_CASE_TEMPLATE("Test main model - updates w/ alternating compute mode", sett if constexpr (std::same_as) { SUBCASE("No new parameter change") { // Math state may be fully cached due to no change - main_model.update_component(update_data); + main_model.update_components(update_data); } } SUBCASE("With parameter change") { // Restore to original state and re-apply same update: causes param change for cached update main_model.restore_components(update_data); - main_model.update_component(update_data); + main_model.update_components(update_data); } auto const math_output_asym_2 = @@ -1231,7 +1231,7 @@ TEST_CASE("Test main model - runtime dispatch") { CHECK(state.asym_node[2].u_pu(2) == doctest::Approx(test::u1)); // update and calculation - model.update_component(update_data); + model.update_components(update_data); model.calculate(get_default_options(symmetric, newton_raphson), sym_result_data); CHECK(state.sym_node[0].u_pu == doctest::Approx(1.05)); CHECK(state.sym_node[1].u_pu == doctest::Approx(1.05)); @@ -1401,8 +1401,8 @@ TEST_CASE("Test main model - runtime dispatch") { 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); + row_based_model.update_components(update_data_with_rows); + columnar_model.update_components(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()); @@ -1455,8 +1455,8 @@ TEST_CASE("Test main model - runtime dispatch") { MainModel columnar_model_w_id{base_model}; MainModel columnar_model_wo_id{base_model}; - columnar_model_w_id.update_component(update_data_with_ids); - columnar_model_wo_id.update_component(update_data_without_ids); + columnar_model_w_id.update_components(update_data_with_ids); + columnar_model_wo_id.update_components(update_data_without_ids); std::vector node_output_columnar_w_id(state.node_input.size()); std::vector node_output_columnar_wo_id(state.node_input.size()); @@ -1496,7 +1496,7 @@ TEST_CASE("Test main model - runtime dispatch") { MainModel base_model{50.0, input_data}; MainModel columnar_model{base_model}; - columnar_model.update_component(update_data_with_columns); + columnar_model.update_components(update_data_with_columns); std::vector node_output_from_base(state.node_input.size()); std::vector node_output_from_columnar(state.node_input.size()); diff --git a/tests/cpp_integration_tests/test_main_model_se.cpp b/tests/cpp_integration_tests/test_main_model_se.cpp index d68784cdd..1ad636d4f 100644 --- a/tests/cpp_integration_tests/test_main_model_se.cpp +++ b/tests/cpp_integration_tests/test_main_model_se.cpp @@ -331,7 +331,7 @@ TEST_CASE_TEMPLATE("Test main model - state estimation", CalcMethod, IterativeLi SUBCASE("State Estimation") { MainModel test_model{50.0, input_data}; MainModel ref_model{50.0, input_data}; - ref_model.update_component(update_data); + ref_model.update_components(update_data); SUBCASE("Symmetric Calculation") { std::vector> test_node_output(1); From a118af8a6306d6cb1d40c80949c9f661e2b35853 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Tue, 12 Nov 2024 16:37:45 +0100 Subject: [PATCH 06/30] main model utils introduced Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_model_impl.hpp | 50 ++++++++----------- .../power_grid_model/main_model_utils.hpp | 22 ++++++++ 2 files changed, 44 insertions(+), 28 deletions(-) create mode 100644 power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp 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 b0fad854b..de2a59146 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 @@ -11,6 +11,7 @@ #include "calculation_parameters.hpp" #include "container.hpp" #include "main_model_fwd.hpp" +#include "main_model_utils.hpp" #include "topology.hpp" // common @@ -131,7 +132,7 @@ class MainModelImpl, ComponentLis template static constexpr size_t index_of_component = container_impl::get_cls_pos_v; - static constexpr size_t n_types = sizeof...(ComponentType); + static constexpr size_t n_types = n_component_types; using SequenceIdx = std::array, n_types>; using SequenceIdxView = std::array, n_types>; @@ -176,15 +177,6 @@ class MainModelImpl, ComponentLis static constexpr Idx not_connected{-1}; static constexpr Idx sequential{-1}; - protected: - // run functors with all component types - template static constexpr void run_functor_with_all_types_return_void(Functor functor) { - (functor.template operator()(), ...); - } - template static constexpr auto run_functor_with_all_types_return_array(Functor functor) { - return std::array { functor.template operator()()... }; - } - public: using Options = MainModelOptions; @@ -211,7 +203,7 @@ class MainModelImpl, ComponentLis auto const get_comp_count = [this]() -> ComponentCountInBase { return make_pair(std::string{CT::name}, this->component_count()); }; - auto const all_count = run_functor_with_all_types_return_array(get_comp_count); + auto const all_count = run_functor_with_all_types_return_array(get_comp_count); std::map> result; for (auto const& [name, count] : all_count) { if (count > 0) { @@ -251,7 +243,7 @@ class MainModelImpl, ComponentLis this->add_component(input_data.get_buffer_span(pos)); } }; - run_functor_with_all_types_return_void(add_func); + run_functor_with_all_types_return_void(add_func); } // template to update components @@ -323,10 +315,11 @@ class MainModelImpl, ComponentLis template requires(std::same_as || std::same_as) void update_components(ConstDataset const& update_data, Idx pos, SequenceIdxMap const& sequence_idx_map) { - run_functor_with_all_types_return_void([this, pos, &update_data, &sequence_idx_map]() { - this->update_component_row_col(update_data, pos, - std::get>(sequence_idx_map)); - }); + run_functor_with_all_types_return_void( + [this, pos, &update_data, &sequence_idx_map]() { + this->update_component_row_col(update_data, pos, + std::get>(sequence_idx_map)); + }); } // update all components in the first scenario (e.g. permanent update) template void update_components(ConstDataset const& update_data) { @@ -410,7 +403,7 @@ class MainModelImpl, ComponentLis [&state](ID id) { return main_core::get_component_idx_by_id(state, id).pos; }); } }; - run_functor_with_all_types_return_void(get_index_func); + run_functor_with_all_types_return_void(get_index_func); } // get sequence idx map of a certain batch scenario @@ -433,14 +426,15 @@ class MainModelImpl, ComponentLis SequenceIdx get_sequence_idx_map(ConstDataset const& update_data, Idx scenario_idx, ComponentFlags const& to_store) const { // TODO: (jguo) this function could be encapsulated in UpdateCompIndependence in update.hpp - return run_functor_with_all_types_return_array([this, scenario_idx, &update_data, &to_store]() { - if (!std::get>(to_store)) { - return std::vector{}; - } - auto const independence = check_component_independence(update_data); - validate_update_data_independence(independence); - return get_component_sequence(update_data, scenario_idx, independence); - }); + return run_functor_with_all_types_return_array( + [this, scenario_idx, &update_data, &to_store]() { + if (!std::get>(to_store)) { + return std::vector{}; + } + auto const independence = check_component_independence(update_data); + validate_update_data_independence(independence); + return get_component_sequence(update_data, scenario_idx, independence); + }); } // get sequence idx map of an entire batch for fast caching of component sequences SequenceIdx get_sequence_idx_map(ConstDataset const& update_data, ComponentFlags const& to_store) const { @@ -717,7 +711,7 @@ class MainModelImpl, ComponentLis auto const scenario_sequence = [&all_scenario_sequence, ¤t_scenario_sequence_cache, &independence_flags]() -> SequenceIdxView { - return run_functor_with_all_types_return_array( + return run_functor_with_all_types_return_array( [&all_scenario_sequence, ¤t_scenario_sequence_cache, &independence_flags]() { constexpr auto comp_idx = index_of_component; if (std::get(independence_flags)) { @@ -849,7 +843,7 @@ class MainModelImpl, ComponentLis UpdateCompIndependence check_components_independence(ConstDataset const& update_data) const { // check and return indenpendence of all components - return run_functor_with_all_types_return_array( + return run_functor_with_all_types_return_array( [this, &update_data]() { return this->check_component_independence(update_data); }); } @@ -976,7 +970,7 @@ class MainModelImpl, ComponentLis }; Timer const t_output(calculation_info_, 3000, "Produce output"); - run_functor_with_all_types_return_void(output_func); + run_functor_with_all_types_return_void(output_func); } CalculationInfo calculation_info() const { return calculation_info_; } diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp new file mode 100644 index 000000000..4ee5d4776 --- /dev/null +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Contributors to the Power Grid Model project +// +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "all_components.hpp" + +// main model class +namespace power_grid_model { + +template constexpr size_t n_component_types = sizeof...(ComponentType); + +// run functors with all component types +template constexpr void run_functor_with_all_types_return_void(Functor functor) { + (functor.template operator()(), ...); +} +template constexpr auto run_functor_with_all_types_return_array(Functor functor) { + return std::array { functor.template operator()()... }; +} + +} // namespace power_grid_model \ No newline at end of file From ba0a0b8c2d962a2758302847a6eabd52ba5fcefe Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Tue, 12 Nov 2024 17:14:38 +0100 Subject: [PATCH 07/30] moved check_id_na Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 12 +++++++++++ .../power_grid_model/main_model_impl.hpp | 20 +++++-------------- 2 files changed, 17 insertions(+), 15 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 653ac9497..4d1a68b79 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 @@ -26,6 +26,16 @@ inline void iterate_component_sequence(Func&& func, ForwardIterator begin, Forwa func(*it, sequence_idx[seq]); } } + +template bool check_id_na(T const& obj) { + if constexpr (requires { obj.id; }) { + return is_nan(obj.id); + } else if constexpr (requires { obj.get().id; }) { + return is_nan(obj.get().id); + } else { + throw UnreachableHit{"check_component_independence", "Only components with id are supported"}; + } +} } // namespace detail template const& state, Forw get_component_sequence(state, begin, end)); } +//////////////////////// + } // namespace power_grid_model::main_core 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 de2a59146..18e2b7622 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 @@ -775,25 +775,15 @@ class MainModelImpl, ComponentLis public: template using UpdateType = typename Component::UpdateType; - template bool check_id_na(T const& obj) const { - if constexpr (requires { obj.id; }) { - return is_nan(obj.id); - } else if constexpr (requires { obj.get().id; }) { - return is_nan(obj.get().id); - } else { - throw UnreachableHit{"check_component_independence", "Only components with id are supported"}; - } - } - template void process_buffer_span(auto const& all_spans, UpdateCompProperties& properties) const { - properties.ids_all_na = std::ranges::all_of(all_spans, [this](auto const& vec) { - return std::ranges::all_of(vec, [this](auto const& item) { return this->check_id_na(item); }); + properties.ids_all_na = std::ranges::all_of(all_spans, [](auto const& vec) { + return std::ranges::all_of(vec, [](auto const& item) { return main_core::detail::check_id_na(item); }); }); properties.ids_part_na = std::ranges::any_of(all_spans, - [this](auto const& vec) { - return std::ranges::any_of(vec, [this](auto const& item) { - return this->check_id_na(item); + [](auto const& vec) { + return std::ranges::any_of(vec, [](auto const& item) { + return main_core::detail::check_id_na(item); }); }) && !properties.ids_all_na; From 7688198f83db4ae3c201dd67981a6b6ae2508136 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Tue, 12 Nov 2024 17:32:22 +0100 Subject: [PATCH 08/30] moved UpdateCompProperties and process_buffer_span Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 59 ++++++++++++++ .../power_grid_model/main_model_impl.hpp | 77 +++---------------- 2 files changed, 69 insertions(+), 67 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 4d1a68b79..05b1f2ee1 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 @@ -142,4 +142,63 @@ inline void update_inverse(MainModelState const& state, Forw //////////////////////// +static constexpr Idx invalid_index{-1}; + +struct UpdateCompProperties { + std::string name{}; + bool has_any_elements{false}; // whether the component has any elements in the update data + bool ids_all_na{false}; // whether all ids are all NA + bool ids_part_na{false}; // whether some ids are NA but some are not + bool dense{false}; // whether the component is dense + bool uniform{false}; // whether the component is uniform + bool is_columnar{false}; // whether the component is columnar + bool update_ids_match{false}; // whether the ids match + Idx elements_ps_in_update{invalid_index}; // count of elements for this component per scenario in update + Idx elements_in_base{invalid_index}; // count of elements for this component per scenario in input + + constexpr bool no_id() const { return !has_any_elements || ids_all_na; } + constexpr bool qualify_for_optional_id() const { + return update_ids_match && ids_all_na && uniform && elements_ps_in_update == elements_in_base; + } + constexpr bool provided_ids_valid() const { + return is_empty_component() || (update_ids_match && !(ids_all_na || ids_part_na)); + } + constexpr bool is_empty_component() const { return !has_any_elements; } + constexpr bool is_independent() const { return qualify_for_optional_id() || provided_ids_valid(); } + constexpr Idx get_n_elements() const { + assert(uniform || elements_ps_in_update == invalid_index); + + return qualify_for_optional_id() ? elements_ps_in_update : na_Idx; + } +}; + +template void process_buffer_span(auto const& all_spans, UpdateCompProperties& properties) { + properties.ids_all_na = std::ranges::all_of(all_spans, [](auto const& vec) { + return std::ranges::all_of(vec, [](auto const& item) { return detail::check_id_na(item); }); + }); + properties.ids_part_na = std::ranges::any_of(all_spans, + [](auto const& vec) { + return std::ranges::any_of(vec, [](auto const& item) { + return detail::check_id_na(item); + }); + }) && + !properties.ids_all_na; + + if (all_spans.empty()) { + properties.update_ids_match = true; + } else { + // Remember the begin iterator of the first scenario, then loop over the remaining scenarios and + // check the ids + auto const first_span = all_spans[0]; + // check the subsequent scenarios + // only return true if all scenarios match the ids of the first batch + properties.update_ids_match = + std::ranges::all_of(all_spans.cbegin() + 1, all_spans.cend(), [&first_span](auto const& current_span) { + return std::ranges::equal(current_span, first_span, + [](ComponentType::UpdateType const& obj, + ComponentType::UpdateType const& first) { return obj.id == first.id; }); + }); + } +} + } // namespace power_grid_model::main_core 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 18e2b7622..f7c0ac31f 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 @@ -139,40 +139,12 @@ class MainModelImpl, ComponentLis using OwnedUpdateDataset = std::tuple...>; - struct UpdateCompProperties { - std::string name{}; - bool has_any_elements{false}; // whether the component has any elements in the update data - bool ids_all_na{false}; // whether all ids are all NA - bool ids_part_na{false}; // whether some ids are NA but some are not - bool dense{false}; // whether the component is dense - bool uniform{false}; // whether the component is uniform - bool is_columnar{false}; // whether the component is columnar - bool update_ids_match{false}; // whether the ids match - Idx elements_ps_in_update{invalid_index}; // count of elements for this component per scenario in update - Idx elements_in_base{invalid_index}; // count of elements for this component per scenario in input - - constexpr bool no_id() const { return !has_any_elements || ids_all_na; } - constexpr bool qualify_for_optional_id() const { - return update_ids_match && ids_all_na && uniform && elements_ps_in_update == elements_in_base; - } - constexpr bool provided_ids_valid() const { - return is_empty_component() || (update_ids_match && !(ids_all_na || ids_part_na)); - } - constexpr bool is_empty_component() const { return !has_any_elements; } - constexpr bool is_independent() const { return qualify_for_optional_id() || provided_ids_valid(); } - constexpr Idx get_n_elements() const { - assert(uniform || elements_ps_in_update == invalid_index); - - return qualify_for_optional_id() ? elements_ps_in_update : na_Idx; - } - }; - using UpdateCompIndependence = std::array; + using UpdateCompIndependence = std::array; using ComponentFlags = std::array; using ComponentCountInBase = std::pair; // TODO: (figueroa1395) probably move to common.hpp or somewhere else static constexpr Idx ignore_output{-1}; - static constexpr Idx invalid_index{-1}; static constexpr Idx isolated_component{-1}; static constexpr Idx not_connected{-1}; static constexpr Idx sequential{-1}; @@ -409,7 +381,7 @@ class MainModelImpl, ComponentLis // get sequence idx map of a certain batch scenario template std::vector get_component_sequence(ConstDataset const& update_data, Idx scenario_idx, - UpdateCompProperties const& comp_independence = {}) const { + main_core::UpdateCompProperties const& comp_independence = {}) const { // TODO: (jguo) this function could be encapsulated in UpdateCompProperties in update.hpp auto const get_sequence = [this, n_comp_elements = comp_independence.get_n_elements()](auto const& span) { return main_core::get_component_sequence(state_, std::begin(span), std::end(span), @@ -773,50 +745,21 @@ class MainModelImpl, ComponentLis } public: + // TODO: (figueroa1395) may need to move this to update.hpp or make something similar template using UpdateType = typename Component::UpdateType; - template - void process_buffer_span(auto const& all_spans, UpdateCompProperties& properties) const { - properties.ids_all_na = std::ranges::all_of(all_spans, [](auto const& vec) { - return std::ranges::all_of(vec, [](auto const& item) { return main_core::detail::check_id_na(item); }); - }); - properties.ids_part_na = std::ranges::any_of(all_spans, - [](auto const& vec) { - return std::ranges::any_of(vec, [](auto const& item) { - return main_core::detail::check_id_na(item); - }); - }) && - !properties.ids_all_na; - - if (all_spans.empty()) { - properties.update_ids_match = true; - } else { - // Remember the begin iterator of the first scenario, then loop over the remaining scenarios and - // check the ids - auto const first_span = all_spans[0]; - // check the subsequent scenarios - // only return true if all scenarios match the ids of the first batch - properties.update_ids_match = - std::ranges::all_of(all_spans.cbegin() + 1, all_spans.cend(), [&first_span](auto const& current_span) { - return std::ranges::equal(current_span, first_span, - [](UpdateType const& obj, UpdateType const& first) { - return obj.id == first.id; - }); - }); - } - } - - template UpdateCompProperties check_component_independence(ConstDataset const& update_data) const { - UpdateCompProperties properties; + template + main_core::UpdateCompProperties check_component_independence(ConstDataset const& update_data) const { + main_core::UpdateCompProperties properties; properties.name = CompType::name; auto const component_idx = update_data.find_component(properties.name, false); properties.is_columnar = update_data.is_columnar(properties.name); properties.dense = update_data.is_dense(properties.name); properties.uniform = update_data.is_uniform(properties.name); - properties.has_any_elements = - component_idx != invalid_index && update_data.get_component_info(component_idx).total_elements > 0; + properties.has_any_elements = component_idx != main_core::invalid_index && + update_data.get_component_info(component_idx).total_elements > 0; properties.elements_ps_in_update = - properties.uniform ? update_data.uniform_elements_per_scenario(properties.name) : invalid_index; + properties.uniform ? update_data.uniform_elements_per_scenario(properties.name) : main_core::invalid_index; properties.elements_in_base = this->component_count(); if (properties.is_columnar) { @@ -844,7 +787,7 @@ class MainModelImpl, ComponentLis return result; } - void validate_update_data_independence(UpdateCompProperties const& comp) const { + void validate_update_data_independence(main_core::UpdateCompProperties const& comp) const { if (comp.is_empty_component()) { return; // empty dataset is still supported } From 15a62c92708a387f2c399fb77d31cafdcfd5bac0 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Tue, 12 Nov 2024 18:05:55 +0100 Subject: [PATCH 09/30] moved check_component_independence Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 33 +++++++++++++++-- .../power_grid_model/main_model_impl.hpp | 37 ++++--------------- 2 files changed, 37 insertions(+), 33 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 05b1f2ee1..e434716a1 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 @@ -172,7 +172,7 @@ struct UpdateCompProperties { } }; -template void process_buffer_span(auto const& all_spans, UpdateCompProperties& properties) { +template void process_buffer_span(auto const& all_spans, UpdateCompProperties& properties) { properties.ids_all_na = std::ranges::all_of(all_spans, [](auto const& vec) { return std::ranges::all_of(vec, [](auto const& item) { return detail::check_id_na(item); }); }); @@ -195,10 +195,37 @@ template void process_buffer_span(auto const& all_spans properties.update_ids_match = std::ranges::all_of(all_spans.cbegin() + 1, all_spans.cend(), [&first_span](auto const& current_span) { return std::ranges::equal(current_span, first_span, - [](ComponentType::UpdateType const& obj, - ComponentType::UpdateType const& first) { return obj.id == first.id; }); + [](CompType::UpdateType const& obj, CompType::UpdateType const& first) { + return obj.id == first.id; + }); }); } } +template +UpdateCompProperties check_component_independence(ConstDataset const& update_data, Idx const n_component) { + UpdateCompProperties properties; + properties.name = CompType::name; + auto const component_idx = update_data.find_component(properties.name, false); + properties.is_columnar = update_data.is_columnar(properties.name); + properties.dense = update_data.is_dense(properties.name); + properties.uniform = update_data.is_uniform(properties.name); + properties.has_any_elements = + component_idx != invalid_index && update_data.get_component_info(component_idx).total_elements > 0; + properties.elements_ps_in_update = + properties.uniform ? update_data.uniform_elements_per_scenario(properties.name) : invalid_index; + properties.elements_in_base = n_component; + + if (properties.is_columnar) { + process_buffer_span( + update_data.template get_columnar_buffer_span_all_scenarios(), + properties); + } else { + process_buffer_span( + update_data.template get_buffer_span_all_scenarios(), properties); + } + + return properties; +} + } // namespace power_grid_model::main_core 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 f7c0ac31f..55764688c 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 @@ -403,7 +403,8 @@ class MainModelImpl, ComponentLis if (!std::get>(to_store)) { return std::vector{}; } - auto const independence = check_component_independence(update_data); + auto const n_component = this->component_count(); + auto const independence = main_core::check_component_independence(update_data, n_component); validate_update_data_independence(independence); return get_component_sequence(update_data, scenario_idx, independence); }); @@ -745,39 +746,15 @@ class MainModelImpl, ComponentLis } public: - // TODO: (figueroa1395) may need to move this to update.hpp or make something similar + // TODO: (figueroa1395) may want to move this to update.hpp or make something similar there template using UpdateType = typename Component::UpdateType; - template - main_core::UpdateCompProperties check_component_independence(ConstDataset const& update_data) const { - main_core::UpdateCompProperties properties; - properties.name = CompType::name; - auto const component_idx = update_data.find_component(properties.name, false); - properties.is_columnar = update_data.is_columnar(properties.name); - properties.dense = update_data.is_dense(properties.name); - properties.uniform = update_data.is_uniform(properties.name); - properties.has_any_elements = component_idx != main_core::invalid_index && - update_data.get_component_info(component_idx).total_elements > 0; - properties.elements_ps_in_update = - properties.uniform ? update_data.uniform_elements_per_scenario(properties.name) : main_core::invalid_index; - properties.elements_in_base = this->component_count(); - - if (properties.is_columnar) { - process_buffer_span( - update_data.template get_columnar_buffer_span_all_scenarios(), - properties); - } else { - process_buffer_span( - update_data.template get_buffer_span_all_scenarios(), properties); - } - - return properties; - } - UpdateCompIndependence check_components_independence(ConstDataset const& update_data) const { // check and return indenpendence of all components - return run_functor_with_all_types_return_array( - [this, &update_data]() { return this->check_component_independence(update_data); }); + return run_functor_with_all_types_return_array([this, &update_data]() { + auto const n_component = this->component_count(); + return main_core::check_component_independence(update_data, n_component); + }); } ComponentFlags is_update_independent(ConstDataset const& update_data) { From 954e933b011057d295ebf2272e63aefc7506a51a Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Wed, 13 Nov 2024 09:48:53 +0100 Subject: [PATCH 10/30] clang tidy Signed-off-by: Santiago Figueroa Manrique --- .../include/power_grid_model/main_core/update.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 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 e434716a1..ae528b750 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 @@ -194,10 +194,11 @@ template void process_buffer_span(auto const& all_spans, Upd // only return true if all scenarios match the ids of the first batch properties.update_ids_match = std::ranges::all_of(all_spans.cbegin() + 1, all_spans.cend(), [&first_span](auto const& current_span) { - return std::ranges::equal(current_span, first_span, - [](CompType::UpdateType const& obj, CompType::UpdateType const& first) { - return obj.id == first.id; - }); + return std::ranges::equal( + current_span, first_span, + [](typename CompType::UpdateType const& obj, typename CompType::UpdateType const& first) { + return obj.id == first.id; + }); }); } } From 104c9fe27de18b3dbe964649b0ec2aefb0e3aa3a Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Wed, 13 Nov 2024 11:23:26 +0100 Subject: [PATCH 11/30] moved validate_update_independence and corrected namespace name Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 20 ++++++++ .../power_grid_model/main_model_impl.hpp | 48 ++++++------------- .../power_grid_model/main_model_utils.hpp | 4 +- 3 files changed, 37 insertions(+), 35 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 ae528b750..367dd13d8 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 @@ -229,4 +229,24 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat return properties; } +void validate_update_data_independence(UpdateCompProperties const& comp) { + if (comp.is_empty_component()) { + return; // empty dataset is still supported + } + auto const elements_ps = comp.get_n_elements(); + assert(comp.uniform || elements_ps < 0); + + if (elements_ps >= 0 && comp.elements_in_base < elements_ps) { + throw DatasetError("Update data has more elements per scenario than input data for component " + comp.name + + "!"); + } + if (comp.ids_part_na) { + throw DatasetError("Some IDs are not valid for component " + comp.name + " in update data!"); + } + if (comp.ids_all_na && comp.elements_in_base != elements_ps) { + throw DatasetError("Update data without IDs for component " + comp.name + + " has a different number of elements per scenario then input data!"); + } +} + } // namespace power_grid_model::main_core 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 55764688c..2261b9801 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 @@ -132,7 +132,7 @@ class MainModelImpl, ComponentLis template static constexpr size_t index_of_component = container_impl::get_cls_pos_v; - static constexpr size_t n_types = n_component_types; + static constexpr size_t n_types = main_core::utils::n_component_types; using SequenceIdx = std::array, n_types>; using SequenceIdxView = std::array, n_types>; @@ -175,7 +175,8 @@ class MainModelImpl, ComponentLis auto const get_comp_count = [this]() -> ComponentCountInBase { return make_pair(std::string{CT::name}, this->component_count()); }; - auto const all_count = run_functor_with_all_types_return_array(get_comp_count); + auto const all_count = + main_core::utils::run_functor_with_all_types_return_array(get_comp_count); std::map> result; for (auto const& [name, count] : all_count) { if (count > 0) { @@ -215,7 +216,7 @@ class MainModelImpl, ComponentLis this->add_component(input_data.get_buffer_span(pos)); } }; - run_functor_with_all_types_return_void(add_func); + main_core::utils::run_functor_with_all_types_return_void(add_func); } // template to update components @@ -287,7 +288,7 @@ class MainModelImpl, ComponentLis template requires(std::same_as || std::same_as) void update_components(ConstDataset const& update_data, Idx pos, SequenceIdxMap const& sequence_idx_map) { - run_functor_with_all_types_return_void( + main_core::utils::run_functor_with_all_types_return_void( [this, pos, &update_data, &sequence_idx_map]() { this->update_component_row_col(update_data, pos, std::get>(sequence_idx_map)); @@ -375,7 +376,7 @@ class MainModelImpl, ComponentLis [&state](ID id) { return main_core::get_component_idx_by_id(state, id).pos; }); } }; - run_functor_with_all_types_return_void(get_index_func); + main_core::utils::run_functor_with_all_types_return_void(get_index_func); } // get sequence idx map of a certain batch scenario @@ -398,14 +399,14 @@ class MainModelImpl, ComponentLis SequenceIdx get_sequence_idx_map(ConstDataset const& update_data, Idx scenario_idx, ComponentFlags const& to_store) const { // TODO: (jguo) this function could be encapsulated in UpdateCompIndependence in update.hpp - return run_functor_with_all_types_return_array( + return main_core::utils::run_functor_with_all_types_return_array( [this, scenario_idx, &update_data, &to_store]() { if (!std::get>(to_store)) { return std::vector{}; } auto const n_component = this->component_count(); auto const independence = main_core::check_component_independence(update_data, n_component); - validate_update_data_independence(independence); + main_core::validate_update_data_independence(independence); return get_component_sequence(update_data, scenario_idx, independence); }); } @@ -684,7 +685,7 @@ class MainModelImpl, ComponentLis auto const scenario_sequence = [&all_scenario_sequence, ¤t_scenario_sequence_cache, &independence_flags]() -> SequenceIdxView { - return run_functor_with_all_types_return_array( + return main_core::utils::run_functor_with_all_types_return_array( [&all_scenario_sequence, ¤t_scenario_sequence_cache, &independence_flags]() { constexpr auto comp_idx = index_of_component; if (std::get(independence_flags)) { @@ -751,10 +752,11 @@ class MainModelImpl, ComponentLis UpdateCompIndependence check_components_independence(ConstDataset const& update_data) const { // check and return indenpendence of all components - return run_functor_with_all_types_return_array([this, &update_data]() { - auto const n_component = this->component_count(); - return main_core::check_component_independence(update_data, n_component); - }); + return main_core::utils::run_functor_with_all_types_return_array( + [this, &update_data]() { + auto const n_component = this->component_count(); + return main_core::check_component_independence(update_data, n_component); + }); } ComponentFlags is_update_independent(ConstDataset const& update_data) { @@ -764,26 +766,6 @@ class MainModelImpl, ComponentLis return result; } - void validate_update_data_independence(main_core::UpdateCompProperties const& comp) const { - if (comp.is_empty_component()) { - return; // empty dataset is still supported - } - auto const elements_ps = comp.get_n_elements(); - assert(comp.uniform || elements_ps < 0); - - if (elements_ps >= 0 && comp.elements_in_base < elements_ps) { - throw DatasetError("Update data has more elements per scenario than input data for component " + comp.name + - "!"); - } - if (comp.ids_part_na) { - throw DatasetError("Some IDs are not valid for component " + comp.name + " in update data!"); - } - if (comp.ids_all_na && comp.elements_in_base != elements_ps) { - throw DatasetError("Update data without IDs for component " + comp.name + - " has a different number of elements per scenario then input data!"); - } - } - // Calculate with optimization, e.g., automatic tap changer template auto calculate(Options const& options) { auto const calculator = [this, &options] { @@ -880,7 +862,7 @@ class MainModelImpl, ComponentLis }; Timer const t_output(calculation_info_, 3000, "Produce output"); - run_functor_with_all_types_return_void(output_func); + main_core::utils::run_functor_with_all_types_return_void(output_func); } CalculationInfo calculation_info() const { return calculation_info_; } diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp index 4ee5d4776..16b17f509 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp @@ -7,7 +7,7 @@ #include "all_components.hpp" // main model class -namespace power_grid_model { +namespace power_grid_model::main_core::utils { template constexpr size_t n_component_types = sizeof...(ComponentType); @@ -19,4 +19,4 @@ template constexpr auto run_functor_with_all_typ return std::array { functor.template operator()()... }; } -} // namespace power_grid_model \ No newline at end of file +} // namespace power_grid_model::main_core::utils \ No newline at end of file From 5f94b0cf6075b386b84f55b7f74035138b5889ec Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Wed, 13 Nov 2024 13:18:42 +0100 Subject: [PATCH 12/30] actually solve merge conflicts Signed-off-by: Santiago Figueroa Manrique --- .../include/power_grid_model/main_model_impl.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 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 bd96da557..752535849 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 @@ -399,13 +399,14 @@ class MainModelImpl, ComponentLis SequenceIdx get_sequence_idx_map(ConstDataset const& update_data, Idx scenario_idx, ComponentFlags const& components_to_store) const { // TODO: (jguo) this function could be encapsulated in UpdateCompIndependence in update.hpp - return main_core::utils::run_functor_with_all_types_return_array( + return main_core::utils::run_functor_with_all_types_return_array( [this, scenario_idx, &update_data, &components_to_store]() { if (!std::get>(components_to_store)) { return std::vector{}; } - auto const independence = check_components_independence(update_data); - validate_update_data_independence(independence); + auto const n_component = this->component_count(); + auto const independence = main_core::check_component_independence(update_data, n_component); + main_core::validate_update_data_independence(independence); return get_component_sequence(update_data, scenario_idx, independence); }); } From c509044b900798b56abbedbdaaaa720e98cd1b61 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Wed, 13 Nov 2024 17:20:11 +0100 Subject: [PATCH 13/30] refactored is_update_independent Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 26 ++++++++++++++++++- .../power_grid_model/main_model_impl.hpp | 24 ++++------------- .../power_grid_model/main_model_utils.hpp | 3 ++- 3 files changed, 32 insertions(+), 21 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 367dd13d8..f73cd359d 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 @@ -8,6 +8,9 @@ #include "../all_components.hpp" #include "../common/iterator_like_concepts.hpp" +#include "../main_model_utils.hpp" + +#include namespace power_grid_model::main_core { @@ -229,7 +232,28 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat return properties; } -void validate_update_data_independence(UpdateCompProperties const& comp) { +template using ComponentFlags = std::array; + +template +ComponentFlags +is_update_independent(ConstDataset const& update_data, + std::map> const& relevant_component_count_map) { + ComponentFlags result{}; + size_t idx{}; + utils::run_functor_with_all_types_return_void( + [&result, &relevant_component_count_map, &update_data, &idx]() { + Idx n_component{}; + auto it = relevant_component_count_map.find(CompType::name); + if (it != relevant_component_count_map.end()) { + n_component = it->second; + } + result[idx] = check_component_independence(update_data, n_component).is_independent(); + ++idx; + }); + return result; +} + +inline void validate_update_data_independence(UpdateCompProperties const& comp) { if (comp.is_empty_component()) { return; // empty dataset is still supported } 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 752535849..45214433f 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 @@ -139,8 +139,7 @@ class MainModelImpl, ComponentLis using OwnedUpdateDataset = std::tuple...>; - using UpdateCompIndependence = std::array; - using ComponentFlags = std::array; + using ComponentFlags = std::array; // TODO: (figueroa1395) also in update.hpp ish using ComponentCountInBase = std::pair; // TODO: (figueroa1395) probably move to common.hpp or somewhere else @@ -581,7 +580,10 @@ class MainModelImpl, ComponentLis // cache component update order where possible. // the order for a cacheable (independent) component by definition is the same across all scenarios - auto const is_independent = is_update_independent(update_data); + // TODO: (figueroa1395): don't use string lookup, it is slow + std::map> const relevant_component_count_map = all_component_count(); + auto const is_independent = + main_core::is_update_independent(update_data, relevant_component_count_map); all_scenarios_sequence = get_sequence_idx_map(update_data, 0, is_independent); return [&base_model, &exceptions, &infos, &calculation_fn, &result_data, &update_data, @@ -750,22 +752,6 @@ class MainModelImpl, ComponentLis // TODO: (figueroa1395) may want to move this to update.hpp or make something similar there template using UpdateType = typename Component::UpdateType; - UpdateCompIndependence check_components_independence(ConstDataset const& update_data) const { - // check and return indenpendence of all components - return main_core::utils::run_functor_with_all_types_return_array( - [this, &update_data]() { - auto const n_component = this->component_count(); - return main_core::check_component_independence(update_data, n_component); - }); - } - - ComponentFlags is_update_independent(ConstDataset const& update_data) { - ComponentFlags result; - std::ranges::transform(check_components_independence(update_data), result.begin(), - [](auto const& comp) { return comp.is_independent(); }); - return result; - } - // Calculate with optimization, e.g., automatic tap changer template auto calculate(Options const& options) { auto const calculator = [this, &options] { diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp index 16b17f509..9a09e55f1 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp @@ -19,4 +19,5 @@ template constexpr auto run_functor_with_all_typ return std::array { functor.template operator()()... }; } -} // namespace power_grid_model::main_core::utils \ No newline at end of file +} // namespace power_grid_model::main_core::utils +// TODO: (figueroa1395) move to main_core under utils.hpp From 366b4248a4b485def74ed63e452bab9ef42d27b0 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Wed, 13 Nov 2024 17:59:31 +0100 Subject: [PATCH 14/30] removed string lookup Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 13 ++++--------- .../power_grid_model/main_model_impl.hpp | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 12 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 f73cd359d..c2ec21a72 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 @@ -235,18 +235,13 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat template using ComponentFlags = std::array; template -ComponentFlags -is_update_independent(ConstDataset const& update_data, - std::map> const& relevant_component_count_map) { +ComponentFlags is_update_independent(ConstDataset const& update_data, + std::span relevant_component_count) { ComponentFlags result{}; size_t idx{}; utils::run_functor_with_all_types_return_void( - [&result, &relevant_component_count_map, &update_data, &idx]() { - Idx n_component{}; - auto it = relevant_component_count_map.find(CompType::name); - if (it != relevant_component_count_map.end()) { - n_component = it->second; - } + [&result, &relevant_component_count, &update_data, &idx]() { + Idx n_component = relevant_component_count[idx]; result[idx] = check_component_independence(update_data, n_component).is_independent(); ++idx; }); 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 45214433f..72c13dcd1 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 @@ -186,6 +186,18 @@ class MainModelImpl, ComponentLis return result; } + // helper function to get the number of components per type + std::array get_n_components_per_type() const { + std::array result{}; + size_t idx{}; + main_core::utils::run_functor_with_all_types_return_void( + [&result, this, &idx]() { + result[idx] = this->component_count(); + ++idx; + }); + return result; + } + // helper function to add vectors of components template void add_component(std::vector const& components) { add_component(components.begin(), components.end()); @@ -580,10 +592,9 @@ class MainModelImpl, ComponentLis // cache component update order where possible. // the order for a cacheable (independent) component by definition is the same across all scenarios - // TODO: (figueroa1395): don't use string lookup, it is slow - std::map> const relevant_component_count_map = all_component_count(); + auto const relevant_component_count = get_n_components_per_type(); auto const is_independent = - main_core::is_update_independent(update_data, relevant_component_count_map); + main_core::is_update_independent(update_data, relevant_component_count); all_scenarios_sequence = get_sequence_idx_map(update_data, 0, is_independent); return [&base_model, &exceptions, &infos, &calculation_fn, &result_data, &update_data, From 44b4233dea43f17fbaeac51e1c5d1007731121cc Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Thu, 14 Nov 2024 08:09:54 +0100 Subject: [PATCH 15/30] moved get_component_sequence Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 22 ++++++++++++++++++- .../power_grid_model/main_model_impl.hpp | 19 +--------------- 2 files changed, 22 insertions(+), 19 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 c2ec21a72..3817fa755 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 @@ -145,6 +145,8 @@ inline void update_inverse(MainModelState const& state, Forw //////////////////////// +// TODO: (figueroa1395) encapsulate all this in a independence related namespace (might even be a good idea to move to a +// different file) static constexpr Idx invalid_index{-1}; struct UpdateCompProperties { @@ -175,6 +177,24 @@ struct UpdateCompProperties { } }; +// get sequence idx map of a certain batch scenario +template +std::vector get_component_sequence(MainModelState const& state, + ConstDataset const& update_data, Idx scenario_idx, + UpdateCompProperties const& comp_independence = {}) { + // TODO: (figueroa1395) this function could be encapsulated in UpdateCompProperties in update.hpp + auto const get_sequence = [&state, n_comp_elements = comp_independence.get_n_elements()](auto const& span) { + return get_component_sequence(state, std::begin(span), std::end(span), n_comp_elements); + }; + if (update_data.is_columnar(CompType::name)) { + auto const buffer_span = + update_data.get_columnar_buffer_span(scenario_idx); + return get_sequence(buffer_span); + } + auto const buffer_span = update_data.get_buffer_span(scenario_idx); + return get_sequence(buffer_span); +} + template void process_buffer_span(auto const& all_spans, UpdateCompProperties& properties) { properties.ids_all_na = std::ranges::all_of(all_spans, [](auto const& vec) { return std::ranges::all_of(vec, [](auto const& item) { return detail::check_id_na(item); }); @@ -241,7 +261,7 @@ ComponentFlags is_update_independent(ConstDataset const& updat size_t idx{}; utils::run_functor_with_all_types_return_void( [&result, &relevant_component_count, &update_data, &idx]() { - Idx n_component = relevant_component_count[idx]; + Idx const n_component = relevant_component_count[idx]; result[idx] = check_component_independence(update_data, n_component).is_independent(); ++idx; }); 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 72c13dcd1..405195318 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 @@ -390,23 +390,6 @@ class MainModelImpl, ComponentLis main_core::utils::run_functor_with_all_types_return_void(get_index_func); } - // get sequence idx map of a certain batch scenario - template - std::vector get_component_sequence(ConstDataset const& update_data, Idx scenario_idx, - main_core::UpdateCompProperties const& comp_independence = {}) const { - // TODO: (jguo) this function could be encapsulated in UpdateCompProperties in update.hpp - auto const get_sequence = [this, n_comp_elements = comp_independence.get_n_elements()](auto const& span) { - return main_core::get_component_sequence(state_, std::begin(span), std::end(span), - n_comp_elements); - }; - if (update_data.is_columnar(CompType::name)) { - auto const buffer_span = - update_data.get_columnar_buffer_span(scenario_idx); - return get_sequence(buffer_span); - } - auto const buffer_span = update_data.get_buffer_span(scenario_idx); - return get_sequence(buffer_span); - } SequenceIdx get_sequence_idx_map(ConstDataset const& update_data, Idx scenario_idx, ComponentFlags const& components_to_store) const { // TODO: (jguo) this function could be encapsulated in UpdateCompIndependence in update.hpp @@ -418,7 +401,7 @@ class MainModelImpl, ComponentLis auto const n_component = this->component_count(); auto const independence = main_core::check_component_independence(update_data, n_component); main_core::validate_update_data_independence(independence); - return get_component_sequence(update_data, scenario_idx, independence); + return main_core::get_component_sequence(state_, update_data, scenario_idx, independence); }); } // Get sequence idx map of an entire batch for fast caching of component sequences. From e4bf1a391b457e066c5df74ba372bf1d0664106a Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Thu, 14 Nov 2024 13:45:41 +0100 Subject: [PATCH 16/30] move get_sequence_idx_map Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 74 +++++++++++++++---- .../power_grid_model/main_model_impl.hpp | 51 +++++-------- 2 files changed, 76 insertions(+), 49 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 3817fa755..08f9aa143 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 @@ -4,6 +4,7 @@ #pragma once +#include "../container.hpp" #include "state.hpp" #include "../all_components.hpp" @@ -30,6 +31,7 @@ inline void iterate_component_sequence(Func&& func, ForwardIterator begin, Forwa } } +// TODO: (figueroa1395) maybe move to detail namespace within independence namespace template bool check_id_na(T const& obj) { if constexpr (requires { obj.id; }) { return is_nan(obj.id); @@ -145,10 +147,14 @@ inline void update_inverse(MainModelState const& state, Forw //////////////////////// -// TODO: (figueroa1395) encapsulate all this in a independence related namespace (might even be a good idea to move to a -// different file) +// TODO: (figueroa1395) encapsulate all these in a independence related namespace (might even be a good idea to move to +// a different file) - UpdateCompIndependence +// TODO: (figueroa1395) reorganize this file to have the independence related functions together and in a way it makes +// sense. For now just dumping and refactoring things individually. static constexpr Idx invalid_index{-1}; +template using ComponentFlags = std::array; + struct UpdateCompProperties { std::string name{}; bool has_any_elements{false}; // whether the component has any elements in the update data @@ -182,7 +188,6 @@ template std::vector get_component_sequence(MainModelState const& state, ConstDataset const& update_data, Idx scenario_idx, UpdateCompProperties const& comp_independence = {}) { - // TODO: (figueroa1395) this function could be encapsulated in UpdateCompProperties in update.hpp auto const get_sequence = [&state, n_comp_elements = comp_independence.get_n_elements()](auto const& span) { return get_component_sequence(state, std::begin(span), std::end(span), n_comp_elements); }; @@ -195,6 +200,11 @@ std::vector get_component_sequence(MainModelState con return get_sequence(buffer_span); } +template using SequenceIdx = std::array, sizeof...(ComponentTypes)>; + +template +constexpr size_t index_of_component = container_impl::get_cls_pos_v; + template void process_buffer_span(auto const& all_spans, UpdateCompProperties& properties) { properties.ids_all_na = std::ranges::all_of(all_spans, [](auto const& vec) { return std::ranges::all_of(vec, [](auto const& item) { return detail::check_id_na(item); }); @@ -227,7 +237,7 @@ template void process_buffer_span(auto const& all_spans, Upd } template -UpdateCompProperties check_component_independence(ConstDataset const& update_data, Idx const n_component) { +UpdateCompProperties check_component_independence(ConstDataset const& update_data, Idx n_component) { UpdateCompProperties properties; properties.name = CompType::name; auto const component_idx = update_data.find_component(properties.name, false); @@ -252,18 +262,50 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat return properties; } -template using ComponentFlags = std::array; - -template -ComponentFlags is_update_independent(ConstDataset const& update_data, - std::span relevant_component_count) { - ComponentFlags result{}; - size_t idx{}; - utils::run_functor_with_all_types_return_void( - [&result, &relevant_component_count, &update_data, &idx]() { - Idx const n_component = relevant_component_count[idx]; - result[idx] = check_component_independence(update_data, n_component).is_independent(); - ++idx; +template +SequenceIdx get_sequence_idx_map(MainModelState const& state, + ConstDataset const& update_data, Idx scenario_idx, + ComponentFlags const& components_to_store, + std::span relevant_component_count) { + size_t comp_idx{}; + return utils::run_functor_with_all_types_return_array( + [&update_data, &components_to_store, &state, &relevant_component_count, scenario_idx, + &comp_idx]() { + if (!std::get>(components_to_store)) { + return std::vector{}; + } + Idx const n_component = relevant_component_count[comp_idx]; + ++comp_idx; + auto const independence = check_component_independence(update_data, n_component); + validate_update_data_independence(independence); + return get_component_sequence(state, update_data, scenario_idx, independence); + }); +} +// Get sequence idx map of an entire batch for fast caching of component sequences. +// The sequence idx map of the batch is the same as that of the first scenario in the batch (assuming homogeneity) +// This is the entry point for permanent updates. +template +SequenceIdx get_sequence_idx_map(MainModelState const& state, + ConstDataset const& update_data, + std::span relevant_component_count) { + constexpr ComponentFlags all_true = [] { + ComponentFlags result{}; + std::ranges::fill(result, true); + return result; + }(); + return get_sequence_idx_map(state, update_data, 0, all_true, relevant_component_count); +} + +template +ComponentFlags is_update_independent(ConstDataset const& update_data, + std::span relevant_component_count) { + ComponentFlags result{}; + size_t comp_idx{}; + utils::run_functor_with_all_types_return_void( + [&result, &relevant_component_count, &update_data, &comp_idx]() { + Idx const n_component = relevant_component_count[comp_idx]; + result[comp_idx] = check_component_independence(update_data, n_component).is_independent(); + ++comp_idx; }); return result; } 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 405195318..a924cffe9 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 @@ -129,6 +129,7 @@ class MainModelImpl, ComponentLis using MainModelState = main_core::MainModelState; using MathState = main_core::MathState; + // Move SequenceIdx, n_types, index_of_component and ComponentFlags to Utils template static constexpr size_t index_of_component = container_impl::get_cls_pos_v; @@ -139,10 +140,9 @@ class MainModelImpl, ComponentLis using OwnedUpdateDataset = std::tuple...>; - using ComponentFlags = std::array; // TODO: (figueroa1395) also in update.hpp ish + using ComponentFlags = std::array; using ComponentCountInBase = std::pair; - // TODO: (figueroa1395) probably move to common.hpp or somewhere else static constexpr Idx ignore_output{-1}; static constexpr Idx isolated_component{-1}; static constexpr Idx not_connected{-1}; @@ -187,8 +187,8 @@ class MainModelImpl, ComponentLis } // helper function to get the number of components per type - std::array get_n_components_per_type() const { - std::array result{}; + std::array get_n_components_per_type() const { + std::array result{}; size_t idx{}; main_core::utils::run_functor_with_all_types_return_void( [&result, this, &idx]() { @@ -307,7 +307,10 @@ class MainModelImpl, ComponentLis } // update all components in the first scenario (e.g. permanent update) template void update_components(ConstDataset const& update_data) { - update_components(update_data, 0, get_sequence_idx_map(update_data.get_individual_scenario(0))); + auto const relevant_component_count = get_n_components_per_type(); + auto const sequence_idx_map = main_core::get_sequence_idx_map( + state_, update_data.get_individual_scenario(0), relevant_component_count); + update_components(update_data, 0, sequence_idx_map); } template void restore_component(SequenceIdxView const& sequence_idx) { @@ -390,30 +393,10 @@ class MainModelImpl, ComponentLis main_core::utils::run_functor_with_all_types_return_void(get_index_func); } - SequenceIdx get_sequence_idx_map(ConstDataset const& update_data, Idx scenario_idx, - ComponentFlags const& components_to_store) const { - // TODO: (jguo) this function could be encapsulated in UpdateCompIndependence in update.hpp - return main_core::utils::run_functor_with_all_types_return_array( - [this, scenario_idx, &update_data, &components_to_store]() { - if (!std::get>(components_to_store)) { - return std::vector{}; - } - auto const n_component = this->component_count(); - auto const independence = main_core::check_component_independence(update_data, n_component); - main_core::validate_update_data_independence(independence); - return main_core::get_component_sequence(state_, update_data, scenario_idx, independence); - }); - } - // Get sequence idx map of an entire batch for fast caching of component sequences. - // The sequence idx map of the batch is the same as that of the first scenario in the batch (assuming homogeneity) - // This is the entry point for permanent updates. - SequenceIdx get_sequence_idx_map(ConstDataset const& update_data) const { - constexpr ComponentFlags all_true = [] { - ComponentFlags result{}; - std::ranges::fill(result, true); - return result; - }(); - return get_sequence_idx_map(update_data, 0, all_true); + // Entry point for main_model.hpp + template SequenceIdx get_sequence_idx_map(ConstDataset const& update_data) { + auto const relevant_component_count = get_n_components_per_type(); + return main_core::get_sequence_idx_map(state_, update_data, relevant_component_count); } private: @@ -578,7 +561,8 @@ class MainModelImpl, ComponentLis auto const relevant_component_count = get_n_components_per_type(); auto const is_independent = main_core::is_update_independent(update_data, relevant_component_count); - all_scenarios_sequence = get_sequence_idx_map(update_data, 0, is_independent); + all_scenarios_sequence = main_core::get_sequence_idx_map( + state_, update_data, 0, is_independent, relevant_component_count); return [&base_model, &exceptions, &infos, &calculation_fn, &result_data, &update_data, &all_scenarios_sequence = std::as_const(all_scenarios_sequence), @@ -695,8 +679,9 @@ class MainModelImpl, ComponentLis [&model, &update_data, scenario_sequence, ¤t_scenario_sequence_cache, do_update_cache_ = std::move(do_update_cache), &infos](Idx scenario_idx) { Timer const t_update_model(infos[scenario_idx], 1200, "Update model"); - current_scenario_sequence_cache = - model.get_sequence_idx_map(update_data, scenario_idx, do_update_cache_); + auto const relevant_component_count = model.get_n_components_per_type(); + current_scenario_sequence_cache = main_core::get_sequence_idx_map( + model.state_, update_data, scenario_idx, do_update_cache_, relevant_component_count); model.template update_components(update_data, scenario_idx, scenario_sequence()); }, @@ -743,7 +728,7 @@ class MainModelImpl, ComponentLis } public: - // TODO: (figueroa1395) may want to move this to update.hpp or make something similar there + // TODO: (figueroa1395) move to update or remove template using UpdateType = typename Component::UpdateType; // Calculate with optimization, e.g., automatic tap changer From c4eb684fd0d5d1199501d1b6bca9a71f5721d354 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Fri, 15 Nov 2024 11:14:34 +0100 Subject: [PATCH 17/30] Fix tests Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 19 +++++++------------ .../power_grid_model/main_model_impl.hpp | 15 ++++++--------- 2 files changed, 13 insertions(+), 21 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 08f9aa143..71cbf085c 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 @@ -265,18 +265,14 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat template SequenceIdx get_sequence_idx_map(MainModelState const& state, ConstDataset const& update_data, Idx scenario_idx, - ComponentFlags const& components_to_store, - std::span relevant_component_count) { - size_t comp_idx{}; + ComponentFlags const& components_to_store) { return utils::run_functor_with_all_types_return_array( - [&update_data, &components_to_store, &state, &relevant_component_count, scenario_idx, - &comp_idx]() { - if (!std::get>(components_to_store)) { + [&update_data, &components_to_store, &state, scenario_idx]() { + auto const n_components = std::get>(components_to_store); + if (!n_components) { return std::vector{}; } - Idx const n_component = relevant_component_count[comp_idx]; - ++comp_idx; - auto const independence = check_component_independence(update_data, n_component); + auto const independence = check_component_independence(update_data, n_components); validate_update_data_independence(independence); return get_component_sequence(state, update_data, scenario_idx, independence); }); @@ -286,14 +282,13 @@ SequenceIdx get_sequence_idx_map(MainModelState SequenceIdx get_sequence_idx_map(MainModelState const& state, - ConstDataset const& update_data, - std::span relevant_component_count) { + ConstDataset const& update_data) { constexpr ComponentFlags all_true = [] { ComponentFlags result{}; std::ranges::fill(result, true); return result; }(); - return get_sequence_idx_map(state, update_data, 0, all_true, relevant_component_count); + return get_sequence_idx_map(state, update_data, 0, all_true); } template 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 a924cffe9..90ac0ad1f 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 @@ -307,9 +307,8 @@ class MainModelImpl, ComponentLis } // update all components in the first scenario (e.g. permanent update) template void update_components(ConstDataset const& update_data) { - auto const relevant_component_count = get_n_components_per_type(); - auto const sequence_idx_map = main_core::get_sequence_idx_map( - state_, update_data.get_individual_scenario(0), relevant_component_count); + auto const sequence_idx_map = + main_core::get_sequence_idx_map(state_, update_data.get_individual_scenario(0)); update_components(update_data, 0, sequence_idx_map); } @@ -395,8 +394,7 @@ class MainModelImpl, ComponentLis // Entry point for main_model.hpp template SequenceIdx get_sequence_idx_map(ConstDataset const& update_data) { - auto const relevant_component_count = get_n_components_per_type(); - return main_core::get_sequence_idx_map(state_, update_data, relevant_component_count); + return main_core::get_sequence_idx_map(state_, update_data); } private: @@ -561,8 +559,8 @@ class MainModelImpl, ComponentLis auto const relevant_component_count = get_n_components_per_type(); auto const is_independent = main_core::is_update_independent(update_data, relevant_component_count); - all_scenarios_sequence = main_core::get_sequence_idx_map( - state_, update_data, 0, is_independent, relevant_component_count); + all_scenarios_sequence = + main_core::get_sequence_idx_map(state_, update_data, 0, is_independent); return [&base_model, &exceptions, &infos, &calculation_fn, &result_data, &update_data, &all_scenarios_sequence = std::as_const(all_scenarios_sequence), @@ -679,9 +677,8 @@ class MainModelImpl, ComponentLis [&model, &update_data, scenario_sequence, ¤t_scenario_sequence_cache, do_update_cache_ = std::move(do_update_cache), &infos](Idx scenario_idx) { Timer const t_update_model(infos[scenario_idx], 1200, "Update model"); - auto const relevant_component_count = model.get_n_components_per_type(); current_scenario_sequence_cache = main_core::get_sequence_idx_map( - model.state_, update_data, scenario_idx, do_update_cache_, relevant_component_count); + model.state_, update_data, scenario_idx, do_update_cache_); model.template update_components(update_data, scenario_idx, scenario_sequence()); }, From 2143cba5583e54ba6824791dc24b0867bc4d1367 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Fri, 15 Nov 2024 14:54:54 +0100 Subject: [PATCH 18/30] fixed bug - finally Signed-off-by: Santiago Figueroa Manrique --- .../include/power_grid_model/main_core/update.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 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 71cbf085c..32de242c8 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 @@ -268,10 +268,10 @@ SequenceIdx get_sequence_idx_map(MainModelState const& components_to_store) { return utils::run_functor_with_all_types_return_array( [&update_data, &components_to_store, &state, scenario_idx]() { - auto const n_components = std::get>(components_to_store); - if (!n_components) { + if (!std::get>(components_to_store)) { return std::vector{}; } + auto const n_components = state.components.template size(); auto const independence = check_component_independence(update_data, n_components); validate_update_data_independence(independence); return get_component_sequence(state, update_data, scenario_idx, independence); From cc768978409d680edb9a5ea8d22c57bd6a8d7d94 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Fri, 15 Nov 2024 16:17:51 +0100 Subject: [PATCH 19/30] re-organize Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 146 +++++++++--------- .../utils.hpp} | 15 +- .../power_grid_model/main_model_impl.hpp | 38 ++--- 3 files changed, 101 insertions(+), 98 deletions(-) rename power_grid_model_c/power_grid_model/include/power_grid_model/{main_model_utils.hpp => main_core/utils.hpp} (53%) 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 32de242c8..8456eb429 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 @@ -4,12 +4,12 @@ #pragma once -#include "../container.hpp" #include "state.hpp" +#include "utils.hpp" #include "../all_components.hpp" #include "../common/iterator_like_concepts.hpp" -#include "../main_model_utils.hpp" +#include "../container.hpp" #include @@ -31,16 +31,6 @@ inline void iterate_component_sequence(Func&& func, ForwardIterator begin, Forwa } } -// TODO: (figueroa1395) maybe move to detail namespace within independence namespace -template bool check_id_na(T const& obj) { - if constexpr (requires { obj.id; }) { - return is_nan(obj.id); - } else if constexpr (requires { obj.get().id; }) { - return is_nan(obj.get().id); - } else { - throw UnreachableHit{"check_component_independence", "Only components with id are supported"}; - } -} } // namespace detail template const& state, Forw get_component_sequence(state, begin, end)); } -//////////////////////// +namespace update_independence { +namespace detail { -// TODO: (figueroa1395) encapsulate all these in a independence related namespace (might even be a good idea to move to -// a different file) - UpdateCompIndependence -// TODO: (figueroa1395) reorganize this file to have the independence related functions together and in a way it makes -// sense. For now just dumping and refactoring things individually. -static constexpr Idx invalid_index{-1}; +constexpr Idx invalid_index{-1}; -template using ComponentFlags = std::array; +template bool check_id_na(T const& obj) { + if constexpr (requires { obj.id; }) { + return is_nan(obj.id); + } else if constexpr (requires { obj.get().id; }) { + return is_nan(obj.get().id); + } else { + throw UnreachableHit{"check_component_independence", "Only components with id are supported"}; + } +} struct UpdateCompProperties { std::string name{}; @@ -183,29 +178,7 @@ struct UpdateCompProperties { } }; -// get sequence idx map of a certain batch scenario -template -std::vector get_component_sequence(MainModelState const& state, - ConstDataset const& update_data, Idx scenario_idx, - UpdateCompProperties const& comp_independence = {}) { - auto const get_sequence = [&state, n_comp_elements = comp_independence.get_n_elements()](auto const& span) { - return get_component_sequence(state, std::begin(span), std::end(span), n_comp_elements); - }; - if (update_data.is_columnar(CompType::name)) { - auto const buffer_span = - update_data.get_columnar_buffer_span(scenario_idx); - return get_sequence(buffer_span); - } - auto const buffer_span = update_data.get_buffer_span(scenario_idx); - return get_sequence(buffer_span); -} - -template using SequenceIdx = std::array, sizeof...(ComponentTypes)>; - -template -constexpr size_t index_of_component = container_impl::get_cls_pos_v; - -template void process_buffer_span(auto const& all_spans, UpdateCompProperties& properties) { +template void process_buffer_span(auto const& all_spans, detail::UpdateCompProperties& properties) { properties.ids_all_na = std::ranges::all_of(all_spans, [](auto const& vec) { return std::ranges::all_of(vec, [](auto const& item) { return detail::check_id_na(item); }); }); @@ -237,8 +210,8 @@ template void process_buffer_span(auto const& all_spans, Upd } template -UpdateCompProperties check_component_independence(ConstDataset const& update_data, Idx n_component) { - UpdateCompProperties properties; +detail::UpdateCompProperties check_component_independence(ConstDataset const& update_data, Idx n_component) { + detail::UpdateCompProperties properties; properties.name = CompType::name; auto const component_idx = update_data.find_component(properties.name, false); properties.is_columnar = update_data.is_columnar(properties.name); @@ -251,17 +224,62 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat properties.elements_in_base = n_component; if (properties.is_columnar) { - process_buffer_span( + detail::process_buffer_span( update_data.template get_columnar_buffer_span_all_scenarios(), properties); } else { - process_buffer_span( + detail::process_buffer_span( update_data.template get_buffer_span_all_scenarios(), properties); } return properties; } +inline void validate_update_data_independence(detail::UpdateCompProperties const& comp) { + if (comp.is_empty_component()) { + return; // empty dataset is still supported + } + auto const elements_ps = comp.get_n_elements(); + assert(comp.uniform || elements_ps < 0); + + if (elements_ps >= 0 && comp.elements_in_base < elements_ps) { + throw DatasetError("Update data has more elements per scenario than input data for component " + comp.name + + "!"); + } + if (comp.ids_part_na) { + throw DatasetError("Some IDs are not valid for component " + comp.name + " in update data!"); + } + if (comp.ids_all_na && comp.elements_in_base != elements_ps) { + throw DatasetError("Update data without IDs for component " + comp.name + + " has a different number of elements per scenario then input data!"); + } +} + +} // namespace detail + +// main core utils +template +constexpr auto index_of_component = main_core::utils::index_of_component; +template using SequenceIdx = main_core::utils::SequenceIdx; +template using ComponentFlags = main_core::utils::ComponentFlags; + +// get sequence idx map of a certain batch scenario +template +std::vector get_component_sequence(MainModelState const& state, + ConstDataset const& update_data, Idx scenario_idx, + detail::UpdateCompProperties const& comp_independence = {}) { + auto const get_sequence = [&state, n_comp_elements = comp_independence.get_n_elements()](auto const& span) { + return get_component_sequence(state, std::begin(span), std::end(span), n_comp_elements); + }; + if (update_data.is_columnar(CompType::name)) { + auto const buffer_span = + update_data.get_columnar_buffer_span(scenario_idx); + return get_sequence(buffer_span); + } + auto const buffer_span = update_data.get_buffer_span(scenario_idx); + return get_sequence(buffer_span); +} + template SequenceIdx get_sequence_idx_map(MainModelState const& state, ConstDataset const& update_data, Idx scenario_idx, @@ -272,8 +290,8 @@ SequenceIdx get_sequence_idx_map(MainModelState{}; } auto const n_components = state.components.template size(); - auto const independence = check_component_independence(update_data, n_components); - validate_update_data_independence(independence); + auto const independence = detail::check_component_independence(update_data, n_components); + detail::validate_update_data_independence(independence); return get_component_sequence(state, update_data, scenario_idx, independence); }); } @@ -296,33 +314,15 @@ ComponentFlags is_update_independent(ConstDataset const& upda std::span relevant_component_count) { ComponentFlags result{}; size_t comp_idx{}; - utils::run_functor_with_all_types_return_void( - [&result, &relevant_component_count, &update_data, &comp_idx]() { - Idx const n_component = relevant_component_count[comp_idx]; - result[comp_idx] = check_component_independence(update_data, n_component).is_independent(); - ++comp_idx; - }); + utils::run_functor_with_all_types_return_void([&result, &relevant_component_count, &update_data, + &comp_idx]() { + Idx const n_component = relevant_component_count[comp_idx]; + result[comp_idx] = detail::check_component_independence(update_data, n_component).is_independent(); + ++comp_idx; + }); return result; } -inline void validate_update_data_independence(UpdateCompProperties const& comp) { - if (comp.is_empty_component()) { - return; // empty dataset is still supported - } - auto const elements_ps = comp.get_n_elements(); - assert(comp.uniform || elements_ps < 0); - - if (elements_ps >= 0 && comp.elements_in_base < elements_ps) { - throw DatasetError("Update data has more elements per scenario than input data for component " + comp.name + - "!"); - } - if (comp.ids_part_na) { - throw DatasetError("Some IDs are not valid for component " + comp.name + " in update data!"); - } - if (comp.ids_all_na && comp.elements_in_base != elements_ps) { - throw DatasetError("Update data without IDs for component " + comp.name + - " has a different number of elements per scenario then input data!"); - } -} +} // namespace update_independence } // namespace power_grid_model::main_core diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/utils.hpp similarity index 53% rename from power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp rename to power_grid_model_c/power_grid_model/include/power_grid_model/main_core/utils.hpp index 9a09e55f1..a87cc8dd7 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model_utils.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/utils.hpp @@ -4,12 +4,20 @@ #pragma once -#include "all_components.hpp" +#include "../all_components.hpp" +#include "../container.hpp" + +#include +#include -// main model class namespace power_grid_model::main_core::utils { -template constexpr size_t n_component_types = sizeof...(ComponentType); +template constexpr size_t n_types = sizeof...(ComponentTypes); +template +constexpr size_t index_of_component = container_impl::get_cls_pos_v; + +template using SequenceIdx = std::array, n_types>; +template using ComponentFlags = std::array>; // run functors with all component types template constexpr void run_functor_with_all_types_return_void(Functor functor) { @@ -20,4 +28,3 @@ template constexpr auto run_functor_with_all_typ } } // namespace power_grid_model::main_core::utils -// TODO: (figueroa1395) move to main_core under utils.hpp 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 90ac0ad1f..a63f90427 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 @@ -11,7 +11,6 @@ #include "calculation_parameters.hpp" #include "container.hpp" #include "main_model_fwd.hpp" -#include "main_model_utils.hpp" #include "topology.hpp" // common @@ -37,6 +36,7 @@ #include "main_core/output.hpp" #include "main_core/topology.hpp" #include "main_core/update.hpp" +#include "main_core/utils.hpp" // stl library #include @@ -129,18 +129,16 @@ class MainModelImpl, ComponentLis using MainModelState = main_core::MainModelState; using MathState = main_core::MathState; - // Move SequenceIdx, n_types, index_of_component and ComponentFlags to Utils - template - static constexpr size_t index_of_component = container_impl::get_cls_pos_v; - - static constexpr size_t n_types = main_core::utils::n_component_types; + // main core utils + static constexpr auto n_types = main_core::utils::n_types; + template + static constexpr auto index_of_component = main_core::utils::index_of_component; + using SequenceIdx = main_core::utils::SequenceIdx; + using ComponentFlags = main_core::utils::ComponentFlags; - using SequenceIdx = std::array, n_types>; using SequenceIdxView = std::array, n_types>; using OwnedUpdateDataset = std::tuple...>; - - using ComponentFlags = std::array; using ComponentCountInBase = std::pair; static constexpr Idx ignore_output{-1}; @@ -307,8 +305,8 @@ class MainModelImpl, ComponentLis } // update all components in the first scenario (e.g. permanent update) template void update_components(ConstDataset const& update_data) { - auto const sequence_idx_map = - main_core::get_sequence_idx_map(state_, update_data.get_individual_scenario(0)); + auto const sequence_idx_map = main_core::update_independence::get_sequence_idx_map( + state_, update_data.get_individual_scenario(0)); update_components(update_data, 0, sequence_idx_map); } @@ -394,7 +392,7 @@ class MainModelImpl, ComponentLis // Entry point for main_model.hpp template SequenceIdx get_sequence_idx_map(ConstDataset const& update_data) { - return main_core::get_sequence_idx_map(state_, update_data); + return main_core::update_independence::get_sequence_idx_map(state_, update_data); } private: @@ -557,10 +555,10 @@ class MainModelImpl, ComponentLis // cache component update order where possible. // the order for a cacheable (independent) component by definition is the same across all scenarios auto const relevant_component_count = get_n_components_per_type(); - auto const is_independent = - main_core::is_update_independent(update_data, relevant_component_count); - all_scenarios_sequence = - main_core::get_sequence_idx_map(state_, update_data, 0, is_independent); + auto const is_independent = main_core::update_independence::is_update_independent( + update_data, relevant_component_count); + all_scenarios_sequence = main_core::update_independence::get_sequence_idx_map( + state_, update_data, 0, is_independent); return [&base_model, &exceptions, &infos, &calculation_fn, &result_data, &update_data, &all_scenarios_sequence = std::as_const(all_scenarios_sequence), @@ -677,8 +675,9 @@ class MainModelImpl, ComponentLis [&model, &update_data, scenario_sequence, ¤t_scenario_sequence_cache, do_update_cache_ = std::move(do_update_cache), &infos](Idx scenario_idx) { Timer const t_update_model(infos[scenario_idx], 1200, "Update model"); - current_scenario_sequence_cache = main_core::get_sequence_idx_map( - model.state_, update_data, scenario_idx, do_update_cache_); + current_scenario_sequence_cache = + main_core::update_independence::get_sequence_idx_map( + model.state_, update_data, scenario_idx, do_update_cache_); model.template update_components(update_data, scenario_idx, scenario_sequence()); }, @@ -725,9 +724,6 @@ class MainModelImpl, ComponentLis } public: - // TODO: (figueroa1395) move to update or remove - template using UpdateType = typename Component::UpdateType; - // Calculate with optimization, e.g., automatic tap changer template auto calculate(Options const& options) { auto const calculator = [this, &options] { From e4746444b75edee2bb1f7eb88bc6a7f614d19230 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Mon, 18 Nov 2024 11:55:58 +0100 Subject: [PATCH 20/30] address comments Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 41 +++++++++---------- .../include/power_grid_model/main_model.hpp | 2 +- .../power_grid_model/main_model_impl.hpp | 12 +++--- 3 files changed, 27 insertions(+), 28 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 8456eb429..4c78d67ac 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 @@ -178,17 +178,16 @@ struct UpdateCompProperties { } }; -template void process_buffer_span(auto const& all_spans, detail::UpdateCompProperties& properties) { +template void process_buffer_span(auto const& all_spans, UpdateCompProperties& properties) { properties.ids_all_na = std::ranges::all_of(all_spans, [](auto const& vec) { - return std::ranges::all_of(vec, [](auto const& item) { return detail::check_id_na(item); }); + return std::ranges::all_of(vec, [](auto const& item) { return check_id_na(item); }); }); - properties.ids_part_na = std::ranges::any_of(all_spans, - [](auto const& vec) { - return std::ranges::any_of(vec, [](auto const& item) { - return detail::check_id_na(item); - }); - }) && - !properties.ids_all_na; + properties.ids_part_na = + std::ranges::any_of(all_spans, + [](auto const& vec) { + return std::ranges::any_of(vec, [](auto const& item) { return check_id_na(item); }); + }) && + !properties.ids_all_na; if (all_spans.empty()) { properties.update_ids_match = true; @@ -210,8 +209,8 @@ template void process_buffer_span(auto const& all_spans, det } template -detail::UpdateCompProperties check_component_independence(ConstDataset const& update_data, Idx n_component) { - detail::UpdateCompProperties properties; +UpdateCompProperties check_component_independence(ConstDataset const& update_data, Idx n_component) { + UpdateCompProperties properties; properties.name = CompType::name; auto const component_idx = update_data.find_component(properties.name, false); properties.is_columnar = update_data.is_columnar(properties.name); @@ -224,18 +223,18 @@ detail::UpdateCompProperties check_component_independence(ConstDataset const& up properties.elements_in_base = n_component; if (properties.is_columnar) { - detail::process_buffer_span( + process_buffer_span( update_data.template get_columnar_buffer_span_all_scenarios(), properties); } else { - detail::process_buffer_span( + process_buffer_span( update_data.template get_buffer_span_all_scenarios(), properties); } return properties; } -inline void validate_update_data_independence(detail::UpdateCompProperties const& comp) { +inline void validate_update_data_independence(UpdateCompProperties const& comp) { if (comp.is_empty_component()) { return; // empty dataset is still supported } @@ -247,7 +246,7 @@ inline void validate_update_data_independence(detail::UpdateCompProperties const "!"); } if (comp.ids_part_na) { - throw DatasetError("Some IDs are not valid for component " + comp.name + " in update data!"); + throw DatasetError("IDs contain both numbers and NANs for component " + comp.name + " in update data!"); } if (comp.ids_all_na && comp.elements_in_base != elements_ps) { throw DatasetError("Update data without IDs for component " + comp.name + @@ -281,9 +280,9 @@ std::vector get_component_sequence(MainModelState con } template -SequenceIdx get_sequence_idx_map(MainModelState const& state, - ConstDataset const& update_data, Idx scenario_idx, - ComponentFlags const& components_to_store) { +SequenceIdx get_all_sequence_idx_map(MainModelState const& state, + ConstDataset const& update_data, Idx scenario_idx, + ComponentFlags const& components_to_store) { return utils::run_functor_with_all_types_return_array( [&update_data, &components_to_store, &state, scenario_idx]() { if (!std::get>(components_to_store)) { @@ -299,14 +298,14 @@ SequenceIdx get_sequence_idx_map(MainModelState -SequenceIdx get_sequence_idx_map(MainModelState const& state, - ConstDataset const& update_data) { +SequenceIdx get_all_sequence_idx_map(MainModelState const& state, + ConstDataset const& update_data) { constexpr ComponentFlags all_true = [] { ComponentFlags result{}; std::ranges::fill(result, true); return result; }(); - return get_sequence_idx_map(state, update_data, 0, all_true); + return get_all_sequence_idx_map(state, update_data, 0, all_true); } template diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp index 0d3c9d291..acdaecd2f 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp @@ -57,7 +57,7 @@ class MainModel { void set_construction_complete() { impl().set_construction_complete(); } void restore_components(ConstDataset const& update_data) { - impl().restore_components(impl().get_sequence_idx_map(update_data)); + impl().restore_components(impl().get_all_sequence_idx_map(update_data)); } template void add_component(std::vector const& components) { 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 a63f90427..789e94c44 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 @@ -305,8 +305,8 @@ class MainModelImpl, ComponentLis } // update all components in the first scenario (e.g. permanent update) template void update_components(ConstDataset const& update_data) { - auto const sequence_idx_map = main_core::update_independence::get_sequence_idx_map( - state_, update_data.get_individual_scenario(0)); + auto const sequence_idx_map = + main_core::update_independence::get_all_sequence_idx_map(state_, update_data); update_components(update_data, 0, sequence_idx_map); } @@ -391,8 +391,8 @@ class MainModelImpl, ComponentLis } // Entry point for main_model.hpp - template SequenceIdx get_sequence_idx_map(ConstDataset const& update_data) { - return main_core::update_independence::get_sequence_idx_map(state_, update_data); + template SequenceIdx get_all_sequence_idx_map(ConstDataset const& update_data) { + return main_core::update_independence::get_all_sequence_idx_map(state_, update_data); } private: @@ -557,7 +557,7 @@ class MainModelImpl, ComponentLis auto const relevant_component_count = get_n_components_per_type(); auto const is_independent = main_core::update_independence::is_update_independent( update_data, relevant_component_count); - all_scenarios_sequence = main_core::update_independence::get_sequence_idx_map( + all_scenarios_sequence = main_core::update_independence::get_all_sequence_idx_map( state_, update_data, 0, is_independent); return [&base_model, &exceptions, &infos, &calculation_fn, &result_data, &update_data, @@ -676,7 +676,7 @@ class MainModelImpl, ComponentLis do_update_cache_ = std::move(do_update_cache), &infos](Idx scenario_idx) { Timer const t_update_model(infos[scenario_idx], 1200, "Update model"); current_scenario_sequence_cache = - main_core::update_independence::get_sequence_idx_map( + main_core::update_independence::get_all_sequence_idx_map( model.state_, update_data, scenario_idx, do_update_cache_); model.template update_components(update_data, scenario_idx, scenario_sequence()); From 67929c5d2e9879f28f75620ce7de412ecaa0ce92 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Mon, 18 Nov 2024 17:48:23 +0100 Subject: [PATCH 21/30] addressed comments Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 286 +++++++++--------- .../power_grid_model/main_model_impl.hpp | 19 +- 2 files changed, 153 insertions(+), 152 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 4c78d67ac..92ffac64e 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 @@ -13,7 +13,15 @@ #include -namespace power_grid_model::main_core { +namespace power_grid_model::main_core::update { + +constexpr Idx invalid_index{-1}; + +// main core utils +template +constexpr auto index_of_component = main_core::utils::index_of_component; +template using SequenceIdx = main_core::utils::SequenceIdx; +template using ComponentFlags = main_core::utils::ComponentFlags; namespace detail { template ForwardIterator, typename Func> @@ -31,115 +39,6 @@ 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, - ForwardIterator end, OutputIterator destination, Idx n_comp_elements) { - using UpdateType = typename Component::UpdateType; - - if (n_comp_elements < 0) { - std::ranges::transform(begin, end, destination, [&state](UpdateType const& update) { - return get_component_idx_by_id(state, update.id); - }); - } else { - assert(std::distance(begin, end) <= n_comp_elements); - std::ranges::transform( - begin, end, destination, - [group = get_component_group_idx(state), index = 0](auto const& /*update*/) mutable { - return Idx2D{group, index++}; // NOSONAR - }); - } -} - -template ForwardIterator> - requires model_component_state_c -inline std::vector get_component_sequence(MainModelState const& state, ForwardIterator begin, - ForwardIterator end, Idx n_comp_elements = na_Idx) { - std::vector result; - result.reserve(std::distance(begin, end)); - get_component_sequence(state, begin, end, std::back_inserter(result), n_comp_elements); - return result; -} - -// template to update components -// 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 UpdateChange update_component(MainModelState& state, ForwardIterator begin, - ForwardIterator end, OutputIterator changed_it, - std::span sequence_idx) { - using UpdateType = typename Component::UpdateType; - - UpdateChange state_changed; - - detail::iterate_component_sequence( - [&state_changed, &changed_it, &state](UpdateType const& update_data, Idx2D const& sequence_single) { - auto& comp = get_component(state, sequence_single); - assert(state.components.get_id_by_idx(sequence_single) == comp.id()); - auto const comp_changed = comp.update(update_data); - state_changed = state_changed || comp_changed; - - if (comp_changed.param || comp_changed.topo) { - *changed_it++ = sequence_single; - } - }, - begin, end, sequence_idx); - - return state_changed; -} -template ForwardIterator, - std::output_iterator OutputIterator> - requires model_component_state_c -inline UpdateChange update_component(MainModelState& state, ForwardIterator begin, - ForwardIterator end, OutputIterator changed_it) { - return update_component(state, begin, end, changed_it, - get_component_sequence(state, begin, end)); -} - -// template to get the inverse update for components -// 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, - OutputIterator destination, std::span sequence_idx) { - using UpdateType = typename Component::UpdateType; - - detail::iterate_component_sequence( - [&destination, &state](UpdateType const& update_data, Idx2D const& sequence_single) { - auto const& comp = get_component(state, sequence_single); - *destination++ = comp.inverse(update_data); - }, - 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, - OutputIterator destination) { - return update_inverse(state, begin, end, destination, - get_component_sequence(state, begin, end)); -} - -namespace update_independence { -namespace detail { - -constexpr Idx invalid_index{-1}; - template bool check_id_na(T const& obj) { if constexpr (requires { obj.id; }) { return is_nan(obj.id); @@ -150,6 +49,9 @@ template bool check_id_na(T const& obj) { } } +} // namespace detail + +namespace independence { struct UpdateCompProperties { std::string name{}; bool has_any_elements{false}; // whether the component has any elements in the update data @@ -180,17 +82,19 @@ struct UpdateCompProperties { template void process_buffer_span(auto const& all_spans, UpdateCompProperties& properties) { properties.ids_all_na = std::ranges::all_of(all_spans, [](auto const& vec) { - return std::ranges::all_of(vec, [](auto const& item) { return check_id_na(item); }); + return std::ranges::all_of(vec, [](auto const& item) { return detail::check_id_na(item); }); }); - properties.ids_part_na = - std::ranges::any_of(all_spans, - [](auto const& vec) { - return std::ranges::any_of(vec, [](auto const& item) { return check_id_na(item); }); - }) && - !properties.ids_all_na; + properties.ids_part_na = std::ranges::any_of(all_spans, + [](auto const& vec) { + return std::ranges::any_of(vec, [](auto const& item) { + return detail::check_id_na(item); + }); + }) && + !properties.ids_all_na; if (all_spans.empty()) { properties.update_ids_match = true; + return; } else { // Remember the begin iterator of the first scenario, then loop over the remaining scenarios and // check the ids @@ -254,21 +158,65 @@ inline void validate_update_data_independence(UpdateCompProperties const& comp) } } -} // namespace detail +template +ComponentFlags is_update_independent(ConstDataset const& update_data, + std::span relevant_component_count) { + ComponentFlags result{}; + size_t comp_idx{}; + utils::run_functor_with_all_types_return_void( + [&result, &relevant_component_count, &update_data, &comp_idx]() { + Idx const n_component = relevant_component_count[comp_idx]; + result[comp_idx] = check_component_independence(update_data, n_component).is_independent(); + ++comp_idx; + }); + return result; +} -// main core utils -template -constexpr auto index_of_component = main_core::utils::index_of_component; -template using SequenceIdx = main_core::utils::SequenceIdx; -template using ComponentFlags = main_core::utils::ComponentFlags; +} // namespace independence + +namespace detail { + +template ForwardIterator, + std::output_iterator OutputIterator> + requires model_component_state_c +inline void get_component_sequence_impl(MainModelState const& state, ForwardIterator begin, + ForwardIterator end, OutputIterator destination, Idx n_comp_elements) { + using UpdateType = typename Component::UpdateType; + + if (n_comp_elements < 0) { + std::ranges::transform(begin, end, destination, [&state](UpdateType const& update) { + return get_component_idx_by_id(state, update.id); + }); + } else { + assert(std::distance(begin, end) <= n_comp_elements); + std::ranges::transform( + begin, end, destination, + [group = get_component_group_idx(state), index = 0](auto const& /*update*/) mutable { + return Idx2D{group, index++}; // NOSONAR + }); + } +} + +template ForwardIterator> + requires model_component_state_c +inline std::vector get_component_sequence_by_it(MainModelState const& state, + ForwardIterator begin, ForwardIterator end, + Idx n_comp_elements = na_Idx) { + std::vector result; + result.reserve(std::distance(begin, end)); + get_component_sequence_impl(state, begin, end, std::back_inserter(result), n_comp_elements); + return result; +} // get sequence idx map of a certain batch scenario template std::vector get_component_sequence(MainModelState const& state, ConstDataset const& update_data, Idx scenario_idx, - detail::UpdateCompProperties const& comp_independence = {}) { + independence::UpdateCompProperties const& comp_independence = {}) { auto const get_sequence = [&state, n_comp_elements = comp_independence.get_n_elements()](auto const& span) { - return get_component_sequence(state, std::begin(span), std::end(span), n_comp_elements); + return get_component_sequence_by_it(state, std::begin(span), std::end(span), n_comp_elements); }; if (update_data.is_columnar(CompType::name)) { auto const buffer_span = @@ -278,6 +226,7 @@ std::vector get_component_sequence(MainModelState con auto const buffer_span = update_data.get_buffer_span(scenario_idx); return get_sequence(buffer_span); } +} // namespace detail template SequenceIdx get_all_sequence_idx_map(MainModelState const& state, @@ -289,9 +238,9 @@ SequenceIdx get_all_sequence_idx_map(MainModelState{}; } auto const n_components = state.components.template size(); - auto const independence = detail::check_component_independence(update_data, n_components); - detail::validate_update_data_independence(independence); - return get_component_sequence(state, update_data, scenario_idx, independence); + auto const independence = independence::check_component_independence(update_data, n_components); + independence::validate_update_data_independence(independence); + return detail::get_component_sequence(state, update_data, scenario_idx, independence); }); } // Get sequence idx map of an entire batch for fast caching of component sequences. @@ -308,20 +257,73 @@ SequenceIdx get_all_sequence_idx_map(MainModelState(state, update_data, 0, all_true); } -template -ComponentFlags is_update_independent(ConstDataset const& update_data, - std::span relevant_component_count) { - ComponentFlags result{}; - size_t comp_idx{}; - utils::run_functor_with_all_types_return_void([&result, &relevant_component_count, &update_data, - &comp_idx]() { - Idx const n_component = relevant_component_count[comp_idx]; - result[comp_idx] = detail::check_component_independence(update_data, n_component).is_independent(); - ++comp_idx; - }); - return result; +// template to update components +// 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 UpdateChange update_component(MainModelState& state, ForwardIterator begin, + ForwardIterator end, OutputIterator changed_it, + std::span sequence_idx) { + using UpdateType = typename Component::UpdateType; + + UpdateChange state_changed; + + detail::iterate_component_sequence( + [&state_changed, &changed_it, &state](UpdateType const& update_data, Idx2D const& sequence_single) { + auto& comp = get_component(state, sequence_single); + assert(state.components.get_id_by_idx(sequence_single) == comp.id()); + auto const comp_changed = comp.update(update_data); + state_changed = state_changed || comp_changed; + + if (comp_changed.param || comp_changed.topo) { + *changed_it++ = sequence_single; + } + }, + begin, end, sequence_idx); + + return state_changed; +} +template ForwardIterator, + std::output_iterator OutputIterator> + requires model_component_state_c +inline UpdateChange update_component(MainModelState& state, ForwardIterator begin, + ForwardIterator end, OutputIterator changed_it) { + return update_component(state, begin, end, changed_it, + detail::get_component_sequence_by_it(state, begin, end)); } -} // namespace update_independence +// template to get the inverse update for components +// 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, + OutputIterator destination, std::span sequence_idx) { + using UpdateType = typename Component::UpdateType; + + detail::iterate_component_sequence( + [&destination, &state](UpdateType const& update_data, Idx2D const& sequence_single) { + auto const& comp = get_component(state, sequence_single); + *destination++ = comp.inverse(update_data); + }, + 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, + OutputIterator destination) { + return update_inverse(state, begin, end, destination, + detail::get_component_sequence_by_it(state, begin, end)); +} -} // namespace power_grid_model::main_core +} // namespace power_grid_model::main_core::update 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 789e94c44..3e5ef6677 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 @@ -241,11 +241,11 @@ class MainModelImpl, ComponentLis assert(static_cast(sequence_idx.size()) == std::distance(begin, end)); if constexpr (CacheType::value) { - main_core::update_inverse( + main_core::update::update_inverse( state_, begin, end, std::back_inserter(std::get(cached_inverse_update_)), sequence_idx); } - UpdateChange const changed = main_core::update_component( + UpdateChange const changed = main_core::update::update_component( state_, begin, end, std::back_inserter(std::get(parameter_changed_components_)), sequence_idx); // update, get changed variable @@ -306,7 +306,7 @@ class MainModelImpl, ComponentLis // update all components in the first scenario (e.g. permanent update) template void update_components(ConstDataset const& update_data) { auto const sequence_idx_map = - main_core::update_independence::get_all_sequence_idx_map(state_, update_data); + main_core::update::get_all_sequence_idx_map(state_, update_data); update_components(update_data, 0, sequence_idx_map); } @@ -392,7 +392,7 @@ class MainModelImpl, ComponentLis // Entry point for main_model.hpp template SequenceIdx get_all_sequence_idx_map(ConstDataset const& update_data) { - return main_core::update_independence::get_all_sequence_idx_map(state_, update_data); + return main_core::update::get_all_sequence_idx_map(state_, update_data); } private: @@ -555,10 +555,10 @@ class MainModelImpl, ComponentLis // cache component update order where possible. // the order for a cacheable (independent) component by definition is the same across all scenarios auto const relevant_component_count = get_n_components_per_type(); - auto const is_independent = main_core::update_independence::is_update_independent( + auto const is_independent = main_core::update::independence::is_update_independent( update_data, relevant_component_count); - all_scenarios_sequence = main_core::update_independence::get_all_sequence_idx_map( - state_, update_data, 0, is_independent); + all_scenarios_sequence = + main_core::update::get_all_sequence_idx_map(state_, update_data, 0, is_independent); return [&base_model, &exceptions, &infos, &calculation_fn, &result_data, &update_data, &all_scenarios_sequence = std::as_const(all_scenarios_sequence), @@ -675,9 +675,8 @@ class MainModelImpl, ComponentLis [&model, &update_data, scenario_sequence, ¤t_scenario_sequence_cache, do_update_cache_ = std::move(do_update_cache), &infos](Idx scenario_idx) { Timer const t_update_model(infos[scenario_idx], 1200, "Update model"); - current_scenario_sequence_cache = - main_core::update_independence::get_all_sequence_idx_map( - model.state_, update_data, scenario_idx, do_update_cache_); + current_scenario_sequence_cache = main_core::update::get_all_sequence_idx_map( + model.state_, update_data, scenario_idx, do_update_cache_); model.template update_components(update_data, scenario_idx, scenario_sequence()); }, From f7c64c99ec2d5bc5b4accacee2bbf680b5599194 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Tue, 19 Nov 2024 09:28:56 +0100 Subject: [PATCH 22/30] minor Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 25 ++++++++----------- .../test_tap_position_optimizer.cpp | 4 +-- 2 files changed, 13 insertions(+), 16 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 92ffac64e..ac4f3dd36 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 @@ -95,21 +95,18 @@ template void process_buffer_span(auto const& all_spans, Upd if (all_spans.empty()) { properties.update_ids_match = true; return; - } else { - // Remember the begin iterator of the first scenario, then loop over the remaining scenarios and - // check the ids - auto const first_span = all_spans[0]; - // check the subsequent scenarios - // only return true if all scenarios match the ids of the first batch - properties.update_ids_match = - std::ranges::all_of(all_spans.cbegin() + 1, all_spans.cend(), [&first_span](auto const& current_span) { - return std::ranges::equal( - current_span, first_span, - [](typename CompType::UpdateType const& obj, typename CompType::UpdateType const& first) { - return obj.id == first.id; - }); - }); } + // Remember the begin iterator of the first scenario, then loop over the remaining scenarios and + // check the ids + auto const first_span = all_spans[0]; + // check the subsequent scenarios + // only return true if all scenarios match the ids of the first batch + properties.update_ids_match = + std::ranges::all_of(all_spans.cbegin() + 1, all_spans.cend(), [&first_span](auto const& current_span) { + return std::ranges::equal(current_span, first_span, + [](typename CompType::UpdateType const& obj, + typename CompType::UpdateType const& first) { return obj.id == first.id; }); + }); } template diff --git a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp index cfed77709..3b732f838 100644 --- a/tests/cpp_unit_tests/test_tap_position_optimizer.cpp +++ b/tests/cpp_unit_tests/test_tap_position_optimizer.cpp @@ -691,8 +691,8 @@ TEST_CASE("Test Tap position optimizer") { auto const& transformers_dataset = update_dataset.get_buffer_span(); auto changed_components = std::vector{}; - main_core::update_component(state, transformers_dataset.begin(), transformers_dataset.end(), - std::back_inserter(changed_components)); + main_core::update::update_component( + state, transformers_dataset.begin(), transformers_dataset.end(), std::back_inserter(changed_components)); }; auto twoStatesEqual = [](const MockState& state1, const MockState& state2) { From 297d2d7e5cccd0b1ceffedb974c6c99908c1f334 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Tue, 19 Nov 2024 10:20:55 +0100 Subject: [PATCH 23/30] rename get_comp_seq in state_queries Signed-off-by: Santiago Figueroa Manrique --- .../main_core/state_queries.hpp | 8 ++--- .../power_grid_model/main_core/topology.hpp | 34 +++++++++---------- .../power_grid_model/main_model_impl.hpp | 6 ++-- .../optimizer/tap_position_optimizer.hpp | 6 ++-- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/state_queries.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/state_queries.hpp index 04b998373..4d92566c7 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/state_queries.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/state_queries.hpp @@ -41,7 +41,7 @@ constexpr Idx get_component_group_idx(MainModelState const& template requires model_component_state_c -inline Idx get_component_sequence(MainModelState const& state, auto const& id_or_index) { +inline Idx get_component_sequence_idx(MainModelState const& state, auto const& id_or_index) { return state.components.template get_seq(id_or_index); } @@ -97,19 +97,19 @@ constexpr auto get_component_citer(MainModelState const& sta template ComponentType, class ComponentContainer> requires model_component_state_c constexpr auto get_topology_index(MainModelState const& state, auto const& id_or_index) { - return get_component_sequence(state, id_or_index); + return get_component_sequence_idx(state, id_or_index); } template ComponentType, class ComponentContainer> requires model_component_state_c constexpr auto get_topology_index(MainModelState const& state, auto const& id_or_index) { - return get_component_sequence(state, id_or_index); + return get_component_sequence_idx(state, id_or_index); } template ComponentType, class ComponentContainer> requires model_component_state_c constexpr auto get_topology_index(MainModelState const& state, auto const& id_or_index) { - return get_component_sequence(state, id_or_index); + return get_component_sequence_idx(state, id_or_index); } template ComponentType, class ComponentContainer> diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/topology.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/topology.hpp index 567f2f684..b5bc94188 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/topology.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/topology.hpp @@ -40,8 +40,8 @@ template Component, class ComponentContainer> constexpr void register_topology_components(MainModelState const& state, ComponentTopology& comp_topo) { detail::register_topo_components(state, comp_topo.branch_node_idx, [&state](Branch const& branch) { - return BranchIdx{get_component_sequence(state, branch.from_node()), - get_component_sequence(state, branch.to_node())}; + return BranchIdx{get_component_sequence_idx(state, branch.from_node()), + get_component_sequence_idx(state, branch.to_node())}; }); } @@ -50,9 +50,9 @@ template Component, class ComponentContainer> constexpr void register_topology_components(MainModelState const& state, ComponentTopology& comp_topo) { detail::register_topo_components(state, comp_topo.branch3_node_idx, [&state](Branch3 const& branch3) { - return Branch3Idx{get_component_sequence(state, branch3.node_1()), - get_component_sequence(state, branch3.node_2()), - get_component_sequence(state, branch3.node_3())}; + return Branch3Idx{get_component_sequence_idx(state, branch3.node_1()), + get_component_sequence_idx(state, branch3.node_2()), + get_component_sequence_idx(state, branch3.node_3())}; }); } @@ -61,7 +61,7 @@ template Component, class ComponentContainer> constexpr void register_topology_components(MainModelState const& state, ComponentTopology& comp_topo) { detail::register_topo_components(state, comp_topo.source_node_idx, [&state](Source const& source) { - return get_component_sequence(state, source.node()); + return get_component_sequence_idx(state, source.node()); }); } @@ -70,7 +70,7 @@ template Component, class ComponentContainer> constexpr void register_topology_components(MainModelState const& state, ComponentTopology& comp_topo) { detail::register_topo_components(state, comp_topo.shunt_node_idx, [&state](Shunt const& shunt) { - return get_component_sequence(state, shunt.node()); + return get_component_sequence_idx(state, shunt.node()); }); } @@ -80,7 +80,7 @@ constexpr void register_topology_components(MainModelState c ComponentTopology& comp_topo) { detail::register_topo_components( state, comp_topo.load_gen_node_idx, - [&state](GenericLoadGen const& load_gen) { return get_component_sequence(state, load_gen.node()); }); + [&state](GenericLoadGen const& load_gen) { return get_component_sequence_idx(state, load_gen.node()); }); detail::register_topo_components(state, comp_topo.load_gen_type, [](GenericLoadGen const& load_gen) { return load_gen.type(); }); @@ -92,7 +92,7 @@ constexpr void register_topology_components(MainModelState c ComponentTopology& comp_topo) { detail::register_topo_components( state, comp_topo.voltage_sensor_node_idx, [&state](GenericVoltageSensor const& voltage_sensor) { - return get_component_sequence(state, voltage_sensor.measured_object()); + return get_component_sequence_idx(state, voltage_sensor.measured_object()); }); } @@ -110,21 +110,21 @@ constexpr void register_topology_components(MainModelState c case branch_from: [[fallthrough]]; case branch_to: - return get_component_sequence(state, measured_object); + return get_component_sequence_idx(state, measured_object); case source: - return get_component_sequence(state, measured_object); + return get_component_sequence_idx(state, measured_object); case shunt: - return get_component_sequence(state, measured_object); + return get_component_sequence_idx(state, measured_object); case load: [[fallthrough]]; case generator: - return get_component_sequence(state, measured_object); + return get_component_sequence_idx(state, measured_object); case branch3_1: case branch3_2: case branch3_3: - return get_component_sequence(state, measured_object); + return get_component_sequence_idx(state, measured_object); case node: - return get_component_sequence(state, measured_object); + return get_component_sequence_idx(state, measured_object); default: throw MissingCaseForEnumError("Power sensor idx to seq transformation", power_sensor.get_terminal_type()); @@ -144,9 +144,9 @@ constexpr void register_topology_components(MainModelState c state, comp_topo.regulated_object_idx, [&state](Regulator const& regulator) { switch (regulator.regulated_object_type()) { case ComponentType::branch: - return get_component_sequence(state, regulator.regulated_object()); + return get_component_sequence_idx(state, regulator.regulated_object()); case ComponentType::branch3: - return get_component_sequence(state, regulator.regulated_object()); + return get_component_sequence_idx(state, regulator.regulated_object()); default: throw MissingCaseForEnumError("Regulator idx to seq transformation", regulator.regulated_object_type()); } 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 3e5ef6677..8a0d2db1b 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 @@ -974,7 +974,7 @@ class MainModelImpl, ComponentLis if constexpr (std::derived_from) { Idx2D const math_idx = state.topo_comp_coup - ->branch[main_core::get_component_sequence(state, changed_component_idx)]; + ->branch[main_core::get_component_sequence_idx(state, changed_component_idx)]; if (math_idx.group == isolated_component) { return; } @@ -983,7 +983,7 @@ class MainModelImpl, ComponentLis } else if constexpr (std::derived_from) { Idx2DBranch3 const math_idx = state.topo_comp_coup - ->branch3[main_core::get_component_sequence(state, changed_component_idx)]; + ->branch3[main_core::get_component_sequence_idx(state, changed_component_idx)]; if (math_idx.group == isolated_component) { return; } @@ -996,7 +996,7 @@ class MainModelImpl, ComponentLis } else if constexpr (std::same_as) { Idx2D const math_idx = state.topo_comp_coup - ->shunt[main_core::get_component_sequence(state, changed_component_idx)]; + ->shunt[main_core::get_component_sequence_idx(state, changed_component_idx)]; if (math_idx.group == isolated_component) { return; } diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp index 0cc867dfb..3bbcce84e 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/optimizer/tap_position_optimizer.hpp @@ -82,8 +82,8 @@ template inline void add_to_edge(main_core::MainModelState const& state, TrafoGraphEdges& edges, TrafoGraphEdgeProperties& edge_props, ID const& start, ID const& end, TrafoGraphEdge const& edge_prop) { - Idx const start_idx = main_core::get_component_sequence(state, start); - Idx const end_idx = main_core::get_component_sequence(state, end); + Idx const start_idx = main_core::get_component_sequence_idx(state, start); + Idx const end_idx = main_core::get_component_sequence_idx(state, end); edges.emplace_back(start_idx, end_idx); edge_props.emplace_back(edge_prop); } @@ -218,7 +218,7 @@ inline auto build_transformer_graph(State const& state) -> TransformerGraph { // Mark sources for (auto const& source : state.components.template citer()) { // ignore disabled sources - trafo_graph[main_core::get_component_sequence(state, source.node())].is_source = source.status(); + trafo_graph[main_core::get_component_sequence_idx(state, source.node())].is_source = source.status(); } return trafo_graph; From 4022bac6480b3c64e0ff33ca6ceec878cbde1585 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Wed, 20 Nov 2024 11:09:08 +0100 Subject: [PATCH 24/30] addess comments Signed-off-by: Santiago Figueroa Manrique --- .../main_core/{utils.hpp => core_utils.hpp} | 0 .../power_grid_model/main_core/update.hpp | 19 +++++++++++-------- .../power_grid_model/main_model_impl.hpp | 14 +++++++------- 3 files changed, 18 insertions(+), 15 deletions(-) rename power_grid_model_c/power_grid_model/include/power_grid_model/main_core/{utils.hpp => core_utils.hpp} (100%) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/utils.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/core_utils.hpp similarity index 100% rename from power_grid_model_c/power_grid_model/include/power_grid_model/main_core/utils.hpp rename to power_grid_model_c/power_grid_model/include/power_grid_model/main_core/core_utils.hpp 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 ac4f3dd36..0bd361b30 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 @@ -4,8 +4,8 @@ #pragma once +#include "core_utils.hpp" #include "state.hpp" -#include "utils.hpp" #include "../all_components.hpp" #include "../common/iterator_like_concepts.hpp" @@ -100,7 +100,8 @@ template void process_buffer_span(auto const& all_spans, Upd // check the ids auto const first_span = all_spans[0]; // check the subsequent scenarios - // only return true if all scenarios match the ids of the first batch + // only return true if ids of all scenarios match the ids of the first batch + properties.update_ids_match = std::ranges::all_of(all_spans.cbegin() + 1, all_spans.cend(), [&first_span](auto const& current_span) { return std::ranges::equal(current_span, first_span, @@ -198,9 +199,9 @@ inline void get_component_sequence_impl(MainModelState const template ForwardIterator> requires model_component_state_c -inline std::vector get_component_sequence_by_it(MainModelState const& state, - ForwardIterator begin, ForwardIterator end, - Idx n_comp_elements = na_Idx) { +inline std::vector get_component_sequence_by_iter(MainModelState const& state, + ForwardIterator begin, ForwardIterator end, + Idx n_comp_elements = na_Idx) { std::vector result; result.reserve(std::distance(begin, end)); get_component_sequence_impl(state, begin, end, std::back_inserter(result), n_comp_elements); @@ -213,7 +214,7 @@ std::vector get_component_sequence(MainModelState con ConstDataset const& update_data, Idx scenario_idx, independence::UpdateCompProperties const& comp_independence = {}) { auto const get_sequence = [&state, n_comp_elements = comp_independence.get_n_elements()](auto const& span) { - return get_component_sequence_by_it(state, std::begin(span), std::end(span), n_comp_elements); + return get_component_sequence_by_iter(state, std::begin(span), std::end(span), n_comp_elements); }; if (update_data.is_columnar(CompType::name)) { auto const buffer_span = @@ -246,6 +247,8 @@ SequenceIdx get_all_sequence_idx_map(MainModelState SequenceIdx get_all_sequence_idx_map(MainModelState const& state, ConstDataset const& update_data) { + // Independence for all components is set to true as permanent updates involve only one scenario. + // Flags for all components (not only the ones present in update_data) are set to avoid more expensive checks. constexpr ComponentFlags all_true = [] { ComponentFlags result{}; std::ranges::fill(result, true); @@ -291,7 +294,7 @@ template & state, ForwardIterator begin, ForwardIterator end, OutputIterator changed_it) { return update_component(state, begin, end, changed_it, - detail::get_component_sequence_by_it(state, begin, end)); + detail::get_component_sequence_by_iter(state, begin, end)); } // template to get the inverse update for components @@ -320,7 +323,7 @@ template const& state, ForwardIterator begin, ForwardIterator end, OutputIterator destination) { return update_inverse(state, begin, end, destination, - detail::get_component_sequence_by_it(state, begin, end)); + detail::get_component_sequence_by_iter(state, begin, end)); } } // namespace power_grid_model::main_core::update 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 8a0d2db1b..f2c51e8e0 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 @@ -31,12 +31,12 @@ // main model implementation #include "main_core/calculation_info.hpp" +#include "main_core/core_utils.hpp" #include "main_core/input.hpp" #include "main_core/math_state.hpp" #include "main_core/output.hpp" #include "main_core/topology.hpp" #include "main_core/update.hpp" -#include "main_core/utils.hpp" // stl library #include @@ -139,7 +139,6 @@ class MainModelImpl, ComponentLis using SequenceIdxView = std::array, n_types>; using OwnedUpdateDataset = std::tuple...>; - using ComponentCountInBase = std::pair; static constexpr Idx ignore_output{-1}; static constexpr Idx isolated_component{-1}; @@ -167,9 +166,10 @@ class MainModelImpl, ComponentLis return state_.components.template size(); } + // TODO: possibly remove, as well as from main_model.hpp // all component count std::map> all_component_count() const { - auto const get_comp_count = [this]() -> ComponentCountInBase { + auto const get_comp_count = [this]() { return make_pair(std::string{CT::name}, this->component_count()); }; auto const all_count = @@ -255,7 +255,7 @@ class MainModelImpl, ComponentLis } } - // update all components of a single type across all scenarios + // ovearloads to update all components of a single type across all scenarios template void update_component(std::vector const& components, std::span sequence_idx) { @@ -278,7 +278,7 @@ class MainModelImpl, ComponentLis } } - // helper for row or columnar-based components + // entry point overload to update one row or column based component type template void update_component_row_col(ConstDataset const& update_data, Idx pos, std::span sequence_idx) { assert(construction_complete_); @@ -293,7 +293,7 @@ class MainModelImpl, ComponentLis } } - // update all components across all scenarios + // overload to update all components across all scenarios template requires(std::same_as || std::same_as) void update_components(ConstDataset const& update_data, Idx pos, SequenceIdxMap const& sequence_idx_map) { @@ -303,7 +303,7 @@ class MainModelImpl, ComponentLis std::get>(sequence_idx_map)); }); } - // update all components in the first scenario (e.g. permanent update) + // overload to update all components in the first scenario (e.g. permanent update) template void update_components(ConstDataset const& update_data) { auto const sequence_idx_map = main_core::update::get_all_sequence_idx_map(state_, update_data); From b6c4f4d06cdb269d83d3d7f85a5799bb366f246b Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Wed, 20 Nov 2024 11:32:36 +0100 Subject: [PATCH 25/30] minor Signed-off-by: Santiago Figueroa Manrique --- .../include/power_grid_model/main_model_impl.hpp | 1 - 1 file changed, 1 deletion(-) 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 f2c51e8e0..d8ec3b592 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 @@ -166,7 +166,6 @@ class MainModelImpl, ComponentLis return state_.components.template size(); } - // TODO: possibly remove, as well as from main_model.hpp // all component count std::map> all_component_count() const { auto const get_comp_count = [this]() { From acf5c9644542cb414f23b5d4eeaf4d157a4103e3 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Thu, 21 Nov 2024 09:36:46 +0100 Subject: [PATCH 26/30] address comments Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 16 ++++++++-------- .../include/power_grid_model/main_model.hpp | 1 - .../power_grid_model/main_model_impl.hpp | 17 ----------------- tests/cpp_integration_tests/test_main_model.cpp | 4 ---- 4 files changed, 8 insertions(+), 30 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 0bd361b30..8d96a31ef 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 @@ -247,14 +247,14 @@ SequenceIdx get_all_sequence_idx_map(MainModelState SequenceIdx get_all_sequence_idx_map(MainModelState const& state, ConstDataset const& update_data) { - // Independence for all components is set to true as permanent updates involve only one scenario. - // Flags for all components (not only the ones present in update_data) are set to avoid more expensive checks. - constexpr ComponentFlags all_true = [] { - ComponentFlags result{}; - std::ranges::fill(result, true); - return result; - }(); - return get_all_sequence_idx_map(state, update_data, 0, all_true); + ComponentFlags components_to_store{}; + Idx comp_idx{}; + utils::run_functor_with_all_types_return_void( + [&update_data, &components_to_store, &comp_idx]() { + components_to_store[comp_idx] = (update_data.find_component(CompType::name, false) != invalid_index); + ++comp_idx; + }); + return get_all_sequence_idx_map(state, update_data, 0, components_to_store); } // template to update components diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp index acdaecd2f..cc749d64a 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp @@ -50,7 +50,6 @@ class MainModel { }; ~MainModel() { impl_.reset(); } - std::map> all_component_count() const { return impl().all_component_count(); } void get_indexer(std::string_view component_type, ID const* id_begin, Idx size, Idx* indexer_begin) const { impl().get_indexer(component_type, id_begin, size, indexer_begin); } 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 d8ec3b592..2bb8a7c05 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 @@ -166,23 +166,6 @@ class MainModelImpl, ComponentLis return state_.components.template size(); } - // all component count - std::map> all_component_count() const { - auto const get_comp_count = [this]() { - return make_pair(std::string{CT::name}, this->component_count()); - }; - auto const all_count = - main_core::utils::run_functor_with_all_types_return_array(get_comp_count); - std::map> result; - for (auto const& [name, count] : all_count) { - if (count > 0) { - // only add if count is greater than 0 - result[name] = count; - } - } - return result; - } - // helper function to get the number of components per type std::array get_n_components_per_type() const { std::array result{}; diff --git a/tests/cpp_integration_tests/test_main_model.cpp b/tests/cpp_integration_tests/test_main_model.cpp index baf63e3b3..f723532a8 100644 --- a/tests/cpp_integration_tests/test_main_model.cpp +++ b/tests/cpp_integration_tests/test_main_model.cpp @@ -1208,10 +1208,6 @@ TEST_CASE("Test main model - runtime dispatch") { state.asym_node.data()); MainModel model{50.0, input_data}; - auto const count = model.all_component_count(); - CHECK(count.at("node") == 3); - CHECK(count.at("source") == 2); - CHECK(count.find("sym_gen") == count.cend()); // calculation model.calculate(get_default_options(symmetric, newton_raphson), sym_result_data); From 979b9f8113c5da2a76ffe87d059736d9409058ae Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Fri, 22 Nov 2024 09:24:04 +0100 Subject: [PATCH 27/30] address comments Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 31 +++++++------- .../power_grid_model/main_model_impl.hpp | 42 ++++++++++--------- 2 files changed, 36 insertions(+), 37 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 8d96a31ef..8a2b3f157 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 @@ -17,12 +17,6 @@ namespace power_grid_model::main_core::update { constexpr Idx invalid_index{-1}; -// main core utils -template -constexpr auto index_of_component = main_core::utils::index_of_component; -template using SequenceIdx = main_core::utils::SequenceIdx; -template using ComponentFlags = main_core::utils::ComponentFlags; - namespace detail { template ForwardIterator, typename Func> requires std::invocable, typename Component::UpdateType, Idx2D const&> @@ -98,7 +92,7 @@ template void process_buffer_span(auto const& all_spans, Upd } // Remember the begin iterator of the first scenario, then loop over the remaining scenarios and // check the ids - auto const first_span = all_spans[0]; + auto const first_span = all_spans.front(); // check the subsequent scenarios // only return true if ids of all scenarios match the ids of the first batch @@ -157,9 +151,9 @@ inline void validate_update_data_independence(UpdateCompProperties const& comp) } template -ComponentFlags is_update_independent(ConstDataset const& update_data, - std::span relevant_component_count) { - ComponentFlags result{}; +main_core::utils::ComponentFlags +is_update_independent(ConstDataset const& update_data, std::span relevant_component_count) { + main_core::utils::ComponentFlags result{}; size_t comp_idx{}; utils::run_functor_with_all_types_return_void( [&result, &relevant_component_count, &update_data, &comp_idx]() { @@ -227,12 +221,13 @@ std::vector get_component_sequence(MainModelState con } // namespace detail template -SequenceIdx get_all_sequence_idx_map(MainModelState const& state, - ConstDataset const& update_data, Idx scenario_idx, - ComponentFlags const& components_to_store) { +main_core::utils::SequenceIdx +get_all_sequence_idx_map(MainModelState const& state, ConstDataset const& update_data, + Idx scenario_idx, + main_core::utils::ComponentFlags const& components_to_store) { return utils::run_functor_with_all_types_return_array( [&update_data, &components_to_store, &state, scenario_idx]() { - if (!std::get>(components_to_store)) { + if (!std::get>(components_to_store)) { return std::vector{}; } auto const n_components = state.components.template size(); @@ -245,12 +240,14 @@ SequenceIdx get_all_sequence_idx_map(MainModelState -SequenceIdx get_all_sequence_idx_map(MainModelState const& state, - ConstDataset const& update_data) { - ComponentFlags components_to_store{}; +main_core::utils::SequenceIdx +get_all_sequence_idx_map(MainModelState const& state, ConstDataset const& update_data) { + main_core::utils::ComponentFlags components_to_store{}; Idx comp_idx{}; utils::run_functor_with_all_types_return_void( [&update_data, &components_to_store, &comp_idx]() { + // In a permanent update, all components that are present are independent (because only one scenario is + // considered) hence all present components are labeled are marked true (independent), the rest are false. components_to_store[comp_idx] = (update_data.find_component(CompType::name, false) != invalid_index); ++comp_idx; }); 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 2bb8a7c05..b5e106c0b 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 @@ -45,6 +45,26 @@ namespace power_grid_model { +namespace detail { +template +static auto calculate_param(auto const& c, auto const&... extra_args) + requires requires { + { c.calc_param(extra_args...) }; + } +{ + return c.calc_param(extra_args...); +} + +template +static auto calculate_param(auto const& c, auto const&... extra_args) + requires requires { + { c.template calc_param(extra_args...) }; + } +{ + return c.template calc_param(extra_args...); +} +} // namespace detail + // solver output type to output type getter meta function template struct output_type_getter; @@ -1065,7 +1085,7 @@ class MainModelImpl, ComponentLis auto const& component = get_component_by_sequence(state, i); CalcStructOut& math_model_input = calc_input[math_idx.group]; std::vector& math_model_input_vect = math_model_input.*comp_vect; - math_model_input_vect[math_idx.pos] = calculate_param(component); + math_model_input_vect[math_idx.pos] = detail::calculate_param(component); } } } @@ -1086,7 +1106,7 @@ class MainModelImpl, ComponentLis CalcStructOut& math_model_input = calc_input[math_idx.group]; std::vector& math_model_input_vect = math_model_input.*comp_vect; math_model_input_vect[math_idx.pos] = - calculate_param(component, extra_args(component)); + detail::calculate_param(component, extra_args(component)); } } } @@ -1306,22 +1326,4 @@ class MainModelImpl, ComponentLis } }; -template -static auto calculate_param(auto const& c, auto const&... extra_args) - requires requires { - { c.calc_param(extra_args...) }; - } -{ - return c.calc_param(extra_args...); -} - -template -static auto calculate_param(auto const& c, auto const&... extra_args) - requires requires { - { c.template calc_param(extra_args...) }; - } -{ - return c.template calc_param(extra_args...); -} - } // namespace power_grid_model From 2a9bc418a53cad4bf4f7875eb5fc0ab0f6da9e09 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Fri, 22 Nov 2024 11:16:15 +0100 Subject: [PATCH 28/30] removed redundant usings Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/update.hpp | 2 - .../power_grid_model/main_model_impl.hpp | 77 ++++++++++--------- 2 files changed, 39 insertions(+), 40 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 8a2b3f157..958f48f77 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 @@ -246,8 +246,6 @@ get_all_sequence_idx_map(MainModelState const& state, ConstD Idx comp_idx{}; utils::run_functor_with_all_types_return_void( [&update_data, &components_to_store, &comp_idx]() { - // In a permanent update, all components that are present are independent (because only one scenario is - // considered) hence all present components are labeled are marked true (independent), the rest are false. components_to_store[comp_idx] = (update_data.find_component(CompType::name, false) != invalid_index); ++comp_idx; }); 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 b5e106c0b..88324ffc0 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 @@ -149,15 +149,7 @@ class MainModelImpl, ComponentLis using MainModelState = main_core::MainModelState; using MathState = main_core::MathState; - // main core utils - static constexpr auto n_types = main_core::utils::n_types; - template - static constexpr auto index_of_component = main_core::utils::index_of_component; - using SequenceIdx = main_core::utils::SequenceIdx; - using ComponentFlags = main_core::utils::ComponentFlags; - - using SequenceIdxView = std::array, n_types>; - + using SequenceIdxView = std::array, main_core::utils::n_types>; using OwnedUpdateDataset = std::tuple...>; static constexpr Idx ignore_output{-1}; @@ -187,8 +179,8 @@ class MainModelImpl, ComponentLis } // helper function to get the number of components per type - std::array get_n_components_per_type() const { - std::array result{}; + std::array> get_n_components_per_type() const { + std::array> result{}; size_t idx{}; main_core::utils::run_functor_with_all_types_return_void( [&result, this, &idx]() { @@ -237,7 +229,7 @@ class MainModelImpl, ComponentLis template ForwardIterator> void update_component(ForwardIterator begin, ForwardIterator end, std::span sequence_idx) { - constexpr auto comp_index = index_of_component; + constexpr auto comp_index = main_core::utils::index_of_component; assert(construction_complete_); assert(static_cast(sequence_idx.size()) == std::distance(begin, end)); @@ -297,12 +289,14 @@ class MainModelImpl, ComponentLis // overload to update all components across all scenarios template - requires(std::same_as || std::same_as) + requires(std::same_as> || + std::same_as) void update_components(ConstDataset const& update_data, Idx pos, SequenceIdxMap const& sequence_idx_map) { main_core::utils::run_functor_with_all_types_return_void( [this, pos, &update_data, &sequence_idx_map]() { - this->update_component_row_col(update_data, pos, - std::get>(sequence_idx_map)); + this->update_component_row_col( + update_data, pos, + std::get>(sequence_idx_map)); }); } // overload to update all components in the first scenario (e.g. permanent update) @@ -313,7 +307,7 @@ class MainModelImpl, ComponentLis } template void restore_component(SequenceIdxView const& sequence_idx) { - constexpr auto component_index = index_of_component; + constexpr auto component_index = main_core::utils::index_of_component; auto& cached_inverse_update = std::get(cached_inverse_update_); auto const& component_sequence = std::get(sequence_idx); @@ -331,13 +325,14 @@ class MainModelImpl, ComponentLis update_state(cached_state_changes_); cached_state_changes_ = {}; } - void restore_components(std::array const>, n_types> const& sequence_idx) { - restore_components( - std::array{std::span{std::get>(sequence_idx).get()}...}); + void restore_components(std::array const>, + main_core::utils::n_types> const& sequence_idx) { + restore_components(std::array{std::span{ + std::get>(sequence_idx).get()}...}); } - void restore_components(SequenceIdx const& sequence_idx) { - restore_components( - std::array{std::span{std::get>(sequence_idx)}...}); + void restore_components(main_core::utils::SequenceIdx const& sequence_idx) { + restore_components(std::array{std::span{ + std::get>(sequence_idx)}...}); } // set complete construction @@ -393,7 +388,8 @@ class MainModelImpl, ComponentLis } // Entry point for main_model.hpp - template SequenceIdx get_all_sequence_idx_map(ConstDataset const& update_data) { + template + main_core::utils::SequenceIdx get_all_sequence_idx_map(ConstDataset const& update_data) { return main_core::update::get_all_sequence_idx_map(state_, update_data); } @@ -534,7 +530,7 @@ class MainModelImpl, ComponentLis std::vector infos(n_scenarios); // lambda for sub batch calculation - SequenceIdx all_scenarios_sequence; + main_core::utils::SequenceIdx all_scenarios_sequence; auto sub_batch = sub_batch_calculation_(calculation_fn, result_data, update_data, all_scenarios_sequence, exceptions, infos); @@ -549,7 +545,8 @@ class MainModelImpl, ComponentLis template requires std::invocable, MainModelImpl&, MutableDataset const&, Idx> auto sub_batch_calculation_(Calculate&& calculation_fn, MutableDataset const& result_data, - ConstDataset const& update_data, SequenceIdx& all_scenarios_sequence, + ConstDataset const& update_data, + main_core::utils::SequenceIdx& all_scenarios_sequence, std::vector& exceptions, std::vector& infos) { // const ref of current instance MainModelImpl const& base_model = *this; @@ -576,7 +573,7 @@ class MainModelImpl, ComponentLis }; auto model = copy_model_functor(start); - SequenceIdx current_scenario_sequence_cache = SequenceIdx{}; + auto current_scenario_sequence_cache = main_core::utils::SequenceIdx{}; auto [setup, winddown] = scenario_update_restore(model, update_data, is_independent, all_scenarios_sequence, current_scenario_sequence_cache, infos); @@ -650,13 +647,14 @@ class MainModelImpl, ComponentLis }; } - static auto scenario_update_restore(MainModelImpl& model, ConstDataset const& update_data, - ComponentFlags const& independence_flags, - SequenceIdx const& all_scenario_sequence, - SequenceIdx& current_scenario_sequence_cache, - std::vector& infos) noexcept { + static auto + scenario_update_restore(MainModelImpl& model, ConstDataset const& update_data, + main_core::utils::ComponentFlags const& independence_flags, + main_core::utils::SequenceIdx const& all_scenario_sequence, + main_core::utils::SequenceIdx& current_scenario_sequence_cache, + std::vector& infos) noexcept { auto do_update_cache = [&independence_flags] { - ComponentFlags result; + main_core::utils::ComponentFlags result; std::ranges::transform(independence_flags, result.begin(), std::logical_not<>{}); return result; }(); @@ -665,7 +663,7 @@ class MainModelImpl, ComponentLis &independence_flags]() -> SequenceIdxView { return main_core::utils::run_functor_with_all_types_return_array( [&all_scenario_sequence, ¤t_scenario_sequence_cache, &independence_flags]() { - constexpr auto comp_idx = index_of_component; + constexpr auto comp_idx = main_core::utils::index_of_component; if (std::get(independence_flags)) { return std::span{std::get(all_scenario_sequence)}; } @@ -845,7 +843,7 @@ class MainModelImpl, ComponentLis OwnedUpdateDataset cached_inverse_update_{}; UpdateChange cached_state_changes_{}; - std::array, n_types> parameter_changed_components_{}; + std::array, main_core::utils::n_types> parameter_changed_components_{}; #ifndef NDEBUG // construction_complete is used for debug assertions only bool construction_complete_{false}; @@ -970,7 +968,7 @@ class MainModelImpl, ComponentLis template std::vector get_math_param_increment() { using AddToIncrement = void (*)(std::vector&, MainModelState const&, Idx2D const&); - static constexpr std::array add_to_increments{ + static constexpr std::array> add_to_increments{ [](std::vector& increments, MainModelState const& state, Idx2D const& changed_component_idx) { if constexpr (std::derived_from) { @@ -1009,7 +1007,7 @@ class MainModelImpl, ComponentLis std::vector math_param_increment(n_math_solvers_); - for (size_t i = 0; i < n_types; ++i) { + for (size_t i = 0; i < main_core::utils::n_types; ++i) { auto const& changed_type_components = parameter_changed_components_[i]; auto const& add_type_to_increment = add_to_increments[i]; for (auto const& changed_component : changed_type_components) { @@ -1267,8 +1265,11 @@ class MainModelImpl, ComponentLis // Check the branch and shunt indices constexpr auto branch_param_in_seq_map = - std::array{index_of_component, index_of_component, index_of_component}; - constexpr auto shunt_param_in_seq_map = std::array{index_of_component}; + std::array{main_core::utils::index_of_component, + main_core::utils::index_of_component, + main_core::utils::index_of_component}; + constexpr auto shunt_param_in_seq_map = + std::array{main_core::utils::index_of_component}; for (Idx i = 0; i != n_math_solvers_; ++i) { // construct from existing Y_bus structure if possible From c56adb238362b2a292d1de8378fbe4d2489d57fb Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Fri, 22 Nov 2024 14:57:51 +0100 Subject: [PATCH 29/30] final refactor attempt Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/core_utils.hpp | 2 + .../power_grid_model/main_core/update.hpp | 101 +++++++++--------- .../power_grid_model/main_model_impl.hpp | 80 +++++++------- 3 files changed, 88 insertions(+), 95 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/core_utils.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/core_utils.hpp index a87cc8dd7..93fb6d065 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/core_utils.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/core_utils.hpp @@ -12,6 +12,8 @@ namespace power_grid_model::main_core::utils { +constexpr Idx invalid_index{-1}; + template constexpr size_t n_types = sizeof...(ComponentTypes); template constexpr size_t index_of_component = container_impl::get_cls_pos_v; 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 958f48f77..4092eaf69 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 @@ -15,8 +15,6 @@ namespace power_grid_model::main_core::update { -constexpr Idx invalid_index{-1}; - namespace detail { template ForwardIterator, typename Func> requires std::invocable, typename Component::UpdateType, Idx2D const&> @@ -47,16 +45,16 @@ template bool check_id_na(T const& obj) { namespace independence { struct UpdateCompProperties { - std::string name{}; - bool has_any_elements{false}; // whether the component has any elements in the update data - bool ids_all_na{false}; // whether all ids are all NA - bool ids_part_na{false}; // whether some ids are NA but some are not - bool dense{false}; // whether the component is dense - bool uniform{false}; // whether the component is uniform - bool is_columnar{false}; // whether the component is columnar - bool update_ids_match{false}; // whether the ids match - Idx elements_ps_in_update{invalid_index}; // count of elements for this component per scenario in update - Idx elements_in_base{invalid_index}; // count of elements for this component per scenario in input + bool has_any_elements{false}; // whether the component has any elements in the update data + bool ids_all_na{false}; // whether all ids are all NA + bool ids_part_na{false}; // whether some ids are NA but some are not + bool dense{false}; // whether the component is dense + bool uniform{false}; // whether the component is uniform + bool is_columnar{false}; // whether the component is columnar + bool update_ids_match{false}; // whether the ids match + Idx elements_ps_in_update{ + main_core::utils::invalid_index}; // count of elements for this component per scenario in update + Idx elements_in_base{main_core::utils::invalid_index}; // count of elements for this component per scenario in input constexpr bool no_id() const { return !has_any_elements || ids_all_na; } constexpr bool qualify_for_optional_id() const { @@ -68,7 +66,7 @@ struct UpdateCompProperties { constexpr bool is_empty_component() const { return !has_any_elements; } constexpr bool is_independent() const { return qualify_for_optional_id() || provided_ids_valid(); } constexpr Idx get_n_elements() const { - assert(uniform || elements_ps_in_update == invalid_index); + assert(uniform || elements_ps_in_update == main_core::utils::invalid_index); return qualify_for_optional_id() ? elements_ps_in_update : na_Idx; } @@ -107,15 +105,14 @@ template void process_buffer_span(auto const& all_spans, Upd template UpdateCompProperties check_component_independence(ConstDataset const& update_data, Idx n_component) { UpdateCompProperties properties; - properties.name = CompType::name; - auto const component_idx = update_data.find_component(properties.name, false); - properties.is_columnar = update_data.is_columnar(properties.name); - properties.dense = update_data.is_dense(properties.name); - properties.uniform = update_data.is_uniform(properties.name); - properties.has_any_elements = - component_idx != invalid_index && update_data.get_component_info(component_idx).total_elements > 0; - properties.elements_ps_in_update = - properties.uniform ? update_data.uniform_elements_per_scenario(properties.name) : invalid_index; + auto const component_idx = update_data.find_component(CompType::name, false); + properties.is_columnar = update_data.is_columnar(CompType::name); + properties.dense = update_data.is_dense(CompType::name); + properties.uniform = update_data.is_uniform(CompType::name); + properties.has_any_elements = component_idx != main_core::utils::invalid_index && + update_data.get_component_info(component_idx).total_elements > 0; + properties.elements_ps_in_update = properties.uniform ? update_data.uniform_elements_per_scenario(CompType::name) + : main_core::utils::invalid_index; properties.elements_in_base = n_component; if (properties.is_columnar) { @@ -130,7 +127,10 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat return properties; } -inline void validate_update_data_independence(UpdateCompProperties const& comp) { +template +using UpdateIndependence = std::array>; + +inline void validate_update_data_independence(UpdateCompProperties const& comp, std::string const& comp_name) { if (comp.is_empty_component()) { return; // empty dataset is still supported } @@ -138,30 +138,26 @@ inline void validate_update_data_independence(UpdateCompProperties const& comp) assert(comp.uniform || elements_ps < 0); if (elements_ps >= 0 && comp.elements_in_base < elements_ps) { - throw DatasetError("Update data has more elements per scenario than input data for component " + comp.name + + throw DatasetError("Update data has more elements per scenario than input data for component " + comp_name + "!"); } if (comp.ids_part_na) { - throw DatasetError("IDs contain both numbers and NANs for component " + comp.name + " in update data!"); + throw DatasetError("IDs contain both numbers and NANs for component " + comp_name + " in update data!"); } if (comp.ids_all_na && comp.elements_in_base != elements_ps) { - throw DatasetError("Update data without IDs for component " + comp.name + + throw DatasetError("Update data without IDs for component " + comp_name + " has a different number of elements per scenario then input data!"); } } -template -main_core::utils::ComponentFlags -is_update_independent(ConstDataset const& update_data, std::span relevant_component_count) { - main_core::utils::ComponentFlags result{}; - size_t comp_idx{}; - utils::run_functor_with_all_types_return_void( - [&result, &relevant_component_count, &update_data, &comp_idx]() { - Idx const n_component = relevant_component_count[comp_idx]; - result[comp_idx] = check_component_independence(update_data, n_component).is_independent(); - ++comp_idx; +template +UpdateIndependence check_update_independence(MainModelState const& state, + ConstDataset const& update_data) { + return utils::run_functor_with_all_types_return_array( + [&state, &update_data]() { + auto const n_component = state.components.template size(); + return check_component_independence(update_data, n_component); }); - return result; } } // namespace independence @@ -224,16 +220,20 @@ template main_core::utils::SequenceIdx get_all_sequence_idx_map(MainModelState const& state, ConstDataset const& update_data, Idx scenario_idx, - main_core::utils::ComponentFlags const& components_to_store) { + main_core::utils::ComponentFlags const& components_to_store, + independence::UpdateIndependence const& independence, bool cached = true) { return utils::run_functor_with_all_types_return_array( - [&update_data, &components_to_store, &state, scenario_idx]() { - if (!std::get>(components_to_store)) { + [&state, &update_data, scenario_idx, &components_to_store, &independence, cached]() { + auto const comp_properties = + std::get>(independence); + bool const is_comp_independent = + cached ? comp_properties.is_independent() : !comp_properties.is_independent(); + if (!std::get>(components_to_store) || + !is_comp_independent) { return std::vector{}; } - auto const n_components = state.components.template size(); - auto const independence = independence::check_component_independence(update_data, n_components); - independence::validate_update_data_independence(independence); - return detail::get_component_sequence(state, update_data, scenario_idx, independence); + independence::validate_update_data_independence(comp_properties, CompType::name); + return detail::get_component_sequence(state, update_data, scenario_idx, comp_properties); }); } // Get sequence idx map of an entire batch for fast caching of component sequences. @@ -241,15 +241,10 @@ get_all_sequence_idx_map(MainModelState const& state, ConstD // This is the entry point for permanent updates. template main_core::utils::SequenceIdx -get_all_sequence_idx_map(MainModelState const& state, ConstDataset const& update_data) { - main_core::utils::ComponentFlags components_to_store{}; - Idx comp_idx{}; - utils::run_functor_with_all_types_return_void( - [&update_data, &components_to_store, &comp_idx]() { - components_to_store[comp_idx] = (update_data.find_component(CompType::name, false) != invalid_index); - ++comp_idx; - }); - return get_all_sequence_idx_map(state, update_data, 0, components_to_store); +get_all_sequence_idx_map(MainModelState const& state, ConstDataset const& update_data, + main_core::utils::ComponentFlags const& components_to_store, + independence::UpdateIndependence const& independence) { + return get_all_sequence_idx_map(state, update_data, 0, components_to_store, independence); } // template to update components 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 88324ffc0..4a29dbce0 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 @@ -172,22 +172,13 @@ class MainModelImpl, ComponentLis explicit MainModelImpl(double system_frequency, meta_data::MetaData const& meta_data) : system_frequency_{system_frequency}, meta_data_{&meta_data} {} - // get number - template Idx component_count() const { - assert(construction_complete_); - return state_.components.template size(); - } - - // helper function to get the number of components per type - std::array> get_n_components_per_type() const { - std::array> result{}; - size_t idx{}; - main_core::utils::run_functor_with_all_types_return_void( - [&result, this, &idx]() { - result[idx] = this->component_count(); - ++idx; + // helper function to get what components are present in the update data + std::array> + get_components_to_update(ConstDataset const& update_data) const { + return main_core::utils::run_functor_with_all_types_return_array( + [&update_data]() { + return (update_data.find_component(CompType::name, false) != main_core::utils::invalid_index); }); - return result; } // helper function to add vectors of components @@ -301,8 +292,11 @@ class MainModelImpl, ComponentLis } // overload to update all components in the first scenario (e.g. permanent update) template void update_components(ConstDataset const& update_data) { - auto const sequence_idx_map = - main_core::update::get_all_sequence_idx_map(state_, update_data); + auto const components_to_update = get_components_to_update(update_data); + auto const update_independence = + main_core::update::independence::check_update_independence(state_, update_data); + auto const sequence_idx_map = main_core::update::get_all_sequence_idx_map( + state_, update_data, 0, components_to_update, update_independence); update_components(update_data, 0, sequence_idx_map); } @@ -388,9 +382,12 @@ class MainModelImpl, ComponentLis } // Entry point for main_model.hpp - template main_core::utils::SequenceIdx get_all_sequence_idx_map(ConstDataset const& update_data) { - return main_core::update::get_all_sequence_idx_map(state_, update_data); + auto const components_to_update = get_components_to_update(update_data); + auto const update_independence = + main_core::update::independence::check_update_independence(state_, update_data); + return main_core::update::get_all_sequence_idx_map(state_, update_data, 0, + components_to_update, update_independence); } private: @@ -553,15 +550,15 @@ class MainModelImpl, ComponentLis // cache component update order where possible. // the order for a cacheable (independent) component by definition is the same across all scenarios - auto const relevant_component_count = get_n_components_per_type(); - auto const is_independent = main_core::update::independence::is_update_independent( - update_data, relevant_component_count); - all_scenarios_sequence = - main_core::update::get_all_sequence_idx_map(state_, update_data, 0, is_independent); + auto const components_to_update = get_components_to_update(update_data); + auto const update_independence = + main_core::update::independence::check_update_independence(state_, update_data); + all_scenarios_sequence = main_core::update::get_all_sequence_idx_map( + state_, update_data, 0, components_to_update, update_independence); return [&base_model, &exceptions, &infos, &calculation_fn, &result_data, &update_data, - &all_scenarios_sequence = std::as_const(all_scenarios_sequence), - is_independent](Idx start, Idx stride, Idx n_scenarios) { + &all_scenarios_sequence = std::as_const(all_scenarios_sequence), components_to_update, + update_independence](Idx start, Idx stride, Idx n_scenarios) { assert(n_scenarios <= narrow_cast(exceptions.size())); assert(n_scenarios <= narrow_cast(infos.size())); @@ -574,8 +571,9 @@ class MainModelImpl, ComponentLis auto model = copy_model_functor(start); auto current_scenario_sequence_cache = main_core::utils::SequenceIdx{}; - auto [setup, winddown] = scenario_update_restore(model, update_data, is_independent, all_scenarios_sequence, - current_scenario_sequence_cache, infos); + auto [setup, winddown] = + scenario_update_restore(model, update_data, components_to_update, update_independence, + all_scenarios_sequence, current_scenario_sequence_cache, infos); auto calculate_scenario = MainModelImpl::call_with( [&model, &calculation_fn, &result_data, &infos](Idx scenario_idx) { @@ -647,18 +645,16 @@ class MainModelImpl, ComponentLis }; } - static auto - scenario_update_restore(MainModelImpl& model, ConstDataset const& update_data, - main_core::utils::ComponentFlags const& independence_flags, - main_core::utils::SequenceIdx const& all_scenario_sequence, - main_core::utils::SequenceIdx& current_scenario_sequence_cache, - std::vector& infos) noexcept { - auto do_update_cache = [&independence_flags] { - main_core::utils::ComponentFlags result; - std::ranges::transform(independence_flags, result.begin(), std::logical_not<>{}); - return result; - }(); - + static auto scenario_update_restore( + MainModelImpl& model, ConstDataset const& update_data, + main_core::utils::ComponentFlags const& components_to_store, + main_core::update::independence::UpdateIndependence const& do_update_cache, + main_core::utils::SequenceIdx const& all_scenario_sequence, + main_core::utils::SequenceIdx& current_scenario_sequence_cache, + std::vector& infos) noexcept { + main_core::utils::ComponentFlags independence_flags{}; + std::ranges::transform(do_update_cache, independence_flags.begin(), + [](auto const& comp) { return comp.is_independent(); }); auto const scenario_sequence = [&all_scenario_sequence, ¤t_scenario_sequence_cache, &independence_flags]() -> SequenceIdxView { return main_core::utils::run_functor_with_all_types_return_array( @@ -672,11 +668,11 @@ class MainModelImpl, ComponentLis }; return std::make_pair( - [&model, &update_data, scenario_sequence, ¤t_scenario_sequence_cache, + [&model, &update_data, scenario_sequence, ¤t_scenario_sequence_cache, &components_to_store, do_update_cache_ = std::move(do_update_cache), &infos](Idx scenario_idx) { Timer const t_update_model(infos[scenario_idx], 1200, "Update model"); current_scenario_sequence_cache = main_core::update::get_all_sequence_idx_map( - model.state_, update_data, scenario_idx, do_update_cache_); + model.state_, update_data, scenario_idx, components_to_store, do_update_cache_, false); model.template update_components(update_data, scenario_idx, scenario_sequence()); }, From 520c174f93bb2d6a9ac116ec668eb893d397bda5 Mon Sep 17 00:00:00 2001 From: Santiago Figueroa Manrique Date: Mon, 25 Nov 2024 10:33:05 +0100 Subject: [PATCH 30/30] Revert "final refactor attempt" This reverts commit c56adb238362b2a292d1de8378fbe4d2489d57fb. Signed-off-by: Santiago Figueroa Manrique --- .../power_grid_model/main_core/core_utils.hpp | 2 - .../power_grid_model/main_core/update.hpp | 101 +++++++++--------- .../power_grid_model/main_model_impl.hpp | 80 +++++++------- 3 files changed, 95 insertions(+), 88 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/core_utils.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/core_utils.hpp index 93fb6d065..a87cc8dd7 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/core_utils.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/core_utils.hpp @@ -12,8 +12,6 @@ namespace power_grid_model::main_core::utils { -constexpr Idx invalid_index{-1}; - template constexpr size_t n_types = sizeof...(ComponentTypes); template constexpr size_t index_of_component = container_impl::get_cls_pos_v; 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 4092eaf69..958f48f77 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 @@ -15,6 +15,8 @@ namespace power_grid_model::main_core::update { +constexpr Idx invalid_index{-1}; + namespace detail { template ForwardIterator, typename Func> requires std::invocable, typename Component::UpdateType, Idx2D const&> @@ -45,16 +47,16 @@ template bool check_id_na(T const& obj) { namespace independence { struct UpdateCompProperties { - bool has_any_elements{false}; // whether the component has any elements in the update data - bool ids_all_na{false}; // whether all ids are all NA - bool ids_part_na{false}; // whether some ids are NA but some are not - bool dense{false}; // whether the component is dense - bool uniform{false}; // whether the component is uniform - bool is_columnar{false}; // whether the component is columnar - bool update_ids_match{false}; // whether the ids match - Idx elements_ps_in_update{ - main_core::utils::invalid_index}; // count of elements for this component per scenario in update - Idx elements_in_base{main_core::utils::invalid_index}; // count of elements for this component per scenario in input + std::string name{}; + bool has_any_elements{false}; // whether the component has any elements in the update data + bool ids_all_na{false}; // whether all ids are all NA + bool ids_part_na{false}; // whether some ids are NA but some are not + bool dense{false}; // whether the component is dense + bool uniform{false}; // whether the component is uniform + bool is_columnar{false}; // whether the component is columnar + bool update_ids_match{false}; // whether the ids match + Idx elements_ps_in_update{invalid_index}; // count of elements for this component per scenario in update + Idx elements_in_base{invalid_index}; // count of elements for this component per scenario in input constexpr bool no_id() const { return !has_any_elements || ids_all_na; } constexpr bool qualify_for_optional_id() const { @@ -66,7 +68,7 @@ struct UpdateCompProperties { constexpr bool is_empty_component() const { return !has_any_elements; } constexpr bool is_independent() const { return qualify_for_optional_id() || provided_ids_valid(); } constexpr Idx get_n_elements() const { - assert(uniform || elements_ps_in_update == main_core::utils::invalid_index); + assert(uniform || elements_ps_in_update == invalid_index); return qualify_for_optional_id() ? elements_ps_in_update : na_Idx; } @@ -105,14 +107,15 @@ template void process_buffer_span(auto const& all_spans, Upd template UpdateCompProperties check_component_independence(ConstDataset const& update_data, Idx n_component) { UpdateCompProperties properties; - auto const component_idx = update_data.find_component(CompType::name, false); - properties.is_columnar = update_data.is_columnar(CompType::name); - properties.dense = update_data.is_dense(CompType::name); - properties.uniform = update_data.is_uniform(CompType::name); - properties.has_any_elements = component_idx != main_core::utils::invalid_index && - update_data.get_component_info(component_idx).total_elements > 0; - properties.elements_ps_in_update = properties.uniform ? update_data.uniform_elements_per_scenario(CompType::name) - : main_core::utils::invalid_index; + properties.name = CompType::name; + auto const component_idx = update_data.find_component(properties.name, false); + properties.is_columnar = update_data.is_columnar(properties.name); + properties.dense = update_data.is_dense(properties.name); + properties.uniform = update_data.is_uniform(properties.name); + properties.has_any_elements = + component_idx != invalid_index && update_data.get_component_info(component_idx).total_elements > 0; + properties.elements_ps_in_update = + properties.uniform ? update_data.uniform_elements_per_scenario(properties.name) : invalid_index; properties.elements_in_base = n_component; if (properties.is_columnar) { @@ -127,10 +130,7 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat return properties; } -template -using UpdateIndependence = std::array>; - -inline void validate_update_data_independence(UpdateCompProperties const& comp, std::string const& comp_name) { +inline void validate_update_data_independence(UpdateCompProperties const& comp) { if (comp.is_empty_component()) { return; // empty dataset is still supported } @@ -138,26 +138,30 @@ inline void validate_update_data_independence(UpdateCompProperties const& comp, assert(comp.uniform || elements_ps < 0); if (elements_ps >= 0 && comp.elements_in_base < elements_ps) { - throw DatasetError("Update data has more elements per scenario than input data for component " + comp_name + + throw DatasetError("Update data has more elements per scenario than input data for component " + comp.name + "!"); } if (comp.ids_part_na) { - throw DatasetError("IDs contain both numbers and NANs for component " + comp_name + " in update data!"); + throw DatasetError("IDs contain both numbers and NANs for component " + comp.name + " in update data!"); } if (comp.ids_all_na && comp.elements_in_base != elements_ps) { - throw DatasetError("Update data without IDs for component " + comp_name + + throw DatasetError("Update data without IDs for component " + comp.name + " has a different number of elements per scenario then input data!"); } } -template -UpdateIndependence check_update_independence(MainModelState const& state, - ConstDataset const& update_data) { - return utils::run_functor_with_all_types_return_array( - [&state, &update_data]() { - auto const n_component = state.components.template size(); - return check_component_independence(update_data, n_component); +template +main_core::utils::ComponentFlags +is_update_independent(ConstDataset const& update_data, std::span relevant_component_count) { + main_core::utils::ComponentFlags result{}; + size_t comp_idx{}; + utils::run_functor_with_all_types_return_void( + [&result, &relevant_component_count, &update_data, &comp_idx]() { + Idx const n_component = relevant_component_count[comp_idx]; + result[comp_idx] = check_component_independence(update_data, n_component).is_independent(); + ++comp_idx; }); + return result; } } // namespace independence @@ -220,20 +224,16 @@ template main_core::utils::SequenceIdx get_all_sequence_idx_map(MainModelState const& state, ConstDataset const& update_data, Idx scenario_idx, - main_core::utils::ComponentFlags const& components_to_store, - independence::UpdateIndependence const& independence, bool cached = true) { + main_core::utils::ComponentFlags const& components_to_store) { return utils::run_functor_with_all_types_return_array( - [&state, &update_data, scenario_idx, &components_to_store, &independence, cached]() { - auto const comp_properties = - std::get>(independence); - bool const is_comp_independent = - cached ? comp_properties.is_independent() : !comp_properties.is_independent(); - if (!std::get>(components_to_store) || - !is_comp_independent) { + [&update_data, &components_to_store, &state, scenario_idx]() { + if (!std::get>(components_to_store)) { return std::vector{}; } - independence::validate_update_data_independence(comp_properties, CompType::name); - return detail::get_component_sequence(state, update_data, scenario_idx, comp_properties); + auto const n_components = state.components.template size(); + auto const independence = independence::check_component_independence(update_data, n_components); + independence::validate_update_data_independence(independence); + return detail::get_component_sequence(state, update_data, scenario_idx, independence); }); } // Get sequence idx map of an entire batch for fast caching of component sequences. @@ -241,10 +241,15 @@ get_all_sequence_idx_map(MainModelState const& state, ConstD // This is the entry point for permanent updates. template main_core::utils::SequenceIdx -get_all_sequence_idx_map(MainModelState const& state, ConstDataset const& update_data, - main_core::utils::ComponentFlags const& components_to_store, - independence::UpdateIndependence const& independence) { - return get_all_sequence_idx_map(state, update_data, 0, components_to_store, independence); +get_all_sequence_idx_map(MainModelState const& state, ConstDataset const& update_data) { + main_core::utils::ComponentFlags components_to_store{}; + Idx comp_idx{}; + utils::run_functor_with_all_types_return_void( + [&update_data, &components_to_store, &comp_idx]() { + components_to_store[comp_idx] = (update_data.find_component(CompType::name, false) != invalid_index); + ++comp_idx; + }); + return get_all_sequence_idx_map(state, update_data, 0, components_to_store); } // template to update components 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 4a29dbce0..88324ffc0 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 @@ -172,13 +172,22 @@ class MainModelImpl, ComponentLis explicit MainModelImpl(double system_frequency, meta_data::MetaData const& meta_data) : system_frequency_{system_frequency}, meta_data_{&meta_data} {} - // helper function to get what components are present in the update data - std::array> - get_components_to_update(ConstDataset const& update_data) const { - return main_core::utils::run_functor_with_all_types_return_array( - [&update_data]() { - return (update_data.find_component(CompType::name, false) != main_core::utils::invalid_index); + // get number + template Idx component_count() const { + assert(construction_complete_); + return state_.components.template size(); + } + + // helper function to get the number of components per type + std::array> get_n_components_per_type() const { + std::array> result{}; + size_t idx{}; + main_core::utils::run_functor_with_all_types_return_void( + [&result, this, &idx]() { + result[idx] = this->component_count(); + ++idx; }); + return result; } // helper function to add vectors of components @@ -292,11 +301,8 @@ class MainModelImpl, ComponentLis } // overload to update all components in the first scenario (e.g. permanent update) template void update_components(ConstDataset const& update_data) { - auto const components_to_update = get_components_to_update(update_data); - auto const update_independence = - main_core::update::independence::check_update_independence(state_, update_data); - auto const sequence_idx_map = main_core::update::get_all_sequence_idx_map( - state_, update_data, 0, components_to_update, update_independence); + auto const sequence_idx_map = + main_core::update::get_all_sequence_idx_map(state_, update_data); update_components(update_data, 0, sequence_idx_map); } @@ -382,12 +388,9 @@ class MainModelImpl, ComponentLis } // Entry point for main_model.hpp + template main_core::utils::SequenceIdx get_all_sequence_idx_map(ConstDataset const& update_data) { - auto const components_to_update = get_components_to_update(update_data); - auto const update_independence = - main_core::update::independence::check_update_independence(state_, update_data); - return main_core::update::get_all_sequence_idx_map(state_, update_data, 0, - components_to_update, update_independence); + return main_core::update::get_all_sequence_idx_map(state_, update_data); } private: @@ -550,15 +553,15 @@ class MainModelImpl, ComponentLis // cache component update order where possible. // the order for a cacheable (independent) component by definition is the same across all scenarios - auto const components_to_update = get_components_to_update(update_data); - auto const update_independence = - main_core::update::independence::check_update_independence(state_, update_data); - all_scenarios_sequence = main_core::update::get_all_sequence_idx_map( - state_, update_data, 0, components_to_update, update_independence); + auto const relevant_component_count = get_n_components_per_type(); + auto const is_independent = main_core::update::independence::is_update_independent( + update_data, relevant_component_count); + all_scenarios_sequence = + main_core::update::get_all_sequence_idx_map(state_, update_data, 0, is_independent); return [&base_model, &exceptions, &infos, &calculation_fn, &result_data, &update_data, - &all_scenarios_sequence = std::as_const(all_scenarios_sequence), components_to_update, - update_independence](Idx start, Idx stride, Idx n_scenarios) { + &all_scenarios_sequence = std::as_const(all_scenarios_sequence), + is_independent](Idx start, Idx stride, Idx n_scenarios) { assert(n_scenarios <= narrow_cast(exceptions.size())); assert(n_scenarios <= narrow_cast(infos.size())); @@ -571,9 +574,8 @@ class MainModelImpl, ComponentLis auto model = copy_model_functor(start); auto current_scenario_sequence_cache = main_core::utils::SequenceIdx{}; - auto [setup, winddown] = - scenario_update_restore(model, update_data, components_to_update, update_independence, - all_scenarios_sequence, current_scenario_sequence_cache, infos); + auto [setup, winddown] = scenario_update_restore(model, update_data, is_independent, all_scenarios_sequence, + current_scenario_sequence_cache, infos); auto calculate_scenario = MainModelImpl::call_with( [&model, &calculation_fn, &result_data, &infos](Idx scenario_idx) { @@ -645,16 +647,18 @@ class MainModelImpl, ComponentLis }; } - static auto scenario_update_restore( - MainModelImpl& model, ConstDataset const& update_data, - main_core::utils::ComponentFlags const& components_to_store, - main_core::update::independence::UpdateIndependence const& do_update_cache, - main_core::utils::SequenceIdx const& all_scenario_sequence, - main_core::utils::SequenceIdx& current_scenario_sequence_cache, - std::vector& infos) noexcept { - main_core::utils::ComponentFlags independence_flags{}; - std::ranges::transform(do_update_cache, independence_flags.begin(), - [](auto const& comp) { return comp.is_independent(); }); + static auto + scenario_update_restore(MainModelImpl& model, ConstDataset const& update_data, + main_core::utils::ComponentFlags const& independence_flags, + main_core::utils::SequenceIdx const& all_scenario_sequence, + main_core::utils::SequenceIdx& current_scenario_sequence_cache, + std::vector& infos) noexcept { + auto do_update_cache = [&independence_flags] { + main_core::utils::ComponentFlags result; + std::ranges::transform(independence_flags, result.begin(), std::logical_not<>{}); + return result; + }(); + auto const scenario_sequence = [&all_scenario_sequence, ¤t_scenario_sequence_cache, &independence_flags]() -> SequenceIdxView { return main_core::utils::run_functor_with_all_types_return_array( @@ -668,11 +672,11 @@ class MainModelImpl, ComponentLis }; return std::make_pair( - [&model, &update_data, scenario_sequence, ¤t_scenario_sequence_cache, &components_to_store, + [&model, &update_data, scenario_sequence, ¤t_scenario_sequence_cache, do_update_cache_ = std::move(do_update_cache), &infos](Idx scenario_idx) { Timer const t_update_model(infos[scenario_idx], 1200, "Update model"); current_scenario_sequence_cache = main_core::update::get_all_sequence_idx_map( - model.state_, update_data, scenario_idx, components_to_store, do_update_cache_, false); + model.state_, update_data, scenario_idx, do_update_cache_); model.template update_components(update_data, scenario_idx, scenario_sequence()); },