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

Generated by: LCOV version 1.14