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() override = default;
153 
154  WRAPPED_PUPable_abstract(PhaseChange); // NOLINT
155 
156  using creatable_classes = Registration::registrants<PhaseChangeRegistrars>;
157 
158  /// Send data from all `participating_components` to the Main chare for
159  /// determining the next phase.
160  template <typename ParallelComponent, typename DbTags, typename Metavariables,
161  typename ArrayIndex>
162  void contribute_phase_data(const gsl::not_null<db::DataBox<DbTags>*> box,
164  const ArrayIndex& array_index) const noexcept {
166  void, creatable_classes>(this, [&box, &cache, &array_index](
167  const auto* const
168  phase_change) noexcept {
169  using phase_change_t = typename std::decay_t<decltype(*phase_change)>;
170  if constexpr (tmpl::list_contains_v<
171  typename phase_change_t::
172  template participating_components<Metavariables>,
173  ParallelComponent>) {
174  db::mutate_apply<typename phase_change_t::return_tags,
175  typename phase_change_t::argument_tags>(
176  [&phase_change, &cache, &array_index](auto&&... args) noexcept {
177  phase_change
178  ->template contribute_phase_data_impl<ParallelComponent>(
179  args..., cache, array_index);
180  },
181  box);
182  }
183  });
184  }
185 
186  /// Determine a phase request and `PhaseControl::ArbitrationStrategy` based on
187  /// aggregated `phase_change_decision_data` on the Main Chare.
188  template <typename... DecisionTags, typename Metavariables>
189  std::optional<std::pair<typename Metavariables::Phase,
193  phase_change_decision_data,
194  const typename Metavariables::Phase current_phase,
195  const Parallel::GlobalCache<Metavariables>& cache) const noexcept {
196  return call_with_dynamic_type<
197  std::optional<std::pair<typename Metavariables::Phase,
199  creatable_classes>(
200  this, [&current_phase, &phase_change_decision_data,
201  &cache](const auto* const phase_change) noexcept {
202  return phase_change->arbitrate_phase_change_impl(
203  phase_change_decision_data, current_phase, cache);
204  });
205  }
206 
207  /// Initialize the `phase_change_decision_data` on the main chare to starting
208  /// values.
209  template <typename... Tags>
212  phase_change_decision_data) const noexcept {
213  return call_with_dynamic_type<void, creatable_classes>(
214  this, [&phase_change_decision_data](
215  const auto* const phase_change) noexcept {
216  return phase_change->initialize_phase_data_impl(
217  phase_change_decision_data);
218  });
219  }
220 };
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:1193
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:162
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:191
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:210
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: ReadSpecThirdOrderPiecewisePolynomial.hpp:13