SpECTRE Documentation Coverage Report
Current view: top level - Parallel/PhaseControl - PhaseChange.hpp Hit Total Coverage
Commit: 990bc653376fc4a4068db06123ec02659d814816 Lines: 5 9 55.6 %
Date: 2021-05-16 17:17:32
Legend: Lines: hit not hit

          Line data    Source code
       1           0 : // 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             : 
      12             : #include "DataStructures/DataBox/DataBox.hpp"
      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.
      29           1 : enum ArbitrationStrategy {
      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.
      37             :   RunPhaseImmediately,
      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.
      45             :   PermitAdditionalJumps
      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           1 : 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           0 :   ~PhaseChange() override = default;
     153             : 
     154           0 :   WRAPPED_PUPable_abstract(PhaseChange);  // NOLINT
     155             : 
     156           0 :   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           1 :   void contribute_phase_data(const gsl::not_null<db::DataBox<DbTags>*> box,
     163             :                              Parallel::GlobalCache<Metavariables>& cache,
     164             :                              const ArrayIndex& array_index) const noexcept {
     165             :     call_with_dynamic_type<
     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,
     190             :                           PhaseControl::ArbitrationStrategy>>
     191           1 :   arbitrate_phase_change(
     192             :       const gsl::not_null<tuples::TaggedTuple<DecisionTags...>*>
     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,
     198             :                                 PhaseControl::ArbitrationStrategy>>,
     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>
     210           1 :   void initialize_phase_data(
     211             :       const gsl::not_null<tuples::TaggedTuple<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             : };

Generated by: LCOV version 1.14