Skip to content

Commit ca58e8c

Browse files
authored
Merge pull request #1109 from PowerGridModel/feature/main-model-refactor-clean-templates-experiment
Cleanup main model: Clean up templates and variadics
2 parents e748c7b + a0c44fb commit ca58e8c

File tree

9 files changed

+370
-96
lines changed

9 files changed

+370
-96
lines changed

power_grid_model_c/power_grid_model/include/power_grid_model/job_adapter.hpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515

1616
namespace power_grid_model {
1717

18-
template <class MainModel, typename... ComponentType> class JobAdapter;
18+
template <class MainModel> class JobAdapter;
1919

20-
template <class MainModel, class... ComponentType>
21-
class JobAdapter<MainModel, ComponentList<ComponentType...>>
22-
: public JobInterface<JobAdapter<MainModel, ComponentList<ComponentType...>>> {
20+
template <class MainModel> class JobAdapter : public JobInterface<JobAdapter<MainModel>> {
2321
public:
22+
using ModelType = typename MainModel::ImplType;
23+
2424
JobAdapter(std::reference_wrapper<MainModel> model_reference,
2525
std::reference_wrapper<MainModelOptions const> options)
2626
: model_reference_{model_reference}, options_{options} {
@@ -89,12 +89,12 @@ class JobAdapter<MainModel, ComponentList<ComponentType...>>
8989
std::reference_wrapper<MainModel> model_reference_;
9090
std::reference_wrapper<MainModelOptions const> options_;
9191

92-
main_core::utils::ComponentFlags<ComponentType...> components_to_update_{};
93-
main_core::update::independence::UpdateIndependence<ComponentType...> update_independence_{};
94-
main_core::utils::ComponentFlags<ComponentType...> independence_flags_{};
95-
std::shared_ptr<main_core::utils::SequenceIdx<ComponentType...>> all_scenarios_sequence_;
92+
typename ModelType::ComponentFlags components_to_update_{};
93+
typename ModelType::UpdateIndependence update_independence_{};
94+
typename ModelType::ComponentFlags independence_flags_{};
95+
std::shared_ptr<typename ModelType::SequenceIdx> all_scenarios_sequence_;
9696
// current_scenario_sequence_cache_ is calculated per scenario, so it is excluded from the constructors.
97-
main_core::utils::SequenceIdx<ComponentType...> current_scenario_sequence_cache_{};
97+
typename ModelType::SequenceIdx current_scenario_sequence_cache_{};
9898

9999
Logger* log_{nullptr};
100100

@@ -125,17 +125,17 @@ class JobAdapter<MainModel, ComponentList<ComponentType...>>
125125
// cache component update order where possible.
126126
// the order for a cacheable (independent) component by definition is the same across all scenarios
127127
components_to_update_ = model_reference_.get().get_components_to_update(update_data);
128-
update_independence_ = main_core::update::independence::check_update_independence<ComponentType...>(
128+
update_independence_ = main_core::update::independence::check_update_independence<ModelType>(
129129
model_reference_.get().state(), update_data);
130130
std::ranges::transform(update_independence_, independence_flags_.begin(),
131131
[](auto const& comp) { return comp.is_independent(); });
132-
all_scenarios_sequence_ = std::make_shared<main_core::utils::SequenceIdx<ComponentType...>>(
133-
main_core::update::get_all_sequence_idx_map<ComponentType...>(
132+
all_scenarios_sequence_ =
133+
std::make_shared<typename ModelType::SequenceIdx>(main_core::update::get_all_sequence_idx_map<ModelType>(
134134
model_reference_.get().state(), update_data, 0, components_to_update_, update_independence_, false));
135135
}
136136

137137
void setup_impl(ConstDataset const& update_data, Idx scenario_idx) {
138-
current_scenario_sequence_cache_ = main_core::update::get_all_sequence_idx_map<ComponentType...>(
138+
current_scenario_sequence_cache_ = main_core::update::get_all_sequence_idx_map<ModelType>(
139139
model_reference_.get().state(), update_data, scenario_idx, components_to_update_, update_independence_,
140140
true);
141141
auto const current_scenario_sequence = get_current_scenario_sequence_view_();
@@ -149,8 +149,8 @@ class JobAdapter<MainModel, ComponentList<ComponentType...>>
149149
}
150150

151151
auto get_current_scenario_sequence_view_() const {
152-
return main_core::utils::run_functor_with_all_types_return_array<ComponentType...>([this]<typename CT>() {
153-
constexpr auto comp_idx = main_core::utils::index_of_component<CT, ComponentType...>;
152+
return ModelType::run_functor_with_all_component_types_return_array([this]<typename CT>() {
153+
constexpr auto comp_idx = ModelType::template index_of_component<CT>;
154154
if (std::get<comp_idx>(independence_flags_)) {
155155
return std::span<Idx2D const>{std::get<comp_idx>(*all_scenarios_sequence_)};
156156
}

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,26 @@
44

55
#pragma once
66

7-
#include "../all_components.hpp"
87
#include "../container.hpp"
8+
#include "state.hpp"
99

1010
#include <array>
1111
#include <vector>
12-
1312
namespace power_grid_model::main_core::utils {
1413

14+
namespace detail {
15+
16+
template <typename Tuple, class Functor, std::size_t... Indices>
17+
constexpr void run_functor_with_tuple_index_return_void(Functor&& functor, std::index_sequence<Indices...> /*unused*/) {
18+
(std::forward<Functor>(functor).template operator()<std::tuple_element_t<Indices, Tuple>>(), ...);
19+
}
20+
21+
} // namespace detail
22+
1523
constexpr Idx invalid_index{-1};
1624

25+
/////////////////// To remove ///////////////////
26+
1727
template <class... ComponentTypes> constexpr size_t n_types = sizeof...(ComponentTypes);
1828
template <class CompType, class... ComponentTypes>
1929
constexpr size_t index_of_component = container_impl::get_cls_pos_v<CompType, ComponentTypes...>;
@@ -28,5 +38,11 @@ template <class... Types, class Functor> constexpr void run_functor_with_all_typ
2838
template <class... Types, class Functor> constexpr auto run_functor_with_all_types_return_array(Functor functor) {
2939
return std::array { functor.template operator()<Types>()... };
3040
}
41+
/////////////////// To remove ///////////////////
42+
43+
template <typename Tuple, class Functor> constexpr void run_functor_with_tuple_return_void(Functor&& functor) {
44+
detail::run_functor_with_tuple_index_return_void<Tuple>(std::forward<Functor>(functor),
45+
std::make_index_sequence<std::tuple_size_v<Tuple>>{});
46+
}
3147

3248
} // namespace power_grid_model::main_core::utils
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// SPDX-FileCopyrightText: Contributors to the Power Grid Model project <[email protected]>
2+
//
3+
// SPDX-License-Identifier: MPL-2.0
4+
5+
#pragma once
6+
7+
#include "../all_components.hpp"
8+
#include "../container.hpp"
9+
#include "state.hpp"
10+
#include "update.hpp"
11+
12+
#include <array>
13+
#include <vector>
14+
namespace power_grid_model::main_core {
15+
16+
namespace detail {
17+
18+
template <typename Tuple> struct tuple_type_identities_to_tuple_types;
19+
20+
template <typename... Ts> struct tuple_type_identities_to_tuple_types<std::tuple<std::type_identity<Ts>...>> {
21+
using type = std::tuple<Ts...>;
22+
};
23+
24+
template <typename Tuple>
25+
using tuple_type_identities_to_tuple_types_t = typename tuple_type_identities_to_tuple_types<Tuple>::type;
26+
27+
template <typename... Types, typename... SelectTypes>
28+
constexpr auto filter_tuple_types(std::tuple<std::type_identity<Types>...> /*unused*/,
29+
std::tuple<std::type_identity<SelectTypes>...> /*unused*/) {
30+
constexpr auto sub_type_in_type = []<typename T>() { return (std::is_same_v<T, SelectTypes> || ...); };
31+
32+
return std::tuple_cat(std::conditional_t<sub_type_in_type.template operator()<Types>(),
33+
std::tuple<std::type_identity<Types>>, std::tuple<>>{}...);
34+
}
35+
36+
} // namespace detail
37+
38+
template <class T, class U> class MainModelType;
39+
40+
// TODO: discussion on checking dependent types can also be done here.
41+
template <class... ExtraRetrievableType, class... ComponentType>
42+
class MainModelType<ExtraRetrievableTypes<ExtraRetrievableType...>, ComponentList<ComponentType...>> {
43+
44+
public:
45+
using ComponentContainer = Container<ExtraRetrievableTypes<ExtraRetrievableType...>, ComponentType...>;
46+
using MainModelState = main_core::MainModelState<ComponentContainer>;
47+
using ComponentTypesTuple = std::tuple<ComponentType...>;
48+
49+
static constexpr size_t n_types = sizeof...(ComponentType);
50+
// TODO Should not have to go via container_impl.
51+
template <class CompType>
52+
static constexpr size_t index_of_component = container_impl::get_cls_pos_v<CompType, ComponentType...>;
53+
54+
private:
55+
static constexpr auto all_types_tuple_v_ =
56+
std::tuple<std::type_identity<ComponentType>..., std::type_identity<ExtraRetrievableType>...>{};
57+
// TODO: Would making a unique be necessary? We have Node mentioned as a ExtraRetrievableType and ComponentType so
58+
// summing up is possible but maybe not appropriate. Would it be better to handle them both separately? using
59+
60+
static constexpr auto topology_types_tuple_v_ =
61+
std::tuple<std::type_identity<Node>, std::type_identity<Branch>, std::type_identity<Branch3>,
62+
std::type_identity<Source>, std::type_identity<Shunt>, std::type_identity<GenericLoadGen>,
63+
std::type_identity<GenericVoltageSensor>, std::type_identity<GenericPowerSensor>,
64+
std::type_identity<GenericCurrentSensor>, std::type_identity<Regulator>>{};
65+
66+
static constexpr auto topology_connection_types_tuple_v_ =
67+
std::tuple<std::type_identity<Branch>, std::type_identity<Branch3>, std::type_identity<Source>>{};
68+
69+
public:
70+
using TopologyTypesTuple = detail::tuple_type_identities_to_tuple_types_t<decltype(detail::filter_tuple_types(
71+
topology_types_tuple_v_, all_types_tuple_v_))>;
72+
using TopologyConnectionTypesTuple =
73+
detail::tuple_type_identities_to_tuple_types_t<decltype(detail::filter_tuple_types(
74+
topology_connection_types_tuple_v_, all_types_tuple_v_))>;
75+
76+
// Update related types
77+
using OwnedUpdateDataset = std::tuple<std::vector<typename ComponentType::UpdateType>...>;
78+
using SequenceIdxView = std::array<std::span<Idx2D const>, n_types>;
79+
using UpdateIndependence = std::array<main_core::update::independence::UpdateCompProperties, n_types>;
80+
using SequenceIdx = std::array<std::vector<Idx2D>, n_types>;
81+
using SequenceIdxRefWrappers = std::array<std::reference_wrapper<std::vector<Idx2D> const>, n_types>;
82+
using ComponentFlags = std::array<bool, n_types>;
83+
84+
// Clean these 2. They are unused
85+
static constexpr auto branch_param_in_seq_map =
86+
std::array{index_of_component<Line>, index_of_component<Link>, index_of_component<Transformer>};
87+
static constexpr auto shunt_param_in_seq_map = std::array{index_of_component<Shunt>};
88+
89+
template <class Functor> static constexpr void run_functor_with_all_component_types_return_void(Functor&& functor) {
90+
(std::forward<Functor>(functor).template operator()<ComponentType>(), ...);
91+
}
92+
template <class Functor>
93+
static constexpr auto run_functor_with_all_component_types_return_array(Functor&& functor) {
94+
return std::array { std::forward<Functor>(functor).template operator()<ComponentType>()... };
95+
}
96+
};
97+
98+
} // namespace power_grid_model::main_core

power_grid_model_c/power_grid_model/include/power_grid_model/main_core/topology.hpp

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -207,31 +207,29 @@ constexpr void register_connections_components(ComponentContainer const& compone
207207

208208
} // namespace detail
209209

210-
template <typename ComponentContainer>
211-
requires common::component_container_c<ComponentContainer, Branch, Branch3, Source, Shunt, GenericLoadGen,
212-
GenericVoltageSensor, GenericPowerSensor, GenericCurrentSensor, Regulator>
213-
ComponentTopology construct_topology(ComponentContainer const& components) {
210+
template <typename ModelType>
211+
requires common::component_container_c<typename ModelType::ComponentContainer, Branch, Branch3, Source, Shunt,
212+
GenericLoadGen, GenericVoltageSensor, GenericPowerSensor,
213+
GenericCurrentSensor, Regulator>
214+
ComponentTopology construct_topology(typename ModelType::ComponentContainer const& components) {
214215
ComponentTopology comp_topo;
215-
detail::register_topology_components<Node>(components, comp_topo);
216-
detail::register_topology_components<Branch>(components, comp_topo);
217-
detail::register_topology_components<Branch3>(components, comp_topo);
218-
detail::register_topology_components<Source>(components, comp_topo);
219-
detail::register_topology_components<Shunt>(components, comp_topo);
220-
detail::register_topology_components<GenericLoadGen>(components, comp_topo);
221-
detail::register_topology_components<GenericVoltageSensor>(components, comp_topo);
222-
detail::register_topology_components<GenericPowerSensor>(components, comp_topo);
223-
detail::register_topology_components<GenericCurrentSensor>(components, comp_topo);
224-
detail::register_topology_components<Regulator>(components, comp_topo);
216+
using TopologyTypesTuple = typename ModelType::TopologyTypesTuple;
217+
main_core::utils::run_functor_with_tuple_return_void<TopologyTypesTuple>(
218+
[&components, &comp_topo]<typename CompType>() {
219+
detail::register_topology_components<CompType>(components, comp_topo);
220+
});
225221
return comp_topo;
226222
}
227223

228-
template <typename ComponentContainer>
229-
requires common::component_container_c<ComponentContainer, Branch, Branch3, Source>
230-
ComponentConnections construct_components_connections(ComponentContainer const& components) {
224+
template <typename ModelType>
225+
requires common::component_container_c<typename ModelType::ComponentContainer, Branch, Branch3, Source>
226+
ComponentConnections construct_components_connections(typename ModelType::ComponentContainer const& components) {
231227
ComponentConnections comp_conn;
232-
detail::register_connections_components<Branch>(components, comp_conn);
233-
detail::register_connections_components<Branch3>(components, comp_conn);
234-
detail::register_connections_components<Source>(components, comp_conn);
228+
using TopologyConnectionTypesTuple = typename ModelType::TopologyConnectionTypesTuple;
229+
main_core::utils::run_functor_with_tuple_return_void<TopologyConnectionTypesTuple>(
230+
[&components, &comp_conn]<typename CompType>() {
231+
detail::register_connections_components<CompType>(components, comp_conn);
232+
});
235233
return comp_conn;
236234
}
237235

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

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ template <typename T> bool check_id_na(T const& obj) {
4545
} // namespace detail
4646

4747
namespace independence {
48+
4849
struct UpdateCompProperties {
4950
bool has_any_elements{false}; // whether the component has any elements in the update data
5051
bool ids_all_na{false}; // whether all ids are all NA
@@ -127,9 +128,6 @@ UpdateCompProperties check_component_independence(ConstDataset const& update_dat
127128
return properties;
128129
}
129130

130-
template <class... ComponentTypes>
131-
using UpdateIndependence = std::array<UpdateCompProperties, utils::n_types<ComponentTypes...>>;
132-
133131
inline void validate_update_data_independence(UpdateCompProperties const& comp, std::string const& comp_name) {
134132
if (comp.is_empty_component()) {
135133
return; // empty dataset is still supported
@@ -150,14 +148,13 @@ inline void validate_update_data_independence(UpdateCompProperties const& comp,
150148
}
151149
}
152150

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);
160-
});
151+
template <typename ModelType>
152+
typename ModelType::UpdateIndependence check_update_independence(typename ModelType::MainModelState const& state,
153+
ConstDataset const& update_data) {
154+
return ModelType::run_functor_with_all_component_types_return_array([&state, &update_data]<typename CompType>() {
155+
auto const n_component = state.components.template size<CompType>();
156+
return check_component_independence<CompType>(update_data, n_component);
157+
});
161158
}
162159

163160
} // namespace independence
@@ -214,22 +211,21 @@ std::vector<Idx2D> get_component_sequence(MainModelState<ComponentContainer> con
214211
}
215212
} // namespace detail
216213

217-
template <class... ComponentTypes, class ComponentContainer>
218-
utils::SequenceIdx<ComponentTypes...>
219-
get_all_sequence_idx_map(MainModelState<ComponentContainer> const& state, ConstDataset const& update_data,
220-
Idx scenario_idx, utils::ComponentFlags<ComponentTypes...> const& components_to_store,
221-
independence::UpdateIndependence<ComponentTypes...> const& independence, bool cached) {
222-
return utils::run_functor_with_all_types_return_array<ComponentTypes...>(
214+
template <class ModelType>
215+
typename ModelType::SequenceIdx
216+
get_all_sequence_idx_map(typename ModelType::MainModelState const& state, ConstDataset const& update_data,
217+
Idx scenario_idx, typename ModelType::ComponentFlags const& components_to_store,
218+
typename ModelType::UpdateIndependence const& independence, bool cached) {
219+
return ModelType::run_functor_with_all_component_types_return_array(
223220
[&state, &update_data, scenario_idx, &components_to_store, &independence, cached]<typename CompType>() {
224-
auto const component_properties =
225-
std::get<utils::index_of_component<CompType, ComponentTypes...>>(independence);
221+
auto const component_properties = std::get<ModelType::template index_of_component<CompType>>(independence);
226222
// The sequence for the independent components is cached (true). For the remaining components, the sequence
227223
// cannot be cached (false), so the independence flags are inverted to not return an empty sequence when
228224
// this is the case.
229225

230226
if (bool const component_independence = cached != component_properties.is_independent();
231227
!component_independence ||
232-
!std::get<utils::index_of_component<CompType, ComponentTypes...>>(components_to_store)) {
228+
!std::get<ModelType::template index_of_component<CompType>>(components_to_store)) {
233229
return std::vector<Idx2D>{};
234230
}
235231
independence::validate_update_data_independence(component_properties, CompType::name);

power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class MainModel {
8181
BatchParameter calculate(Options const& options, MutableDataset const& result_data,
8282
ConstDataset const& update_data) {
8383
info_.clear();
84-
JobAdapter<Impl, AllComponents> adapter{std::ref(impl()), std::ref(options)};
84+
JobAdapter<Impl> adapter{std::ref(impl()), std::ref(options)};
8585
return JobDispatch::batch_calculation(adapter, result_data, update_data, options.threading, info_);
8686
}
8787

0 commit comments

Comments
 (0)