1515
1616namespace power_grid_model ::main_core::update {
1717
18+ constexpr Idx invalid_index{-1 };
19+
1820namespace detail {
1921template <component_c Component, forward_iterator_like<typename Component::UpdateType> ForwardIterator, typename Func>
2022 requires std::invocable<std::remove_cvref_t <Func>, typename Component::UpdateType, Idx2D const &>
@@ -45,16 +47,16 @@ template <typename T> bool check_id_na(T const& obj) {
4547
4648namespace independence {
4749struct UpdateCompProperties {
48- bool has_any_elements{ false }; // whether the component has any elements in the update data
49- bool ids_all_na {false }; // whether all ids are all NA
50- bool ids_part_na {false }; // whether some ids are NA but some are not
51- bool dense {false }; // whether the component is dense
52- bool uniform {false }; // whether the component is uniform
53- bool is_columnar {false }; // whether the component is columnar
54- bool update_ids_match {false }; // whether the ids match
55- Idx elements_ps_in_update{
56- main_core::utils:: invalid_index}; // count of elements for this component per scenario in update
57- Idx elements_in_base{main_core::utils:: invalid_index}; // count of elements for this component per scenario in input
50+ std::string name{};
51+ bool has_any_elements {false }; // whether the component has any elements in the update data
52+ bool ids_all_na {false }; // whether all ids are all NA
53+ bool ids_part_na {false }; // whether some ids are NA but some are not
54+ bool dense {false }; // whether the component is dense
55+ bool uniform {false }; // whether the component is uniform
56+ bool is_columnar {false }; // whether the component is columnar
57+ bool update_ids_match{ false }; // whether the ids match
58+ Idx elements_ps_in_update{ invalid_index}; // count of elements for this component per scenario in update
59+ Idx elements_in_base{invalid_index}; // count of elements for this component per scenario in input
5860
5961 constexpr bool no_id () const { return !has_any_elements || ids_all_na; }
6062 constexpr bool qualify_for_optional_id () const {
@@ -66,7 +68,7 @@ struct UpdateCompProperties {
6668 constexpr bool is_empty_component () const { return !has_any_elements; }
6769 constexpr bool is_independent () const { return qualify_for_optional_id () || provided_ids_valid (); }
6870 constexpr Idx get_n_elements () const {
69- assert (uniform || elements_ps_in_update == main_core::utils:: invalid_index);
71+ assert (uniform || elements_ps_in_update == invalid_index);
7072
7173 return qualify_for_optional_id () ? elements_ps_in_update : na_Idx;
7274 }
@@ -105,14 +107,15 @@ template <typename CompType> void process_buffer_span(auto const& all_spans, Upd
105107template <class CompType >
106108UpdateCompProperties check_component_independence (ConstDataset const & update_data, Idx n_component) {
107109 UpdateCompProperties properties;
108- auto const component_idx = update_data.find_component (CompType::name, false );
109- properties.is_columnar = update_data.is_columnar (CompType::name);
110- properties.dense = update_data.is_dense (CompType::name);
111- properties.uniform = update_data.is_uniform (CompType::name);
112- properties.has_any_elements = component_idx != main_core::utils::invalid_index &&
113- update_data.get_component_info (component_idx).total_elements > 0 ;
114- properties.elements_ps_in_update = properties.uniform ? update_data.uniform_elements_per_scenario (CompType::name)
115- : main_core::utils::invalid_index;
110+ properties.name = CompType::name;
111+ auto const component_idx = update_data.find_component (properties.name , false );
112+ properties.is_columnar = update_data.is_columnar (properties.name );
113+ properties.dense = update_data.is_dense (properties.name );
114+ properties.uniform = update_data.is_uniform (properties.name );
115+ properties.has_any_elements =
116+ component_idx != invalid_index && update_data.get_component_info (component_idx).total_elements > 0 ;
117+ properties.elements_ps_in_update =
118+ properties.uniform ? update_data.uniform_elements_per_scenario (properties.name ) : invalid_index;
116119 properties.elements_in_base = n_component;
117120
118121 if (properties.is_columnar ) {
@@ -127,37 +130,38 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat
127130 return properties;
128131}
129132
130- template <class ... ComponentTypes>
131- using UpdateIndependence = std::array<UpdateCompProperties, main_core::utils::n_types<ComponentTypes...>>;
132-
133- inline void validate_update_data_independence (UpdateCompProperties const & comp, std::string const & comp_name) {
133+ inline void validate_update_data_independence (UpdateCompProperties const & comp) {
134134 if (comp.is_empty_component ()) {
135135 return ; // empty dataset is still supported
136136 }
137137 auto const elements_ps = comp.get_n_elements ();
138138 assert (comp.uniform || elements_ps < 0 );
139139
140140 if (elements_ps >= 0 && comp.elements_in_base < elements_ps) {
141- throw DatasetError (" Update data has more elements per scenario than input data for component " + comp_name +
141+ throw DatasetError (" Update data has more elements per scenario than input data for component " + comp. name +
142142 " !" );
143143 }
144144 if (comp.ids_part_na ) {
145- throw DatasetError (" IDs contain both numbers and NANs for component " + comp_name + " in update data!" );
145+ throw DatasetError (" IDs contain both numbers and NANs for component " + comp. name + " in update data!" );
146146 }
147147 if (comp.ids_all_na && comp.elements_in_base != elements_ps) {
148- throw DatasetError (" Update data without IDs for component " + comp_name +
148+ throw DatasetError (" Update data without IDs for component " + comp. name +
149149 " has a different number of elements per scenario then input data!" );
150150 }
151151}
152152
153- template <class ... ComponentTypes, class ComponentContainer >
154- UpdateIndependence<ComponentTypes...> check_update_independence (MainModelState<ComponentContainer> const & state,
155- ConstDataset const & update_data) {
156- return utils::run_functor_with_all_types_return_array<ComponentTypes...>(
157- [&state, &update_data]<typename CompType>() {
158- auto const n_component = state.components .template size <CompType>();
159- return check_component_independence<CompType>(update_data, n_component);
153+ template <class ... ComponentTypes>
154+ main_core::utils::ComponentFlags<ComponentTypes...>
155+ is_update_independent (ConstDataset const & update_data, std::span<Idx const > relevant_component_count) {
156+ main_core::utils::ComponentFlags<ComponentTypes...> result{};
157+ size_t comp_idx{};
158+ utils::run_functor_with_all_types_return_void<ComponentTypes...>(
159+ [&result, &relevant_component_count, &update_data, &comp_idx]<typename CompType>() {
160+ Idx const n_component = relevant_component_count[comp_idx];
161+ result[comp_idx] = check_component_independence<CompType>(update_data, n_component).is_independent ();
162+ ++comp_idx;
160163 });
164+ return result;
161165}
162166
163167} // namespace independence
@@ -220,31 +224,32 @@ template <class... ComponentTypes, class ComponentContainer>
220224main_core::utils::SequenceIdx<ComponentTypes...>
221225get_all_sequence_idx_map (MainModelState<ComponentContainer> const & state, ConstDataset const & update_data,
222226 Idx scenario_idx,
223- main_core::utils::ComponentFlags<ComponentTypes...> const & components_to_store,
224- independence::UpdateIndependence<ComponentTypes...> const & independence, bool cached = true ) {
227+ main_core::utils::ComponentFlags<ComponentTypes...> const & components_to_store) {
225228 return utils::run_functor_with_all_types_return_array<ComponentTypes...>(
226- [&state, &update_data, scenario_idx, &components_to_store, &independence, cached]<typename CompType>() {
227- auto const comp_properties =
228- std::get<main_core::utils::index_of_component<CompType, ComponentTypes...>>(independence);
229- bool const is_comp_independent =
230- cached ? comp_properties.is_independent () : !comp_properties.is_independent ();
231- if (!std::get<main_core::utils::index_of_component<CompType, ComponentTypes...>>(components_to_store) ||
232- !is_comp_independent) {
229+ [&update_data, &components_to_store, &state, scenario_idx]<typename CompType>() {
230+ if (!std::get<main_core::utils::index_of_component<CompType, ComponentTypes...>>(components_to_store)) {
233231 return std::vector<Idx2D>{};
234232 }
235- independence::validate_update_data_independence (comp_properties, CompType::name);
236- return detail::get_component_sequence<CompType>(state, update_data, scenario_idx, comp_properties);
233+ auto const n_components = state.components .template size <CompType>();
234+ auto const independence = independence::check_component_independence<CompType>(update_data, n_components);
235+ independence::validate_update_data_independence (independence);
236+ return detail::get_component_sequence<CompType>(state, update_data, scenario_idx, independence);
237237 });
238238}
239239// Get sequence idx map of an entire batch for fast caching of component sequences.
240240// The sequence idx map of the batch is the same as that of the first scenario in the batch (assuming homogeneity)
241241// This is the entry point for permanent updates.
242242template <class ... ComponentTypes, class ComponentContainer >
243243main_core::utils::SequenceIdx<ComponentTypes...>
244- get_all_sequence_idx_map (MainModelState<ComponentContainer> const & state, ConstDataset const & update_data,
245- main_core::utils::ComponentFlags<ComponentTypes...> const & components_to_store,
246- independence::UpdateIndependence<ComponentTypes...> const & independence) {
247- return get_all_sequence_idx_map<ComponentTypes...>(state, update_data, 0 , components_to_store, independence);
244+ get_all_sequence_idx_map (MainModelState<ComponentContainer> const & state, ConstDataset const & update_data) {
245+ main_core::utils::ComponentFlags<ComponentTypes...> components_to_store{};
246+ Idx comp_idx{};
247+ utils::run_functor_with_all_types_return_void<ComponentTypes...>(
248+ [&update_data, &components_to_store, &comp_idx]<typename CompType>() {
249+ components_to_store[comp_idx] = (update_data.find_component (CompType::name, false ) != invalid_index);
250+ ++comp_idx;
251+ });
252+ return get_all_sequence_idx_map<ComponentTypes...>(state, update_data, 0 , components_to_store);
248253}
249254
250255// template to update components
0 commit comments