Skip to content

Commit c56adb2

Browse files
committed
final refactor attempt
Signed-off-by: Santiago Figueroa Manrique <santiago.figueroa.manrique@alliander.com>
1 parent 2a9bc41 commit c56adb2

File tree

3 files changed

+88
-95
lines changed

3 files changed

+88
-95
lines changed

power_grid_model_c/power_grid_model/include/power_grid_model/main_core/core_utils.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
namespace power_grid_model::main_core::utils {
1414

15+
constexpr Idx invalid_index{-1};
16+
1517
template <class... ComponentTypes> constexpr size_t n_types = sizeof...(ComponentTypes);
1618
template <class CompType, class... ComponentTypes>
1719
constexpr size_t index_of_component = container_impl::get_cls_pos_v<CompType, ComponentTypes...>;

power_grid_model_c/power_grid_model/include/power_grid_model/main_core/update.hpp

Lines changed: 48 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515

1616
namespace power_grid_model::main_core::update {
1717

18-
constexpr Idx invalid_index{-1};
19-
2018
namespace detail {
2119
template <component_c Component, forward_iterator_like<typename Component::UpdateType> ForwardIterator, typename Func>
2220
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) {
4745

4846
namespace independence {
4947
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
6058

6159
constexpr bool no_id() const { return !has_any_elements || ids_all_na; }
6260
constexpr bool qualify_for_optional_id() const {
@@ -68,7 +66,7 @@ struct UpdateCompProperties {
6866
constexpr bool is_empty_component() const { return !has_any_elements; }
6967
constexpr bool is_independent() const { return qualify_for_optional_id() || provided_ids_valid(); }
7068
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);
7270

7371
return qualify_for_optional_id() ? elements_ps_in_update : na_Idx;
7472
}
@@ -107,15 +105,14 @@ template <typename CompType> void process_buffer_span(auto const& all_spans, Upd
107105
template <class CompType>
108106
UpdateCompProperties check_component_independence(ConstDataset const& update_data, Idx n_component) {
109107
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;
119116
properties.elements_in_base = n_component;
120117

121118
if (properties.is_columnar) {
@@ -130,38 +127,37 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat
130127
return properties;
131128
}
132129

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) {
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>
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);
163160
});
164-
return result;
165161
}
166162

167163
} // namespace independence
@@ -224,32 +220,31 @@ template <class... ComponentTypes, class ComponentContainer>
224220
main_core::utils::SequenceIdx<ComponentTypes...>
225221
get_all_sequence_idx_map(MainModelState<ComponentContainer> const& state, ConstDataset const& update_data,
226222
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) {
228225
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) {
231233
return std::vector<Idx2D>{};
232234
}
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);
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.
242242
template <class... ComponentTypes, class ComponentContainer>
243243
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);
253248
}
254249

255250
// template to update components

power_grid_model_c/power_grid_model/include/power_grid_model/main_model_impl.hpp

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -172,22 +172,13 @@ class MainModelImpl<ExtraRetrievableTypes<ExtraRetrievableType...>, ComponentLis
172172
explicit MainModelImpl(double system_frequency, meta_data::MetaData const& meta_data)
173173
: system_frequency_{system_frequency}, meta_data_{&meta_data} {}
174174

175-
// get number
176-
template <class CompType> Idx component_count() const {
177-
assert(construction_complete_);
178-
return state_.components.template size<CompType>();
179-
}
180-
181-
// helper function to get the number of components per type
182-
std::array<Idx, main_core::utils::n_types<ComponentType...>> get_n_components_per_type() const {
183-
std::array<Idx, main_core::utils::n_types<ComponentType...>> result{};
184-
size_t idx{};
185-
main_core::utils::run_functor_with_all_types_return_void<ComponentType...>(
186-
[&result, this, &idx]<typename CompType>() {
187-
result[idx] = this->component_count<CompType>();
188-
++idx;
175+
// helper function to get what components are present in the update data
176+
std::array<bool, main_core::utils::n_types<ComponentType...>>
177+
get_components_to_update(ConstDataset const& update_data) const {
178+
return main_core::utils::run_functor_with_all_types_return_array<ComponentType...>(
179+
[&update_data]<typename CompType>() {
180+
return (update_data.find_component(CompType::name, false) != main_core::utils::invalid_index);
189181
});
190-
return result;
191182
}
192183

193184
// helper function to add vectors of components
@@ -301,8 +292,11 @@ class MainModelImpl<ExtraRetrievableTypes<ExtraRetrievableType...>, ComponentLis
301292
}
302293
// overload to update all components in the first scenario (e.g. permanent update)
303294
template <cache_type_c CacheType> void update_components(ConstDataset const& update_data) {
304-
auto const sequence_idx_map =
305-
main_core::update::get_all_sequence_idx_map<ComponentType...>(state_, update_data);
295+
auto const components_to_update = get_components_to_update(update_data);
296+
auto const update_independence =
297+
main_core::update::independence::check_update_independence<ComponentType...>(state_, update_data);
298+
auto const sequence_idx_map = main_core::update::get_all_sequence_idx_map<ComponentType...>(
299+
state_, update_data, 0, components_to_update, update_independence);
306300
update_components<CacheType>(update_data, 0, sequence_idx_map);
307301
}
308302

@@ -388,9 +382,12 @@ class MainModelImpl<ExtraRetrievableTypes<ExtraRetrievableType...>, ComponentLis
388382
}
389383

390384
// Entry point for main_model.hpp
391-
template <class... ComponentTypes>
392385
main_core::utils::SequenceIdx<ComponentType...> get_all_sequence_idx_map(ConstDataset const& update_data) {
393-
return main_core::update::get_all_sequence_idx_map<ComponentType...>(state_, update_data);
386+
auto const components_to_update = get_components_to_update(update_data);
387+
auto const update_independence =
388+
main_core::update::independence::check_update_independence<ComponentType...>(state_, update_data);
389+
return main_core::update::get_all_sequence_idx_map<ComponentType...>(state_, update_data, 0,
390+
components_to_update, update_independence);
394391
}
395392

396393
private:
@@ -553,15 +550,15 @@ class MainModelImpl<ExtraRetrievableTypes<ExtraRetrievableType...>, ComponentLis
553550

554551
// cache component update order where possible.
555552
// the order for a cacheable (independent) component by definition is the same across all scenarios
556-
auto const relevant_component_count = get_n_components_per_type();
557-
auto const is_independent = main_core::update::independence::is_update_independent<ComponentType...>(
558-
update_data, relevant_component_count);
559-
all_scenarios_sequence =
560-
main_core::update::get_all_sequence_idx_map<ComponentType...>(state_, update_data, 0, is_independent);
553+
auto const components_to_update = get_components_to_update(update_data);
554+
auto const update_independence =
555+
main_core::update::independence::check_update_independence<ComponentType...>(state_, update_data);
556+
all_scenarios_sequence = main_core::update::get_all_sequence_idx_map<ComponentType...>(
557+
state_, update_data, 0, components_to_update, update_independence);
561558

562559
return [&base_model, &exceptions, &infos, &calculation_fn, &result_data, &update_data,
563-
&all_scenarios_sequence = std::as_const(all_scenarios_sequence),
564-
is_independent](Idx start, Idx stride, Idx n_scenarios) {
560+
&all_scenarios_sequence = std::as_const(all_scenarios_sequence), components_to_update,
561+
update_independence](Idx start, Idx stride, Idx n_scenarios) {
565562
assert(n_scenarios <= narrow_cast<Idx>(exceptions.size()));
566563
assert(n_scenarios <= narrow_cast<Idx>(infos.size()));
567564

@@ -574,8 +571,9 @@ class MainModelImpl<ExtraRetrievableTypes<ExtraRetrievableType...>, ComponentLis
574571
auto model = copy_model_functor(start);
575572

576573
auto current_scenario_sequence_cache = main_core::utils::SequenceIdx<ComponentType...>{};
577-
auto [setup, winddown] = scenario_update_restore(model, update_data, is_independent, all_scenarios_sequence,
578-
current_scenario_sequence_cache, infos);
574+
auto [setup, winddown] =
575+
scenario_update_restore(model, update_data, components_to_update, update_independence,
576+
all_scenarios_sequence, current_scenario_sequence_cache, infos);
579577

580578
auto calculate_scenario = MainModelImpl::call_with<Idx>(
581579
[&model, &calculation_fn, &result_data, &infos](Idx scenario_idx) {
@@ -647,18 +645,16 @@ class MainModelImpl<ExtraRetrievableTypes<ExtraRetrievableType...>, ComponentLis
647645
};
648646
}
649647

650-
static auto
651-
scenario_update_restore(MainModelImpl& model, ConstDataset const& update_data,
652-
main_core::utils::ComponentFlags<ComponentType...> const& independence_flags,
653-
main_core::utils::SequenceIdx<ComponentType...> const& all_scenario_sequence,
654-
main_core::utils::SequenceIdx<ComponentType...>& current_scenario_sequence_cache,
655-
std::vector<CalculationInfo>& infos) noexcept {
656-
auto do_update_cache = [&independence_flags] {
657-
main_core::utils::ComponentFlags<ComponentType...> result;
658-
std::ranges::transform(independence_flags, result.begin(), std::logical_not<>{});
659-
return result;
660-
}();
661-
648+
static auto scenario_update_restore(
649+
MainModelImpl& model, ConstDataset const& update_data,
650+
main_core::utils::ComponentFlags<ComponentType...> const& components_to_store,
651+
main_core::update::independence::UpdateIndependence<ComponentType...> const& do_update_cache,
652+
main_core::utils::SequenceIdx<ComponentType...> const& all_scenario_sequence,
653+
main_core::utils::SequenceIdx<ComponentType...>& current_scenario_sequence_cache,
654+
std::vector<CalculationInfo>& infos) noexcept {
655+
main_core::utils::ComponentFlags<ComponentType...> independence_flags{};
656+
std::ranges::transform(do_update_cache, independence_flags.begin(),
657+
[](auto const& comp) { return comp.is_independent(); });
662658
auto const scenario_sequence = [&all_scenario_sequence, &current_scenario_sequence_cache,
663659
&independence_flags]() -> SequenceIdxView {
664660
return main_core::utils::run_functor_with_all_types_return_array<ComponentType...>(
@@ -672,11 +668,11 @@ class MainModelImpl<ExtraRetrievableTypes<ExtraRetrievableType...>, ComponentLis
672668
};
673669

674670
return std::make_pair(
675-
[&model, &update_data, scenario_sequence, &current_scenario_sequence_cache,
671+
[&model, &update_data, scenario_sequence, &current_scenario_sequence_cache, &components_to_store,
676672
do_update_cache_ = std::move(do_update_cache), &infos](Idx scenario_idx) {
677673
Timer const t_update_model(infos[scenario_idx], 1200, "Update model");
678674
current_scenario_sequence_cache = main_core::update::get_all_sequence_idx_map<ComponentType...>(
679-
model.state_, update_data, scenario_idx, do_update_cache_);
675+
model.state_, update_data, scenario_idx, components_to_store, do_update_cache_, false);
680676

681677
model.template update_components<cached_update_t>(update_data, scenario_idx, scenario_sequence());
682678
},

0 commit comments

Comments
 (0)