SpECTRE Documentation Coverage Report
Current view: top level - Parallel/ArrayCollection - DgElementArrayMember.hpp Hit Total Coverage
Commit: 1f2210958b4f38fdc0400907ee7c6d5af5111418 Lines: 13 31 41.9 %
Date: 2025-12-05 05:03:31
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 <charm++.h>
       7             : #include <cstddef>
       8             : #include <exception>
       9             : #include <pup.h>
      10             : #include <string>
      11             : #include <type_traits>
      12             : #include <utility>
      13             : 
      14             : #include "DataStructures/DataBox/DataBox.hpp"
      15             : #include "DataStructures/DataBox/MetavariablesTag.hpp"
      16             : #include "DataStructures/DataBox/PrefixHelpers.hpp"
      17             : #include "Domain/Structure/ElementId.hpp"
      18             : #include "Parallel/AlgorithmExecution.hpp"
      19             : #include "Parallel/AlgorithmMetafunctions.hpp"
      20             : #include "Parallel/ArrayCollection/DgElementArrayMemberBase.hpp"
      21             : #include "Parallel/ArrayCollection/SetTerminateOnElement.hpp"
      22             : #include "Parallel/GlobalCache.hpp"
      23             : #include "Parallel/Info.hpp"
      24             : #include "Parallel/Invoke.hpp"
      25             : #include "Parallel/Local.hpp"
      26             : #include "Parallel/ParallelComponentHelpers.hpp"
      27             : #include "Parallel/Phase.hpp"
      28             : #include "Parallel/Tags/ArrayIndex.hpp"
      29             : #include "ParallelAlgorithms/Initialization/MutateAssign.hpp"
      30             : #include "Utilities/ErrorHandling/Assert.hpp"
      31             : #include "Utilities/ErrorHandling/Error.hpp"
      32             : #include "Utilities/Gsl.hpp"
      33             : #include "Utilities/MakeString.hpp"
      34             : #include "Utilities/PrettyType.hpp"
      35             : #include "Utilities/Serialization/CharmPupable.hpp"
      36             : #include "Utilities/System/Abort.hpp"
      37             : #include "Utilities/TMPL.hpp"
      38             : #include "Utilities/TaggedTuple.hpp"
      39             : 
      40             : /// \cond
      41             : namespace Parallel {
      42             : template <size_t Dim, class Metavariables, class PhaseDepActionList>
      43             : struct DgElementCollection;
      44             : }  // namespace Parallel
      45             : /// \endcond
      46             : 
      47             : namespace Parallel {
      48             : /*!
      49             :  * \brief An element or multiple elements stored contiguously on a group or
      50             :  * nodegroup.
      51             :  *
      52             :  * Consider first the simpler case where each `DgElementArrayMember` is single
      53             :  * DG or FD element. Each has a DataBox, and inbox. The various bookkeeping
      54             :  * constructs are stored in the `DgElementArrayMemberBase`. The
      55             :  * `DgElementArrayMember` is effectively the distributed object that has
      56             :  * remote entry methods invoked on it. However, a `DgElementArrayMember` is
      57             :  * not tied to a particalur core since it lives on a nodegroup (the
      58             :  * `DgElementCollection`). It is also possible to use a group instead of a
      59             :  * nodegroup, but that is mostly of interest when using GPUs.
      60             :  */
      61             : template <size_t Dim, typename Metavariables, typename PhaseDepActionList,
      62             :           typename SimpleTagsFromOptions>
      63           1 : class DgElementArrayMember;
      64             : 
      65             : template <size_t Dim, typename Metavariables,
      66             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
      67             : // NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor)
      68           0 : class DgElementArrayMember<Dim, Metavariables,
      69             :                            tmpl::list<PhaseDepActionListsPack...>,
      70             :                            SimpleTagsFromOptions>
      71             :     : public DgElementArrayMemberBase<Dim> {
      72             :  public:
      73           0 :   using ParallelComponent =
      74             :       DgElementCollection<Dim, Metavariables,
      75             :                           tmpl::list<PhaseDepActionListsPack...>>;
      76             : 
      77             :   /// List of Actions in the order that generates the DataBox types
      78           1 :   using all_actions_list = tmpl::flatten<
      79             :       tmpl::list<typename PhaseDepActionListsPack::action_list...>>;
      80             :   /// The metavariables class passed to the Algorithm
      81           1 :   using metavariables = Metavariables;
      82             :   /// List of all the Tags that can be received into the Inbox
      83           1 :   using inbox_tags_list = Parallel::get_inbox_tags<all_actions_list>;
      84           0 :   using phase_dependent_action_lists = tmpl::list<PhaseDepActionListsPack...>;
      85           0 :   using all_cache_tags = get_const_global_cache_tags<metavariables>;
      86             : 
      87           0 :   using databox_type = db::compute_databox_type<tmpl::flatten<tmpl::list<
      88             :       Tags::MetavariablesImpl<metavariables>, Tags::ArrayIndex<ElementId<Dim>>,
      89             :       Tags::GlobalCacheProxy<metavariables>, SimpleTagsFromOptions,
      90             :       Tags::GlobalCacheCompute<metavariables>,
      91             :       Tags::ResourceInfoReference<metavariables>,
      92             :       db::wrap_tags_in<Tags::FromGlobalCache, all_cache_tags, metavariables>,
      93             :       Algorithm_detail::get_pdal_simple_tags<phase_dependent_action_lists>,
      94             :       Algorithm_detail::get_pdal_compute_tags<phase_dependent_action_lists>>>>;
      95             : 
      96           0 :   using inbox_type = tuples::tagged_tuple_from_typelist<inbox_tags_list>;
      97             : 
      98           0 :   DgElementArrayMember() = default;
      99             : 
     100             :   template <class... InitializationTags>
     101           0 :   DgElementArrayMember(
     102             :       const Parallel::CProxy_GlobalCache<Metavariables>& global_cache_proxy,
     103             :       tuples::TaggedTuple<InitializationTags...> initialization_items,
     104             :       ElementId<Dim> element_id);
     105             : 
     106             :   /// \cond
     107             :   ~DgElementArrayMember() override = default;
     108             : 
     109             :   DgElementArrayMember(const DgElementArrayMember& /*unused*/) = default;
     110             :   DgElementArrayMember& operator=(const DgElementArrayMember& /*unused*/) =
     111             :       default;
     112             :   DgElementArrayMember(DgElementArrayMember&& /*unused*/) = default;
     113             :   DgElementArrayMember& operator=(DgElementArrayMember&& /*unused*/) = default;
     114             : 
     115             :   WRAPPED_PUPable_decl_base_template(  // NOLINT
     116             :       SINGLE_ARG(DgElementArrayMemberBase<Dim>), DgElementArrayMember);
     117             : 
     118             :   explicit DgElementArrayMember(CkMigrateMessage* msg);
     119             :   /// \endcond
     120             : 
     121             :   /// Start execution of the phase-dependent action list in `next_phase`. If
     122             :   /// `next_phase` has already been visited, execution will resume at the point
     123             :   /// where the previous execution of the same phase left off.
     124             :   ///
     125             :   /// If \p force is true, then regardless of how this component terminated
     126             :   /// (error or deadlock), it will resume.
     127             :   ///
     128             :   /// \warning Don't set \p force to true unless you are absolutely sure you
     129             :   /// want to. This can have very unintended consequences if used incorrectly.
     130           1 :   void start_phase(Parallel::Phase next_phase, bool force = false) override;
     131             : 
     132           0 :   const auto& databox() const { return box_; }
     133             : 
     134             :   /// Start evaluating the algorithm until it is stopped by an action.
     135           1 :   void perform_algorithm() override;
     136             : 
     137             :   template <typename ThisAction, typename PhaseIndex, typename DataBoxIndex>
     138           0 :   bool invoke_iterable_action();
     139             : 
     140             :   /*!
     141             :    * \brief Invokes a simple action on the element.
     142             :    *
     143             :    * \note This does not lock the element. It is up to the calling action to
     144             :    * lock the element if needed.
     145             :    */
     146             :   template <typename Action, typename... Args>
     147           1 :   void simple_action(Args&&... args) {
     148             :     try {
     149             :       if (this->performing_action_) {
     150             :         ERROR(
     151             :             "Already performing an Action and cannot execute additional "
     152             :             "Actions from inside of an Action. This is only possible if the "
     153             :             "simple_action function is not invoked via a proxy, which "
     154             :             "we do not allow.");
     155             :       }
     156             :       this->performing_action_ = true;
     157             :       Action::template apply<ParallelComponent>(
     158             :           box_, *Parallel::local_branch(global_cache_proxy_), this->element_id_,
     159             :           std::forward<Args>(args)...);
     160             :       this->performing_action_ = false;
     161             :       perform_algorithm();
     162             :     } catch (const std::exception& exception) {
     163             :       initiate_shutdown(exception);
     164             :     }
     165             :   }
     166             : 
     167             :   /// Print the expanded type aliases
     168           1 :   std::string print_types() const override;
     169             : 
     170             :   /// Print the current contents of the inboxes
     171           1 :   std::string print_inbox() const override;
     172             : 
     173             :   /// Print the current contents of the DataBox
     174           1 :   std::string print_databox() const override;
     175             : 
     176             :   /// @{
     177             :   /// Get read access to all the inboxes
     178           1 :   auto& inboxes() { return inboxes_; }
     179           1 :   const auto& inboxes() const { return inboxes_; }
     180           1 :   const auto& get_inboxes() const { return inboxes(); }
     181             :   /// @}
     182             : 
     183           0 :   void pup(PUP::er& p) override;
     184             : 
     185             :  private:
     186           0 :   size_t number_of_actions_in_phase(Parallel::Phase phase) const;
     187             : 
     188             :   // After catching an exception, shutdown the simulation
     189           0 :   void initiate_shutdown(const std::exception& exception);
     190             : 
     191             :   template <typename PhaseDepActions, size_t... Is>
     192           0 :   bool iterate_over_actions(std::index_sequence<Is...> /*meta*/);
     193             :   static_assert(std::is_move_constructible_v<databox_type>);
     194             :   static_assert(std::is_move_constructible_v<inbox_type>);
     195             : 
     196           0 :   Parallel::CProxy_GlobalCache<Metavariables> global_cache_proxy_{};
     197           0 :   databox_type box_{};
     198           0 :   inbox_type inboxes_{};
     199             : };
     200             : 
     201             : /// \cond
     202             : template <size_t Dim, typename Metavariables,
     203             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     204             : DgElementArrayMember<
     205             :     Dim, Metavariables, tmpl::list<PhaseDepActionListsPack...>,
     206             :     SimpleTagsFromOptions>::DgElementArrayMember(CkMigrateMessage* msg)
     207             :     : DgElementArrayMemberBase<Dim>(msg) {}
     208             : 
     209             : template <size_t Dim, typename Metavariables,
     210             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     211             : template <class... InitializationTags>
     212             : DgElementArrayMember<Dim, Metavariables, tmpl::list<PhaseDepActionListsPack...>,
     213             :                      SimpleTagsFromOptions>::
     214             :     DgElementArrayMember(
     215             :         const Parallel::CProxy_GlobalCache<Metavariables>& global_cache_proxy,
     216             :         tuples::TaggedTuple<InitializationTags...> initialization_items,
     217             :         ElementId<Dim> element_id)
     218             :     : Parallel::DgElementArrayMemberBase<Dim>(
     219             :           std::move(element_id),
     220             :           Parallel::my_node<size_t>(
     221             :               *Parallel::local_branch(global_cache_proxy))),
     222             :       global_cache_proxy_(global_cache_proxy) {
     223             :   (void)initialization_items;  // avoid potential compiler warnings if unused
     224             :   ::Initialization::mutate_assign<
     225             :       tmpl::list<Tags::ArrayIndex<ElementId<Dim>>,
     226             :                  Tags::GlobalCacheProxy<Metavariables>, InitializationTags...>>(
     227             :       make_not_null(&box_), this->element_id_, global_cache_proxy_,
     228             :       std::move(get<InitializationTags>(initialization_items))...);
     229             : }
     230             : 
     231             : template <size_t Dim, typename Metavariables,
     232             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     233             : void DgElementArrayMember<
     234             :     Dim, Metavariables, tmpl::list<PhaseDepActionListsPack...>,
     235             :     SimpleTagsFromOptions>::start_phase(const Parallel::Phase next_phase,
     236             :                                         const bool force) {
     237             :   try {
     238             :     auto& cache = *Parallel::local_branch(global_cache_proxy_);
     239             :     // terminate should be true since we exited a phase previously.
     240             :     if (force) {
     241             :       Parallel::local_synchronous_action<
     242             :           Parallel::Actions::SetTerminateOnElement>(
     243             :           Parallel::get_parallel_component<ParallelComponent>(cache),
     244             :           make_not_null(&cache), this->element_id_, true);
     245             :     }
     246             :     if (not this->get_terminate() and
     247             :         not this->halt_algorithm_until_next_phase_) {
     248             :       ERROR(
     249             :           "An algorithm must always be set to terminate at the beginning of a "
     250             :           "phase. Since this is not the case the previous phase did not end "
     251             :           "correctly. The previous phase is: "
     252             :           << this->phase_ << " and the next phase is: " << next_phase
     253             :           << ", The termination flag is: " << this->get_terminate()
     254             :           << ", and the halt flag is: "
     255             :           << this->halt_algorithm_until_next_phase_ << ' '
     256             :           << this->element_id_);
     257             :     }
     258             :     // set terminate to true if there are no actions in this PDAL
     259             :     Parallel::local_synchronous_action<
     260             :         Parallel::Actions::SetTerminateOnElement>(
     261             :         Parallel::get_parallel_component<ParallelComponent>(cache),
     262             :         make_not_null(&cache), this->element_id_,
     263             :         number_of_actions_in_phase(next_phase) == 0);
     264             : 
     265             :     // Ideally, we'd set the bookmarks as we are leaving a phase, but there is
     266             :     // no 'clean-up' code that we run when departing a phase, so instead we set
     267             :     // the bookmark for the previous phase (still stored in `phase_` at this
     268             :     // point), before we update the member variable `phase_`.
     269             :     // Then, after updating `phase_`, we check if we've ever stored a bookmark
     270             :     // for the new phase previously. If so, we start from where we left off,
     271             :     // otherwise, start from the beginning of the action list.
     272             :     this->phase_bookmarks_[this->phase_] = this->algorithm_step_;
     273             :     this->phase_ = next_phase;
     274             :     if (this->phase_bookmarks_.count(this->phase_) != 0) {
     275             :       this->algorithm_step_ = this->phase_bookmarks_.at(this->phase_);
     276             :     } else {
     277             :       this->algorithm_step_ = 0;
     278             :     }
     279             :     this->halt_algorithm_until_next_phase_ = false;
     280             :     perform_algorithm();
     281             :   } catch (const std::exception& exception) {
     282             :     initiate_shutdown(exception);
     283             :   }
     284             : }
     285             : 
     286             : template <size_t Dim, typename Metavariables,
     287             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     288             : void DgElementArrayMember<Dim, Metavariables,
     289             :                           tmpl::list<PhaseDepActionListsPack...>,
     290             :                           SimpleTagsFromOptions>::perform_algorithm() {
     291             :   try {
     292             :     if (this->performing_action_ or this->get_terminate() or
     293             :         this->halt_algorithm_until_next_phase_) {
     294             :       return;
     295             :     }
     296             :     const auto invoke_for_phase = [this](auto phase_dep_v) {
     297             :       using PhaseDep = decltype(phase_dep_v);
     298             :       constexpr Parallel::Phase phase = PhaseDep::phase;
     299             :       using actions_list = typename PhaseDep::action_list;
     300             :       if (this->phase_ == phase) {
     301             :         while (
     302             :             tmpl::size<actions_list>::value > 0 and
     303             :             not this->get_terminate() and
     304             :             not this->halt_algorithm_until_next_phase_ and
     305             :             iterate_over_actions<PhaseDep>(
     306             :                 std::make_index_sequence<tmpl::size<actions_list>::value>{})) {
     307             :         }
     308             :         tmpl::for_each<actions_list>([this](auto action_v) {
     309             :           using action = tmpl::type_from<decltype(action_v)>;
     310             :           if (this->algorithm_step_ ==
     311             :               tmpl::index_of<actions_list, action>::value) {
     312             :             this->deadlock_analysis_next_iterable_action_ =
     313             :                 pretty_type::name<action>();
     314             :           }
     315             :         });
     316             :       }
     317             :     };
     318             :     // Loop over all phases, once the current phase is found we perform the
     319             :     // algorithm in that phase until we are no longer able to because we are
     320             :     // waiting on data to be sent or because the algorithm has been marked as
     321             :     // terminated.
     322             :     EXPAND_PACK_LEFT_TO_RIGHT(invoke_for_phase(PhaseDepActionListsPack{}));
     323             :   } catch (const std::exception& exception) {
     324             :     initiate_shutdown(exception);
     325             :   }
     326             : }
     327             : 
     328             : template <size_t Dim, typename Metavariables,
     329             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     330             : std::string
     331             : DgElementArrayMember<Dim, Metavariables, tmpl::list<PhaseDepActionListsPack...>,
     332             :                      SimpleTagsFromOptions>::print_types() const {
     333             :   std::ostringstream os;
     334             :   os << "Algorithm type aliases:\n";
     335             :   os << "using all_actions_list = " << pretty_type::get_name<all_actions_list>()
     336             :      << ";\n";
     337             : 
     338             :   os << "using metavariables = " << pretty_type::get_name<metavariables>()
     339             :      << ";\n";
     340             :   os << "using inbox_tags_list = " << pretty_type::get_name<inbox_tags_list>()
     341             :      << ";\n";
     342             :   os << "using array_index = " << pretty_type::get_name<ElementId<Dim>>()
     343             :      << ";\n";
     344             :   os << "using parallel_component = "
     345             :      << pretty_type::get_name<ParallelComponent>() << ";\n";
     346             :   os << "using phase_dependent_action_lists = "
     347             :      << pretty_type::get_name<phase_dependent_action_lists>() << ";\n";
     348             :   os << "using all_cache_tags = " << pretty_type::get_name<all_cache_tags>()
     349             :      << ";\n";
     350             :   os << "using databox_type = " << pretty_type::get_name<databox_type>()
     351             :      << ";\n";
     352             :   return os.str();
     353             : }
     354             : 
     355             : template <size_t Dim, typename Metavariables,
     356             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     357             : std::string
     358             : DgElementArrayMember<Dim, Metavariables, tmpl::list<PhaseDepActionListsPack...>,
     359             :                      SimpleTagsFromOptions>::print_inbox() const {
     360             :   std::ostringstream os;
     361             :   os << "inboxes_ = " << inboxes_ << ";\n";
     362             :   return os.str();
     363             : }
     364             : 
     365             : template <size_t Dim, typename Metavariables,
     366             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     367             : std::string
     368             : DgElementArrayMember<Dim, Metavariables, tmpl::list<PhaseDepActionListsPack...>,
     369             :                      SimpleTagsFromOptions>::print_databox() const {
     370             :   std::ostringstream os;
     371             :   os << "box_:\n" << box_;
     372             :   return os.str();
     373             : }
     374             : 
     375             : template <size_t Dim, typename Metavariables,
     376             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     377             : template <typename PhaseDepActions, size_t... Is>
     378             : bool DgElementArrayMember<Dim, Metavariables,
     379             :                           tmpl::list<PhaseDepActionListsPack...>,
     380             :                           SimpleTagsFromOptions>::
     381             :     iterate_over_actions(const std::index_sequence<Is...> /*meta*/) {
     382             :   bool take_next_action = true;
     383             :   const auto helper = [this, &take_next_action](auto iteration) {
     384             :     constexpr size_t iter = decltype(iteration)::value;
     385             :     if (not(take_next_action and not this->terminate_ and
     386             :             not this->halt_algorithm_until_next_phase_ and
     387             :             this->algorithm_step_ == iter)) {
     388             :       return;
     389             :     }
     390             :     using actions_list = typename PhaseDepActions::action_list;
     391             :     using this_action = tmpl::at_c<actions_list, iter>;
     392             : 
     393             :     constexpr size_t phase_index =
     394             :         tmpl::index_of<phase_dependent_action_lists, PhaseDepActions>::value;
     395             :     this->performing_action_ = true;
     396             :     ++(this->algorithm_step_);
     397             :     // While the overhead from using the local entry method to enable
     398             :     // profiling is fairly small (<2%), we still avoid it when we aren't
     399             :     // tracing.
     400             :     // #ifdef SPECTRE_CHARM_PROJECTIONS
     401             :     //     if constexpr (Parallel::is_array<parallel_component>::value) {
     402             :     //       if (not this->thisProxy[array_index_]
     403             :     //                   .template invoke_iterable_action<
     404             :     //                       this_action, std::integral_constant<size_t,
     405             :     //                       phase_index>, std::integral_constant<size_t,
     406             :     //                       iter>>()) {
     407             :     //         take_next_action = false;
     408             :     //         --algorithm_step_;
     409             :     //       }
     410             :     //     } else {
     411             :     // #endif  // SPECTRE_CHARM_PROJECTIONS
     412             :     if (not invoke_iterable_action<this_action,
     413             :                                    std::integral_constant<size_t, phase_index>,
     414             :                                    std::integral_constant<size_t, iter>>()) {
     415             :       take_next_action = false;
     416             :       --(this->algorithm_step_);
     417             :     }
     418             :     // #ifdef SPECTRE_CHARM_PROJECTIONS
     419             :     //     }
     420             :     // #endif  // SPECTRE_CHARM_PROJECTIONS
     421             :     this->performing_action_ = false;
     422             :     // Wrap counter if necessary
     423             :     if (this->algorithm_step_ >= tmpl::size<actions_list>::value) {
     424             :       this->algorithm_step_ = 0;
     425             :     }
     426             :   };
     427             :   // In case of no Actions avoid compiler warning.
     428             :   (void)helper;
     429             :   // This is a template for loop for Is
     430             :   EXPAND_PACK_LEFT_TO_RIGHT(helper(std::integral_constant<size_t, Is>{}));
     431             :   return take_next_action;
     432             : }
     433             : 
     434             : template <size_t Dim, typename Metavariables,
     435             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     436             : template <typename ThisAction, typename PhaseIndex, typename DataBoxIndex>
     437             : bool DgElementArrayMember<Dim, Metavariables,
     438             :                           tmpl::list<PhaseDepActionListsPack...>,
     439             :                           SimpleTagsFromOptions>::invoke_iterable_action() {
     440             :   using phase_dep_action =
     441             :       tmpl::at_c<phase_dependent_action_lists, PhaseIndex::value>;
     442             :   using actions_list = typename phase_dep_action::action_list;
     443             : 
     444             : #ifdef SPECTRE_CHARM_PROJECTIONS
     445             :   if constexpr (Parallel::is_array<ParallelComponent>::value) {
     446             :     (void)Parallel::charmxx::RegisterInvokeIterableAction<
     447             :         ParallelComponent, ThisAction, PhaseIndex, DataBoxIndex>::registrar;
     448             :   }
     449             : #endif  // SPECTRE_CHARM_PROJECTIONS
     450             : 
     451             :   const auto& [requested_execution_return, next_action_step] =
     452             :       ThisAction::apply(box_, inboxes_,
     453             :                         *Parallel::local_branch(global_cache_proxy_),
     454             :                         std::as_const(this->element_id_), actions_list{},
     455             :                         std::add_pointer_t<ParallelComponent>{});
     456             :   const auto& requested_execution = requested_execution_return;
     457             : 
     458             :   if (next_action_step.has_value()) {
     459             :     ASSERT(
     460             :         AlgorithmExecution::Retry != requested_execution,
     461             :         "Switching actions on Retry doesn't make sense. Specify std::nullopt "
     462             :         "as the second argument of the iterable action return type");
     463             :     this->algorithm_step_ = next_action_step.value();
     464             :   }
     465             : 
     466             :   switch (requested_execution) {
     467             :     case AlgorithmExecution::Continue:
     468             :       return true;
     469             :     case AlgorithmExecution::Retry:
     470             :       return false;
     471             :     case AlgorithmExecution::Pause: {
     472             :       auto& cache = *Parallel::local_branch(global_cache_proxy_);
     473             :       Parallel::local_synchronous_action<
     474             :           Parallel::Actions::SetTerminateOnElement>(
     475             :           Parallel::get_parallel_component<ParallelComponent>(cache),
     476             :           make_not_null(&cache), this->element_id_, true);
     477             :       return true;
     478             :     }
     479             :     case AlgorithmExecution::Halt: {
     480             :       // Need to make sure halt also gets propagated to the nodegroup
     481             :       this->halt_algorithm_until_next_phase_ = true;
     482             :       auto& cache = *Parallel::local_branch(global_cache_proxy_);
     483             :       Parallel::local_synchronous_action<
     484             :           Parallel::Actions::SetTerminateOnElement>(
     485             :           Parallel::get_parallel_component<ParallelComponent>(cache),
     486             :           make_not_null(&cache), this->element_id_, true);
     487             :       return true;
     488             :     }
     489             :     default:  // LCOV_EXCL_LINE
     490             :       // LCOV_EXCL_START
     491             :       ERROR("No case for a Parallel::AlgorithmExecution with integral value "
     492             :             << static_cast<std::underlying_type_t<AlgorithmExecution>>(
     493             :                    requested_execution)
     494             :             << "\n");
     495             :       // LCOV_EXCL_STOP
     496             :   };
     497             : }
     498             : 
     499             : template <size_t Dim, typename Metavariables,
     500             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     501             : size_t DgElementArrayMember<
     502             :     Dim, Metavariables, tmpl::list<PhaseDepActionListsPack...>,
     503             :     SimpleTagsFromOptions>::number_of_actions_in_phase(const Parallel::Phase
     504             :                                                            phase) const {
     505             :   size_t number_of_actions = 0;
     506             :   const auto helper = [&number_of_actions, phase](auto pdal_v) {
     507             :     if (pdal_v.phase == phase) {
     508             :       number_of_actions = pdal_v.number_of_actions;
     509             :     }
     510             :   };
     511             :   EXPAND_PACK_LEFT_TO_RIGHT(helper(PhaseDepActionListsPack{}));
     512             :   return number_of_actions;
     513             : }
     514             : 
     515             : template <size_t Dim, typename Metavariables,
     516             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     517             : void DgElementArrayMember<
     518             :     Dim, Metavariables, tmpl::list<PhaseDepActionListsPack...>,
     519             :     SimpleTagsFromOptions>::initiate_shutdown(const std::exception& exception) {
     520             :   // In order to make it so that we can later run other actions for cleanup
     521             :   // (e.g. dumping data) we need to make sure that we enable running actions
     522             :   // again
     523             :   this->performing_action_ = false;
     524             :   // Send message to `Main` that we received an exception and set termination.
     525             :   auto* global_cache = Parallel::local_branch(global_cache_proxy_);
     526             :   if (UNLIKELY(global_cache == nullptr)) {
     527             :     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
     528             :     CkError(
     529             :         "Global cache pointer is null. This is an internal inconsistency "
     530             :         "error. Please file an issue.");
     531             :     sys::abort("");
     532             :   }
     533             :   auto main_proxy = global_cache->get_main_proxy();
     534             :   if (UNLIKELY(not main_proxy.has_value())) {
     535             :     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
     536             :     CkError(
     537             :         "The main proxy has not been set in the global cache when terminating "
     538             :         "the component. This is an internal inconsistency error. Please file "
     539             :         "an issue.");
     540             :     sys::abort("");
     541             :   }
     542             :   const std::string message = MakeString{}
     543             :                               << "Message: " << exception.what() << "\nType: "
     544             :                               << pretty_type::get_runtime_type_name(exception);
     545             :   main_proxy.value().add_exception_message(message);
     546             :   auto& cache = *Parallel::local_branch(global_cache_proxy_);
     547             :   Parallel::local_synchronous_action<Parallel::Actions::SetTerminateOnElement>(
     548             :       Parallel::get_parallel_component<ParallelComponent>(cache),
     549             :       make_not_null(&cache), this->element_id_, true);
     550             : }
     551             : 
     552             : template <size_t Dim, typename Metavariables,
     553             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     554             : void DgElementArrayMember<Dim, Metavariables,
     555             :                           tmpl::list<PhaseDepActionListsPack...>,
     556             :                           SimpleTagsFromOptions>::pup(PUP::er& p) {
     557             :   DgElementArrayMemberBase<Dim>::pup(p);
     558             :   p | global_cache_proxy_;
     559             :   p | box_;
     560             :   p | inboxes_;
     561             :   if (p.isUnpacking()) {
     562             :     // Since we need the global cache to set the node, the derived class
     563             :     // does it instead of the base class.
     564             :     this->my_node_ =
     565             :         Parallel::my_node<size_t>(*Parallel::local_branch(global_cache_proxy_));
     566             :   }
     567             : }
     568             : 
     569             : template <size_t Dim, typename Metavariables,
     570             :           typename... PhaseDepActionListsPack, typename SimpleTagsFromOptions>
     571             : PUP::able::PUP_ID DgElementArrayMember<
     572             :     Dim, Metavariables, tmpl::list<PhaseDepActionListsPack...>,
     573             :     SimpleTagsFromOptions>::my_PUP_ID =  // NOLINT
     574             :     0;
     575             : /// \endcond
     576             : }  // namespace Parallel

Generated by: LCOV version 1.14