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 new file mode 100644 index 000000000..a87cc8dd7 --- /dev/null +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/core_utils.hpp @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Contributors to the Power Grid Model project +// +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../all_components.hpp" +#include "../container.hpp" + +#include +#include + +namespace power_grid_model::main_core::utils { + +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) { + (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::main_core::utils 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_core/update.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp index 653ac9497..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 @@ -4,12 +4,18 @@ #pragma once +#include "core_utils.hpp" #include "state.hpp" #include "../all_components.hpp" #include "../common/iterator_like_concepts.hpp" +#include "../container.hpp" -namespace power_grid_model::main_core { +#include + +namespace power_grid_model::main_core::update { + +constexpr Idx invalid_index{-1}; namespace detail { template ForwardIterator, typename Func> @@ -26,14 +32,148 @@ 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 +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 + + 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; + return; + } + // Remember the begin iterator of the first scenario, then loop over the remaining scenarios and + // check the ids + 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 + + 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 +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; + 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; +} + +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("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 + + " 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; + }); + return result; +} + +} // namespace independence + +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) { +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) { @@ -53,14 +193,65 @@ inline void get_component_sequence(MainModelState const& sta 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) { +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(state, begin, end, std::back_inserter(result), n_comp_elements); + 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, + 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_iter(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); +} +} // namespace detail + +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) { + return utils::run_functor_with_all_types_return_array( + [&update_data, &components_to_store, &state, scenario_idx]() { + if (!std::get>(components_to_store)) { + 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); + }); +} +// 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 +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); +} + // template to update components // using forward interators // different selection based on component type @@ -98,7 +289,7 @@ template & state, ForwardIterator begin, ForwardIterator end, OutputIterator changed_it) { return update_component(state, begin, end, changed_it, - get_component_sequence(state, begin, end)); + detail::get_component_sequence_by_iter(state, begin, end)); } // template to get the inverse update for components @@ -127,7 +318,7 @@ template const& state, ForwardIterator begin, ForwardIterator end, OutputIterator destination) { return update_inverse(state, begin, end, destination, - get_component_sequence(state, begin, end)); + detail::get_component_sequence_by_iter(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.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp index 642e8d5d2..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 @@ -5,6 +5,7 @@ #pragma once #include "main_model_impl.hpp" +#include namespace power_grid_model { @@ -49,14 +50,13 @@ 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); } 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) { @@ -66,8 +66,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 b62b30cdc..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 @@ -31,6 +31,7 @@ // 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" @@ -44,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; @@ -128,58 +149,13 @@ class MainModelImpl, ComponentLis using MainModelState = main_core::MainModelState; using MathState = main_core::MathState; - template - static constexpr size_t index_of_component = container_impl::get_cls_pos_v; - - static constexpr size_t n_types = sizeof...(ComponentType); - - using SequenceIdx = std::array, n_types>; - using SequenceIdxView = std::array, n_types>; - + using SequenceIdxView = std::array, main_core::utils::n_types>; 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 ComponentFlags = std::array; - using ComponentCountInBase = std::pair; - static constexpr Idx ignore_output{-1}; - static constexpr Idx invalid_index{-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()()... }; - } + static constexpr Idx isolated_component{-1}; + static constexpr Idx not_connected{-1}; + static constexpr Idx sequential{-1}; public: using Options = MainModelOptions; @@ -202,19 +178,15 @@ class MainModelImpl, ComponentLis return state_.components.template size(); } - // all component count - std::map> all_component_count() const { - 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); - std::map> result; - for (auto const& [name, count] : all_count) { - if (count > 0) { - // only add if count is greater than 0 - result[name] = count; - } - } + // 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; } @@ -247,7 +219,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 @@ -257,17 +229,17 @@ 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)); 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 @@ -277,7 +249,7 @@ class MainModelImpl, ComponentLis } } - // helper function to update vectors of components + // ovearloads to update all components of a single type across all scenarios template void update_component(std::vector const& components, std::span sequence_idx) { @@ -300,8 +272,9 @@ class MainModelImpl, ComponentLis } } + // entry point overload to update one row or column based component type 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")); @@ -314,25 +287,27 @@ class MainModelImpl, ComponentLis } } - // update all components - template - void update_component(ConstDataset const& update_data, Idx pos, SequenceIdxView 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, 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)); - }); + // 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) { + 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)); + }); } - template void update_component(ConstDataset const& update_data) { - update_component(update_data, 0, get_sequence_idx_map(update_data.get_individual_scenario(0))); + // 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); + update_components(update_data, 0, sequence_idx_map); } 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); @@ -350,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 @@ -408,49 +384,13 @@ 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 - template - std::vector get_component_sequence(ConstDataset const& update_data, Idx scenario_idx, - 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 - return 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); - return get_component_sequence(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 + 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); } private: @@ -552,7 +492,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()) { @@ -590,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); @@ -605,15 +545,19 @@ 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; // 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); - all_scenarios_sequence = get_sequence_idx_map(update_data, 0, is_independent); + 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), @@ -629,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); @@ -703,22 +647,24 @@ class MainModelImpl, ComponentLis }; } - static auto scenario_update_restore(MainModelImpl& model, ConstDataset const& update_data, - ComponentFlags const& is_independent, SequenceIdx const& all_scenario_sequence, - SequenceIdx& current_scenario_sequence_cache, - std::vector& infos) noexcept { - auto do_update_cache = [&is_independent] { - ComponentFlags result; - std::ranges::transform(is_independent, result.begin(), std::logical_not<>{}); + 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, - &is_independent]() -> SequenceIdxView { - return run_functor_with_all_types_return_array( - [&all_scenario_sequence, ¤t_scenario_sequence_cache, &is_independent]() { - constexpr auto comp_idx = index_of_component; - if (std::get(is_independent)) { + &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 = main_core::utils::index_of_component; + if (std::get(independence_flags)) { return std::span{std::get(all_scenario_sequence)}; } return std::span{std::get(current_scenario_sequence_cache)}; @@ -729,10 +675,10 @@ 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_); + current_scenario_sequence_cache = main_core::update::get_all_sequence_idx_map( + model.state_, 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"); @@ -777,110 +723,6 @@ 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; - - 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; }); - }); - } - }; - - 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; - }; - - return check_each_component(); - } - - 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); }); - } - - 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; - } - - void validate_update_data_independence(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] { @@ -903,7 +745,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); } @@ -977,7 +819,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_; } @@ -1001,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}; @@ -1081,7 +923,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 @@ -1091,7 +933,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 @@ -1104,7 +946,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 @@ -1114,7 +956,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 @@ -1126,14 +968,14 @@ 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) { Idx2D const math_idx = state.topo_comp_coup - ->branch[main_core::get_component_sequence(state, changed_component_idx)]; - if (math_idx.group == -1) { + ->branch[main_core::get_component_sequence_idx(state, changed_component_idx)]; + if (math_idx.group == isolated_component) { return; } // assign parameters @@ -1141,8 +983,8 @@ 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)]; - if (math_idx.group == -1) { + ->branch3[main_core::get_component_sequence_idx(state, changed_component_idx)]; + if (math_idx.group == isolated_component) { return; } // assign parameters, branch3 param consists of three branch parameters @@ -1154,8 +996,8 @@ 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)]; - if (math_idx.group == -1) { + ->shunt[main_core::get_component_sequence_idx(state, changed_component_idx)]; + if (math_idx.group == isolated_component) { return; } // assign parameters @@ -1165,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) { @@ -1237,11 +1079,11 @@ 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; - math_model_input_vect[math_idx.pos] = calculate_param(component); + math_model_input_vect[math_idx.pos] = detail::calculate_param(component); } } } @@ -1257,41 +1099,23 @@ 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; math_model_input_vect[math_idx.pos] = - calculate_param(component, extra_args(component)); + detail::calculate_param(component, extra_args(component)); } } } } - 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) { 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] = @@ -1399,7 +1223,8 @@ 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) { @@ -1440,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 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; 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 621caebc2..199991c46 100644 --- a/tests/cpp_integration_tests/test_main_model.cpp +++ b/tests/cpp_integration_tests/test_main_model.cpp @@ -503,7 +503,7 @@ TEST_CASE_TEMPLATE("Test main model - unknown id", settings, regular_update, 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( @@ -517,7 +517,7 @@ TEST_CASE_TEMPLATE( 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 = @@ -567,7 +567,7 @@ TEST_CASE_TEMPLATE( 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 = @@ -624,7 +624,7 @@ TEST_CASE_TEMPLATE( 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 = @@ -676,7 +676,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 = @@ -727,7 +727,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") { @@ -824,7 +824,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)); @@ -840,13 +840,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 = @@ -914,10 +914,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); @@ -937,7 +933,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)); @@ -1109,8 +1105,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()); @@ -1163,8 +1159,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()); @@ -1205,7 +1201,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 6625ae107..714d53dee 100644 --- a/tests/cpp_integration_tests/test_main_model_se.cpp +++ b/tests/cpp_integration_tests/test_main_model_se.cpp @@ -336,7 +336,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); 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) {