SetupDataBox.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <tuple>
8 #include <type_traits>
9 
11 #include "Parallel/GlobalCache.hpp"
12 #include "ParallelAlgorithms/Initialization/MergeIntoDataBox.hpp"
13 #include "Utilities/TMPL.hpp"
14 #include "Utilities/TaggedTuple.hpp"
15 
16 namespace Actions {
17 /// \cond
18 struct SetupDataBox;
19 /// \endcond
20 
21 namespace detail {
22 template <typename Action, typename enable = std::void_t<>>
23 struct optional_simple_tags {
24  using type = tmpl::list<>;
25 };
26 
27 template <typename Action>
28 struct optional_simple_tags<Action, std::void_t<typename Action::simple_tags>> {
29  using type = typename Action::simple_tags;
30 };
31 
32 template <typename Action, typename enable = std::void_t<>>
33 struct optional_compute_tags {
34  using type = tmpl::list<>;
35 };
36 
37 template <typename Action>
38 struct optional_compute_tags<Action,
39  std::void_t<typename Action::compute_tags>> {
40  using type = typename Action::compute_tags;
41 };
42 
43 template <typename ActionList>
44 struct get_action_list_simple_tags {
45  using type = tmpl::flatten<tmpl::transform<typename ActionList::action_list,
46  optional_simple_tags<tmpl::_1>>>;
47 };
48 
49 template <typename ActionList>
50 struct get_action_list_compute_tags {
51  using type = tmpl::flatten<tmpl::transform<typename ActionList::action_list,
52  optional_compute_tags<tmpl::_1>>>;
53 };
54 
55 template <typename Pdal>
56 using get_pdal_simple_tags =
57  tmpl::flatten<tmpl::transform<Pdal, get_action_list_simple_tags<tmpl::_1>>>;
58 
59 template <typename Pdal>
60 using get_pdal_compute_tags = tmpl::flatten<
61  tmpl::transform<Pdal, get_action_list_compute_tags<tmpl::_1>>>;
62 
63 template <typename DbTags, typename... SimpleTags, typename... ComputeTags>
64 auto merge_into_databox_helper(db::DataBox<DbTags>&& box,
65  tmpl::list<SimpleTags...> /*meta*/,
66  tmpl::list<ComputeTags...> /*meta*/) noexcept {
67  return db::create_from<db::RemoveTags<>, db::AddSimpleTags<SimpleTags...>,
68  db::AddComputeTags<ComputeTags...>>(
69  std::move(box), typename SimpleTags::type{}...);
70 }
71 } // namespace detail
72 
73 /*!
74  * \brief Add into the \ref DataBoxGroup "DataBox" default constructed items for
75  * the collection of tags requested by any of the actions in the phase-dependent
76  * action list.
77  *
78  * \details This action adds all of the simple tags given in the `simple_tags`
79  * type lists in each of the other actions in the current component's full
80  * phase-dependent action list, and all of the compute tags given in the
81  * `compute_tags` type lists. If an action does not give either of the type
82  * lists, it is treated as an empty type list.
83  *
84  * To prevent the proliferation of many \ref DataBoxGroup "DataBox" types, which
85  * can drastically slow compile times, it is preferable to use only this action
86  * to add tags to the \ref DataBoxGroup "DataBox", and place this action at the
87  * start of the `Initialization` phase action list. The rest of the
88  * initialization actions should specify `simple_tags` and `compute_tags`, and
89  * assign initial values to those tags, but not add those tags into the \ref
90  * DataBoxGroup "DataBox".
91  *
92  * An example initialization action:
93  * \snippet Test_SetupDataBox.cpp initialization_action
94  *
95  * \note This action operates on the assumption that the phase dependent action
96  * list of the `ParallelComponent` and the `ActionList` do not depend on the
97  * \ref DataBoxGroup "DataBox" type in the Algorithm. This assumption holds
98  * for all current utilities, but if it must be relaxed, revisions to
99  * `SetupDataBox` may be required to avoid a cyclic dependency of the \ref
100  * DataBoxGroup "DataBox" types.
101  */
102 struct SetupDataBox {
103  template <typename DbTags, typename... InboxTags, typename Metavariables,
104  typename ArrayIndex, typename ActionList,
105  typename ParallelComponent>
106  static auto apply(db::DataBox<DbTags>& box,
107  const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
108  const Parallel::GlobalCache<Metavariables>& /*cache*/,
109  const ArrayIndex& /*array_index*/,
110  const ActionList /*meta*/,
111  const ParallelComponent* const /*meta*/) noexcept {
112  using action_list_simple_tags =
113  tmpl::remove_duplicates<detail::get_pdal_simple_tags<
114  typename ParallelComponent::phase_dependent_action_list>>;
115  using action_list_compute_tags =
116  tmpl::remove_duplicates<detail::get_pdal_compute_tags<
117  typename ParallelComponent::phase_dependent_action_list>>;
118  using all_new_tags =
119  tmpl::append<action_list_simple_tags, action_list_compute_tags>;
120  // We just check the first tag in the list to prevent repeat-applications
121  // of the action. Any cases where a tag is mistakenly added to the DataBox
122  // before `SetupDataBox` is called (which shouldn't happen if it's used as
123  // suggested) will result in a multiple inheritance error.
124  if constexpr (tmpl::size<all_new_tags>::value != 0_st) {
125  if constexpr (not tmpl::list_contains_v<DbTags,
126  tmpl::front<all_new_tags>>) {
127  return std::make_tuple(detail::merge_into_databox_helper(
128  std::move(box), action_list_simple_tags{},
129  action_list_compute_tags{}));
130  } else {
131  ERROR(
132  "Trying to call SetupDataBox after it has already been called "
133  "previously. SetupDataBox may only be called once.");
134  return std::make_tuple(std::move(box));
135  }
136  } else {
137  return std::make_tuple(std::move(box));
138  }
139 
140  }
141 };
142 } // namespace Actions
Actions::SetupDataBox
Add into the DataBox default constructed items for the collection of tags requested by any of the act...
Definition: SetupDataBox.hpp:102
Parallel::GlobalCache
Definition: ElementReceiveInterpPoints.hpp:15
GlobalCache.hpp
db::AddComputeTags
tmpl::flatten< tmpl::list< Tags... > > AddComputeTags
List of Compute Item Tags to add to the DataBox.
Definition: DataBox.hpp:863
tuple
ERROR
#define ERROR(m)
prints an error message to the standard error stream and aborts the program.
Definition: Error.hpp:37
DataBox.hpp
cstddef
tuples::TaggedTuple
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:271
db::AddSimpleTags
tmpl::flatten< tmpl::list< Tags... > > AddSimpleTags
List of Tags to add to the DataBox.
Definition: DataBox.hpp:856
type_traits
TMPL.hpp