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

Generated by: LCOV version 1.14