15
15
16
16
namespace power_grid_model ::main_core::update {
17
17
18
+ constexpr Idx invalid_index{-1 };
19
+
18
20
namespace detail {
19
21
template <component_c Component, forward_iterator_like<typename Component::UpdateType> ForwardIterator, typename Func>
20
22
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) {
45
47
46
48
namespace independence {
47
49
struct 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
58
60
59
61
constexpr bool no_id () const { return !has_any_elements || ids_all_na; }
60
62
constexpr bool qualify_for_optional_id () const {
@@ -66,7 +68,7 @@ struct UpdateCompProperties {
66
68
constexpr bool is_empty_component () const { return !has_any_elements; }
67
69
constexpr bool is_independent () const { return qualify_for_optional_id () || provided_ids_valid (); }
68
70
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);
70
72
71
73
return qualify_for_optional_id () ? elements_ps_in_update : na_Idx;
72
74
}
@@ -105,14 +107,15 @@ template <typename CompType> void process_buffer_span(auto const& all_spans, Upd
105
107
template <class CompType >
106
108
UpdateCompProperties check_component_independence (ConstDataset const & update_data, Idx n_component) {
107
109
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;
116
119
properties.elements_in_base = n_component;
117
120
118
121
if (properties.is_columnar ) {
@@ -127,37 +130,38 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat
127
130
return properties;
128
131
}
129
132
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) {
134
134
if (comp.is_empty_component ()) {
135
135
return ; // empty dataset is still supported
136
136
}
137
137
auto const elements_ps = comp.get_n_elements ();
138
138
assert (comp.uniform || elements_ps < 0 );
139
139
140
140
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 +
142
142
" !" );
143
143
}
144
144
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!" );
146
146
}
147
147
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 +
149
149
" has a different number of elements per scenario then input data!" );
150
150
}
151
151
}
152
152
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;
160
163
});
164
+ return result;
161
165
}
162
166
163
167
} // namespace independence
@@ -220,31 +224,32 @@ template <class... ComponentTypes, class ComponentContainer>
220
224
main_core::utils::SequenceIdx<ComponentTypes...>
221
225
get_all_sequence_idx_map (MainModelState<ComponentContainer> const & state, ConstDataset const & update_data,
222
226
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) {
225
228
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)) {
233
231
return std::vector<Idx2D>{};
234
232
}
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);
237
237
});
238
238
}
239
239
// Get sequence idx map of an entire batch for fast caching of component sequences.
240
240
// The sequence idx map of the batch is the same as that of the first scenario in the batch (assuming homogeneity)
241
241
// This is the entry point for permanent updates.
242
242
template <class ... ComponentTypes, class ComponentContainer >
243
243
main_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);
248
253
}
249
254
250
255
// template to update components
0 commit comments