SpECTRE Documentation Coverage Report
Current view: top level - Parallel/PhaseControl - VisitAndReturn.hpp Hit Total Coverage
Commit: 990bc653376fc4a4068db06123ec02659d814816 Lines: 3 22 13.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 <optional>
       7             : #include <pup.h>
       8             : #include <string>
       9             : #include <utility>
      10             : #include <type_traits>
      11             : 
      12             : #include "Options/Options.hpp"
      13             : #include "Parallel/CharmPupable.hpp"
      14             : #include "Parallel/GlobalCache.hpp"
      15             : #include "Parallel/Main.hpp"
      16             : #include "Parallel/PhaseControl/PhaseChange.hpp"
      17             : #include "Utilities/ErrorHandling/Error.hpp"
      18             : #include "Utilities/Functional.hpp"
      19             : #include "Utilities/TMPL.hpp"
      20             : #include "Utilities/TaggedTuple.hpp"
      21             : 
      22             : /// \cond
      23             : namespace PhaseControl {
      24             : template <typename Metavariables, typename Metavariables::Phase TargetPhase,
      25             :           typename PhaseChangeRegistrars>
      26             : class VisitAndReturn;
      27             : 
      28             : namespace Registrars {
      29             : template <typename Metavariables, typename Metavariables::Phase TargetPhase>
      30             : struct VisitAndReturn {
      31             :   template <typename PhaseChangeRegistrars>
      32             :   using f = ::PhaseControl::VisitAndReturn<Metavariables, TargetPhase,
      33             :                                                  PhaseChangeRegistrars>;
      34             : };
      35             : }  // namespace Registrars
      36             : /// \endcond
      37             : 
      38             : namespace Tags {
      39             : /// Storage in the phase change decision tuple so that the Main chare can record
      40             : /// the phase to return to after a temporary phase.
      41             : ///
      42             : /// \note This tag is not intended to participate in any of the reduction
      43             : /// procedures, so will error if the combine method is called.
      44             : template <auto Phase>
      45           1 : struct ReturnPhase {
      46           0 :   using type = std::optional<decltype(Phase)>;
      47             : 
      48           0 :   struct combine_method {
      49           0 :     std::optional<decltype(Phase)> operator()(
      50             :         const std::optional<decltype(Phase)> /*first_phase*/,
      51             :         const std::optional<decltype(Phase)>& /*second_phase*/) noexcept {
      52             :       ERROR(
      53             :           "The return phase should only be altered by the phase change "
      54             :           "arbitration in the Main chare, so no reduction data should be "
      55             :           "provided.");
      56             :     }
      57             :   };
      58             : 
      59           0 :   using main_combine_method = combine_method;
      60             : };
      61             : 
      62             : /// Stores whether the phase in question has been requested.
      63             : ///
      64             : /// Combinations are performed via `funcl::Or`, as the phase in question should
      65             : /// be chosen if any component requests the jump.
      66             : template <auto Phase>
      67           1 : struct TemporaryPhaseRequested {
      68           0 :   using type = bool;
      69             : 
      70           0 :   using combine_method = funcl::Or<>;
      71           0 :   using main_combine_method = funcl::Or<>;
      72             : };
      73             : }  // namespace Tags
      74             : 
      75             : /*!
      76             :  * \brief Phase control object for temporarily visiting `TargetPhase`, until the
      77             :  * algorithm halts again, then returning to the original phase.
      78             :  *
      79             :  * The motivation for this type of procedure is e.g. load balancing,
      80             :  * checkpointing, and other maintenance tasks that should be performed
      81             :  * periodically during a lengthy evolution.
      82             :  * Once triggered, this will cause a change to `TargetPhase`, but store the
      83             :  * current phase to resume execution when the tasks in `TargetPhase` are
      84             :  * completed.
      85             :  *
      86             :  * Any parallel component can participate in the associated phase change
      87             :  * reduction data contribution, and if any component requests the temporary
      88             :  * phase, it will execute.
      89             :  *
      90             :  * To determine which specialization of this template is requested from the
      91             :  * input file, the `Metavariables` must define a `phase_name(Phase)` static
      92             :  * member function that returns a string for each phase that will be used in
      93             :  * `VisitAndReturn`s.
      94             :  *
      95             :  * \note  If multiple such methods are specified (with different
      96             :  * `TargetPhase`s), then the order of phase jumps depends on their order in the
      97             :  * list.
      98             :  * - If multiple `VisitAndReturn`s trigger simultaneously, then they will visit
      99             :  *   in sequence specified by the input file: first going to the first
     100             :  *   `TargetPhase` until that phase resolves, then immediately entering the
     101             :  *   second `TargetPhase` (without yet returning to the original phase), then
     102             :  *   finally returning to the original phase.
     103             :  * - If a `VisitAndReturn` is triggered in a phase that is already a
     104             :  *   `TargetPhase` of another `VisitAndReturn`, it will be executed, and
     105             :  *   following completion, control will return to the original phase from before
     106             :  *   the first `VisitAndReturn`.
     107             :  */
     108             : template <typename Metavariables, typename Metavariables::Phase TargetPhase,
     109             :           typename PhaseChangeRegistrars = tmpl::list<
     110             :               Registrars::VisitAndReturn<Metavariables, TargetPhase>>>
     111           1 : struct VisitAndReturn : public PhaseChange<PhaseChangeRegistrars> {
     112             :   /// \cond
     113             :   VisitAndReturn() = default;
     114             :   explicit VisitAndReturn(CkMigrateMessage* /*unused*/) noexcept {}
     115             :   using PUP::able::register_constructor;
     116             :   WRAPPED_PUPable_decl_template(VisitAndReturn);  // NOLINT
     117             :   /// \endcond
     118             : 
     119           0 :   static std::string name() noexcept {
     120             :     return "VisitAndReturn(" + Metavariables::phase_name(TargetPhase) +
     121             :            ")";
     122             :   }
     123           0 :   using options = tmpl::list<>;
     124           0 :   static constexpr Options::String help{
     125             :       "Temporarily jump to the phase given by `TargetPhase`, returning to the "
     126             :       "previously executing phase when complete."};
     127             : 
     128           0 :   using argument_tags = tmpl::list<>;
     129           0 :   using return_tags = tmpl::list<>;
     130             : 
     131           0 :   using phase_change_tags_and_combines =
     132             :       tmpl::list<Tags::ReturnPhase<TargetPhase>,
     133             :                  Tags::TemporaryPhaseRequested<TargetPhase>>;
     134             : 
     135             :   template <typename LocalMetavariables>
     136           0 :   using participating_components = typename LocalMetavariables::component_list;
     137             : 
     138             :   template <typename... DecisionTags>
     139           0 :   void initialize_phase_data_impl(
     140             :       const gsl::not_null<tuples::TaggedTuple<DecisionTags...>*>
     141             :           phase_change_decision_data) const noexcept {
     142             :     tuples::get<Tags::ReturnPhase<TargetPhase>>(*phase_change_decision_data) =
     143             :         std::nullopt;
     144             :     tuples::get<Tags::TemporaryPhaseRequested<TargetPhase>>(
     145             :         *phase_change_decision_data) = false;
     146             :   }
     147             : 
     148             :   template <typename ParallelComponent, typename ArrayIndex>
     149           0 :   void contribute_phase_data_impl(
     150             :       Parallel::GlobalCache<Metavariables>& cache,
     151             :       const ArrayIndex& array_index) const noexcept {
     152             :     if constexpr (std::is_same_v<typename ParallelComponent::chare_type,
     153             :                                  Parallel::Algorithms::Array>) {
     154             :       Parallel::contribute_to_phase_change_reduction<ParallelComponent>(
     155             :           tuples::TaggedTuple<Tags::TemporaryPhaseRequested<TargetPhase>>{true},
     156             :           cache, array_index);
     157             :     } else {
     158             :       Parallel::contribute_to_phase_change_reduction<ParallelComponent>(
     159             :           tuples::TaggedTuple<Tags::TemporaryPhaseRequested<TargetPhase>>{true},
     160             :           cache);
     161             :     }
     162             :   }
     163             : 
     164             :   template <typename... DecisionTags>
     165             :   typename std::optional<
     166             :       std::pair<typename Metavariables::Phase, ArbitrationStrategy>>
     167           0 :   arbitrate_phase_change_impl(
     168             :       const gsl::not_null<tuples::TaggedTuple<DecisionTags...>*>
     169             :           phase_change_decision_data,
     170             :       const typename Metavariables::Phase current_phase,
     171             :       const Parallel::GlobalCache<Metavariables>& /*cache*/) const noexcept {
     172             :     auto& return_phase = tuples::get<Tags::ReturnPhase<TargetPhase>>(
     173             :         *phase_change_decision_data);
     174             :     if (return_phase.has_value()) {
     175             :       const auto result = return_phase;
     176             :       return_phase.reset();
     177             :       return std::make_pair(result.value(),
     178             :                             ArbitrationStrategy::PermitAdditionalJumps);
     179             :     }
     180             :     auto& temporary_phase_requested =
     181             :         tuples::get<Tags::TemporaryPhaseRequested<TargetPhase>>(
     182             :             *phase_change_decision_data);
     183             :     if (temporary_phase_requested) {
     184             :       return_phase = current_phase;
     185             :       temporary_phase_requested = false;
     186             :       return std::make_pair(TargetPhase,
     187             :                             ArbitrationStrategy::RunPhaseImmediately);
     188             :     }
     189             :     return std::nullopt;
     190             :   }
     191             : 
     192           0 :   void pup(PUP::er& /*p*/) noexcept override {}
     193             : };
     194             : }  // namespace PhaseControl
     195             : 
     196             : /// \cond
     197             : template <typename Metavariables, typename Metavariables::Phase TargetPhase,
     198             :           typename PhaseChangeRegistrars>
     199             : PUP::able::PUP_ID PhaseControl::VisitAndReturn<
     200             :     Metavariables, TargetPhase, PhaseChangeRegistrars>::my_PUP_ID = 0;
     201             : /// \endcond

Generated by: LCOV version 1.14