15
15
16
16
namespace power_grid_model ::main_core::update {
17
17
18
- constexpr Idx invalid_index{-1 };
19
-
20
18
namespace detail {
21
19
template <component_c Component, forward_iterator_like<typename Component::UpdateType> ForwardIterator, typename Func>
22
20
requires std::invocable<std::remove_cvref_t <Func>, typename Component::UpdateType, Idx2D const &>
@@ -47,16 +45,16 @@ template <typename T> bool check_id_na(T const& obj) {
47
45
48
46
namespace independence {
49
47
struct UpdateCompProperties {
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
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
60
58
61
59
constexpr bool no_id () const { return !has_any_elements || ids_all_na; }
62
60
constexpr bool qualify_for_optional_id () const {
@@ -68,7 +66,7 @@ struct UpdateCompProperties {
68
66
constexpr bool is_empty_component () const { return !has_any_elements; }
69
67
constexpr bool is_independent () const { return qualify_for_optional_id () || provided_ids_valid (); }
70
68
constexpr Idx get_n_elements () const {
71
- assert (uniform || elements_ps_in_update == invalid_index);
69
+ assert (uniform || elements_ps_in_update == main_core::utils:: invalid_index);
72
70
73
71
return qualify_for_optional_id () ? elements_ps_in_update : na_Idx;
74
72
}
@@ -107,15 +105,14 @@ template <typename CompType> void process_buffer_span(auto const& all_spans, Upd
107
105
template <class CompType >
108
106
UpdateCompProperties check_component_independence (ConstDataset const & update_data, Idx n_component) {
109
107
UpdateCompProperties properties;
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;
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;
119
116
properties.elements_in_base = n_component;
120
117
121
118
if (properties.is_columnar ) {
@@ -130,38 +127,37 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat
130
127
return properties;
131
128
}
132
129
133
- inline void validate_update_data_independence (UpdateCompProperties const & comp) {
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) {
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>
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;
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);
163
160
});
164
- return result;
165
161
}
166
162
167
163
} // namespace independence
@@ -224,32 +220,31 @@ template <class... ComponentTypes, class ComponentContainer>
224
220
main_core::utils::SequenceIdx<ComponentTypes...>
225
221
get_all_sequence_idx_map (MainModelState<ComponentContainer> const & state, ConstDataset const & update_data,
226
222
Idx scenario_idx,
227
- main_core::utils::ComponentFlags<ComponentTypes...> const & components_to_store) {
223
+ main_core::utils::ComponentFlags<ComponentTypes...> const & components_to_store,
224
+ independence::UpdateIndependence<ComponentTypes...> const & independence, bool cached = true ) {
228
225
return utils::run_functor_with_all_types_return_array<ComponentTypes...>(
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)) {
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) {
231
233
return std::vector<Idx2D>{};
232
234
}
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);
235
+ independence::validate_update_data_independence (comp_properties, CompType::name);
236
+ return detail::get_component_sequence<CompType>(state, update_data, scenario_idx, comp_properties);
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...> 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);
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);
253
248
}
254
249
255
250
// template to update components
0 commit comments