SpECTRE Documentation Coverage Report
Current view: top level - Parallel/PhaseControl - VisitAndReturn.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 13.6 % 22 3
Test Date: 2026-10-22 17:29:42
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 <type_traits>
      10              : #include <utility>
      11              : 
      12              : #include "DataStructures/TaggedTuple.hpp"
      13              : #include "Options/String.hpp"
      14              : #include "Parallel/GlobalCache.hpp"
      15              : #include "Parallel/Phase.hpp"
      16              : #include "Parallel/PhaseControl/ContributeToPhaseChangeReduction.hpp"
      17              : #include "Parallel/PhaseControl/PhaseChange.hpp"
      18              : #include "Utilities/ErrorHandling/Error.hpp"
      19              : #include "Utilities/Functional.hpp"
      20              : #include "Utilities/MakeString.hpp"
      21              : #include "Utilities/Serialization/CharmPupable.hpp"
      22              : #include "Utilities/TMPL.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 2.0-1