PhaseChange.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <memory>
7 #include <optional>
8 #include <type_traits>
9 #include <utility>
10 #include <vector>
11 
13 #include "Parallel/GlobalCache.hpp"
14 #include "ParallelAlgorithms/EventsAndTriggers/Trigger.hpp"
15 #include "Utilities/FakeVirtual.hpp"
16 #include "Utilities/Gsl.hpp"
17 #include "Utilities/Registration.hpp"
18 #include "Utilities/TMPL.hpp"
19 #include "Utilities/TaggedTuple.hpp"
20 
21 
22 /// Contains utilities for determining control-flow among phases
23 namespace PhaseControl {
24 /// The possible options for instructing the Main chare in deciding the next
25 /// phase to jump to.
26 ///
27 /// An object of this enum type is packaged with a requested phase in the
28 /// `PhaseChange::arbitrate_phase_change` function.
30  /// Jump to the requested phase immediately, before considering other
31  /// requested phases.
32  ///
33  /// This will ensure that the requested phase is always run, where
34  /// alternative methods could have 'double-jumps' where the Main chare
35  /// replaces a requested phase immediately without actually entering the
36  /// phase.
38  /// After the requested phase is considered, continue considering other
39  /// requests, potentially replacing this request.
40  ///
41  /// This will permit reprocessing the phase-jumps to help with cases where
42  /// multiple phases are simultaneously requested.
43  /// The `PermitAdditionalJumps` permits 'double-jumps' where a requested phase
44  /// is immediately replaced by another phase to jump to.
46 };
47 } // namespace PhaseControl
48 
49 /*!
50  * \brief `PhaseChange` objects determine the storage types and logic for
51  * moving between phases based on runtime data.
52  *
53  * The phase control flow must have the cooperation of each parallel component,
54  * but make phase decisions centrally so that at any point, all components are
55  * in the same phase. The operations needed by the parallel components and by
56  * the Main chare, are:
57  *
58  * 1. Parallel components must select and/or compute the runtime data necessary
59  * for choosing the next phase, then contribute it to a global reduction to
60  * the Main component.
61  * The components must then halt at a globally-valid state for the phase
62  * change.
63  * The requirements for the state will vary depending on the phase choices,
64  * so triggers must be selected appropriately for the `PhaseChange` object.
65  * For instance, selecting a common slab will usually represent a globally
66  * well-behaved state for a `DgElementArray`.
67  * 2. On the Main chare, the `PhaseChange` objects must use the collected
68  * reduction data, or other persistent data stored in
69  * `phase_change_decision_data` to decide on a phase to request and an
70  * `PhaseControl::ArbitrationStrategy` to determine how to resolve multiple
71  * simultaneous requests.
72  * Additionally, the `PhaseChange` objects must specify initialization
73  * functions to set the starting state of the tags in
74  * `phase_change_decision_data` for which they are responsible.
75  *
76  * In addition to the `options` type alias and `static constexpr Options::String
77  * help` variable needed to be option-creatable, a derived class of
78  * `PhaseChange` must specify the type aliases:
79  * - `argument_tags`: A `tmpl::list` of tags from the
80  * \ref DataBoxGroup "DataBox" to be passed to `contribute_phase_data_impl` as
81  * const references.
82  * - `return_tags`: A `tmpl::list` of mutable tags from the
83  * \ref DataBoxGroup "DataBox" to be passed to `contribute_phase_data_impl` as
84  * `gsl::not_null` pointers. This should be used only for tags that may be
85  * altered during the `contribute_phase_data_impl` function.
86  * - `phase_change_tags_and_combines_list`: A `tmpl::list` of tags for
87  * populating the `phase_change_decision_data` in the Main chare. Each tag in
88  * this list must also define a `combine_method` and a `main_combine_method`
89  * for performing the aggregation during reduction.
90  * - `participating_components` (templated on `Metavariables`): A `tmpl::list`
91  * of components that contribute data during this reduction. This can be used
92  * to screen out components that will not have the necessary information to
93  * contribute to the reduction. If all components should participate, this
94  * type alias can be set to simply `typename Metavariables::component_list`.
95  *
96  * And member functions with signatures:
97  *
98  * ```
99  * template <typename... DecisionTags>
100  * void initialize_phase_data_impl(
101  * const gsl::not_null<tuples::TaggedTuple<DecisionTags...>*>
102  * phase_change_decision_data) const noexcept;
103  * ```
104  * - Must set all tags in `phase_change_tags_and_combines_list` to useful
105  * initial states in the `phase_change_decision_data`.
106  *
107  * ```
108  * template <typename ParallelComponent, typename ArrayIndex>
109  * void contribute_phase_data_impl(
110  * [DataBox return tags...], [DataBox argument tags...],
111  * Parallel::GlobalCache<Metavariables>& cache,
112  * const ArrayIndex& array_index) const noexcept;
113  * ```
114  * - Should send any data relevant for the associated phase change decision made
115  * in `arbitrate_phase_change_impl` to the Main chare via function
116  * `Parallel::contribute_to_phase_change_reduction`.
117  *
118  * ```
119  * template <typename... DecisionTags, typename Metavariables>
120  * typename std::optional<
121  * std::pair<typename Metavariables::Phase, ArbitrationStrategy>>
122  * arbitrate_phase_change_impl(
123  * const gsl::not_null<tuples::TaggedTuple<DecisionTags...>*>
124  * phase_change_decision_data,
125  * const typename Metavariables::Phase current_phase,
126  * const Parallel::GlobalCache<Metavariables>& cache) const noexcept;
127  * ```
128  * - Should examine the collected data in `phase_change_decision_data` and
129  * optionally return a `std::pair` with the desired `Metavariables::Phase` and
130  * an `PhaseControl::ArbitrationStrategy` indicating a method for arbitrating
131  * multiple simultaneous requests. Alternatively, it may return `std::nullopt`
132  * to abstain from the phase decision.
133  * The `arbitrate_phase_change_impl` may (and often will) mutate the
134  * `phase_change_decision_data`. For instance, it may be desirable to 'reset'
135  * the data to allow for future jumps associated with the same `PhaseChange`,
136  * or the `PhaseChange` will describe multiple changes in sequence, and the
137  * state of that sequential process can be recorded in
138  * `phase_change_decision_data`.
139  */
140 template <typename PhaseChangeRegistrars>
141 struct PhaseChange : public PUP::able {
142  protected:
143  /// \cond
144  PhaseChange() = default;
145  PhaseChange(const PhaseChange&) = default;
146  PhaseChange(PhaseChange&&) = default;
147  PhaseChange& operator=(const PhaseChange&) = default;
148  PhaseChange& operator=(PhaseChange&&) = default;
149  /// \endcond
150 
151  public:
152  PhaseChange(CkMigrateMessage* msg) noexcept : PUP::able(msg) {};
153 
154  ~PhaseChange() override = default;
155 
156  WRAPPED_PUPable_abstract(PhaseChange); // NOLINT
157 
158  using creatable_classes = Registration::registrants<PhaseChangeRegistrars>;
159 
160  /// Send data from all `participating_components` to the Main chare for
161  /// determining the next phase.
162  template <typename ParallelComponent, typename DbTags, typename Metavariables,
163  typename ArrayIndex>
164  void contribute_phase_data(const gsl::not_null<db::DataBox<DbTags>*> box,
166  const ArrayIndex& array_index) const noexcept {
168  void, creatable_classes>(this, [&box, &cache, &array_index](
169  const auto* const
170  phase_change) noexcept {
171  using phase_change_t = typename std::decay_t<decltype(*phase_change)>;
172  if constexpr (tmpl::list_contains_v<
173  typename phase_change_t::
174  template participating_components<Metavariables>,
175  ParallelComponent>) {
176  db::mutate_apply<typename phase_change_t::return_tags,
177  typename phase_change_t::argument_tags>(
178  [&phase_change, &cache, &array_index](auto&&... args) noexcept {
179  phase_change
180  ->template contribute_phase_data_impl<ParallelComponent>(
181  args..., cache, array_index);
182  },
183  box);
184  }
185  });
186  }
187 
188  /// Determine a phase request and `PhaseControl::ArbitrationStrategy` based on
189  /// aggregated `phase_change_decision_data` on the Main Chare.
190  template <typename... DecisionTags, typename Metavariables>
191  std::optional<std::pair<typename Metavariables::Phase,
195  phase_change_decision_data,
196  const typename Metavariables::Phase current_phase,
197  const Parallel::GlobalCache<Metavariables>& cache) const noexcept {
198  return call_with_dynamic_type<
199  std::optional<std::pair<typename Metavariables::Phase,
201  creatable_classes>(
202  this, [&current_phase, &phase_change_decision_data,
203  &cache](const auto* const phase_change) noexcept {
204  return phase_change->arbitrate_phase_change_impl(
205  phase_change_decision_data, current_phase, cache);
206  });
207  }
208 
209  /// Initialize the `phase_change_decision_data` on the main chare to starting
210  /// values.
211  template <typename... Tags>
214  phase_change_decision_data) const noexcept {
215  return call_with_dynamic_type<void, creatable_classes>(
216  this, [&phase_change_decision_data](
217  const auto* const phase_change) noexcept {
218  return phase_change->initialize_phase_data_impl(
219  phase_change_decision_data);
220  });
221  }
222 };
PhaseControl
Contains utilities for determining control-flow among phases.
Definition: ExecutePhaseChange.hpp:17
utility
Parallel::GlobalCache
Definition: ElementReceiveInterpPoints.hpp:15
std::pair
GlobalCache.hpp
vector
call_with_dynamic_type
Result call_with_dynamic_type(Base *const obj, Callable &&f) noexcept
Call a functor with the derived type of a base class pointer.
Definition: FakeVirtual.hpp:103
PhaseControl::ArbitrationStrategy
ArbitrationStrategy
The possible options for instructing the Main chare in deciding the next phase to jump to.
Definition: PhaseChange.hpp:29
DataBox.hpp
tuples::TaggedTuple
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:271
memory
std::decay_t
ActionTesting::cache
Parallel::GlobalCache< Metavariables > & cache(MockRuntimeSystem< Metavariables > &runner, const ArrayIndex &array_index) noexcept
Returns the GlobalCache of Component with index array_index.
Definition: MockRuntimeSystemFreeFunctions.hpp:382
PhaseChange
PhaseChange objects determine the storage types and logic for moving between phases based on runtime ...
Definition: PhaseChange.hpp:141
PhaseControl::PermitAdditionalJumps
@ PermitAdditionalJumps
After the requested phase is considered, continue considering other requests, potentially replacing t...
Definition: PhaseChange.hpp:45
Gsl.hpp
db::mutate_apply
constexpr decltype(auto) mutate_apply(F &&f, const gsl::not_null< DataBox< BoxTags > * > box, Args &&... args) noexcept
Apply the invokable f mutating items MutateTags and taking as additional arguments ArgumentTags and a...
Definition: DataBox.hpp:1257
PhaseChange::contribute_phase_data
void contribute_phase_data(const gsl::not_null< db::DataBox< DbTags > * > box, Parallel::GlobalCache< Metavariables > &cache, const ArrayIndex &array_index) const noexcept
Send data from all participating_components to the Main chare for determining the next phase.
Definition: PhaseChange.hpp:164
PhaseChange::arbitrate_phase_change
std::optional< std::pair< typename Metavariables::Phase, PhaseControl::ArbitrationStrategy > > arbitrate_phase_change(const gsl::not_null< tuples::TaggedTuple< DecisionTags... > * > phase_change_decision_data, const typename Metavariables::Phase current_phase, const Parallel::GlobalCache< Metavariables > &cache) const noexcept
Determine a phase request and PhaseControl::ArbitrationStrategy based on aggregated phase_change_deci...
Definition: PhaseChange.hpp:193
optional
PhaseChange::initialize_phase_data
void initialize_phase_data(const gsl::not_null< tuples::TaggedTuple< Tags... > * > phase_change_decision_data) const noexcept
Initialize the phase_change_decision_data on the main chare to starting values.
Definition: PhaseChange.hpp:212
PhaseControl::RunPhaseImmediately
@ RunPhaseImmediately
Jump to the requested phase immediately, before considering other requested phases.
Definition: PhaseChange.hpp:37
Registration::registrants
tmpl::transform< tmpl::remove_duplicates< RegistrarList >, detail::registrant< tmpl::pin< tmpl::remove_duplicates< RegistrarList > >, tmpl::_1 > > registrants
Transform a list of registrars into the list of associated registrants. This is usually used to defin...
Definition: Registration.hpp:65
type_traits
TMPL.hpp
gsl::not_null
Require a pointer to not be a nullptr
Definition: ReadSpecPiecewisePolynomial.hpp:13