SpECTRE Documentation Coverage Report
Current view: top level - Parallel/ArrayCollection - DgElementArrayMember.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 41.9 % 31 13
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <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 "DataStructures/TaggedTuple.hpp"
      18              : #include "Domain/Structure/ElementId.hpp"
      19              : #include "Parallel/AlgorithmExecution.hpp"
      20              : #include "Parallel/AlgorithmMetafunctions.hpp"
      21              : #include "Parallel/ArrayCollection/DgElementArrayMemberBase.hpp"
      22              : #include "Parallel/ArrayCollection/SetTerminateOnElement.hpp"
      23              : #include "Parallel/GlobalCache.hpp"
      24              : #include "Parallel/Info.hpp"
      25              : #include "Parallel/Invoke.hpp"
      26              : #include "Parallel/Local.hpp"
      27              : #include "Parallel/ParallelComponentHelpers.hpp"
      28              : #include "Parallel/Phase.hpp"
      29              : #include "Parallel/Tags/ArrayIndex.hpp"
      30              : #include "ParallelAlgorithms/Initialization/MutateAssign.hpp"
      31              : #include "Utilities/ErrorHandling/Assert.hpp"
      32              : #include "Utilities/ErrorHandling/Error.hpp"
      33              : #include "Utilities/Gsl.hpp"
      34              : #include "Utilities/MakeString.hpp"
      35              : #include "Utilities/PrettyType.hpp"
      36              : #include "Utilities/Serialization/CharmPupable.hpp"
      37              : #include "Utilities/System/Abort.hpp"
      38              : #include "Utilities/TMPL.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 2.0-1