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

Generated by: LCOV version 1.14