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

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <cstddef>
       7              : #include <mutex>
       8              : 
       9              : #include "DataStructures/DataBox/DataBox.hpp"
      10              : #include "DataStructures/TaggedTuple.hpp"
      11              : #include "Domain/Structure/ElementId.hpp"
      12              : #include "Parallel/GlobalCache.hpp"
      13              : #include "Parallel/Invoke.hpp"
      14              : #include "Parallel/Local.hpp"
      15              : #include "Parallel/NodeLock.hpp"
      16              : #include "Parallel/Phase.hpp"
      17              : #include "Utilities/ErrorHandling/Error.hpp"
      18              : #include "Utilities/Gsl.hpp"
      19              : 
      20              : namespace Parallel::Actions {
      21              : /// \brief Receive data for a specific element on the nodegroup.
      22              : ///
      23              : /// If `StartPhase` is `true` then `start_phase(phase)` is called on the
      24              : /// `element_to_execute_on`, otherwise `perform_algorithm()` is called on the
      25              : /// `element_to_execute_on`.
      26              : template <bool StartPhase = false>
      27            1 : struct ReceiveDataForElement {
      28              :   /// \brief Entry method called when receiving data from another node.
      29              :   template <typename ParallelComponent, typename DbTagsList,
      30              :             typename Metavariables, typename ArrayIndex, typename ReceiveData,
      31              :             typename ReceiveTag, size_t Dim, typename DistributedObject>
      32            1 :   static void apply(db::DataBox<DbTagsList>& box,
      33              :                     Parallel::GlobalCache<Metavariables>& cache,
      34              :                     const ArrayIndex& /*array_index*/,
      35              :                     const gsl::not_null<Parallel::NodeLock*> /*node_lock*/,
      36              :                     const DistributedObject* /*distributed_object*/,
      37              :                     const ReceiveTag& /*meta*/,
      38              :                     const ElementId<Dim>& element_to_execute_on,
      39              :                     typename ReceiveTag::temporal_id instance,
      40              :                     ReceiveData receive_data) {
      41              :     [[maybe_unused]] const size_t my_node = Parallel::my_node<size_t>(cache);
      42              :     auto& element_collection = db::get_mutable_reference<
      43              :         typename ParallelComponent::element_collection_tag>(
      44              :         make_not_null(&box));
      45              : 
      46              :     ASSERT(
      47              :         element_collection.count(element_to_execute_on) == 1,
      48              :         "ElementId " << element_to_execute_on << " is not on node " << my_node);
      49              :     const bool run_algorithm = ReceiveTag::insert_into_inbox(
      50              :         make_not_null(&tuples::get<ReceiveTag>(
      51              :             element_collection.at(element_to_execute_on).inboxes())),
      52              :         instance, std::move(receive_data));
      53              :     if (run_algorithm) {
      54              :       apply_impl<ParallelComponent>(cache, element_to_execute_on,
      55              :                                     make_not_null(&element_collection));
      56              :     }
      57              :   }
      58              : 
      59              :   /// \brief Entry method call when receiving from same node.
      60              :   template <typename ParallelComponent, typename DbTagsList,
      61              :             typename Metavariables, typename ArrayIndex, size_t Dim,
      62              :             typename DistributedObject>
      63            1 :   static void apply(db::DataBox<DbTagsList>& box,
      64              :                     Parallel::GlobalCache<Metavariables>& cache,
      65              :                     const ArrayIndex& /*array_index*/,
      66              :                     const gsl::not_null<Parallel::NodeLock*> /*node_lock*/,
      67              :                     const DistributedObject* /*distributed_object*/,
      68              :                     const ElementId<Dim>& element_to_execute_on) {
      69              :     auto& element_collection = db::get_mutable_reference<
      70              :         typename ParallelComponent::element_collection_tag>(
      71              :         make_not_null(&box));
      72              :     apply_impl<ParallelComponent>(cache, element_to_execute_on,
      73              :                                   make_not_null(&element_collection));
      74              :   }
      75              : 
      76              :  private:
      77              :   template <typename ParallelComponent, typename Metavariables,
      78              :             typename ElementCollection, size_t Dim>
      79            0 :   static void apply_impl(
      80              :       Parallel::GlobalCache<Metavariables>& cache,
      81              :       const ElementId<Dim>& element_to_execute_on,
      82              :       const gsl::not_null<ElementCollection*> element_collection) {
      83              :     if constexpr (StartPhase) {
      84              :       const Phase current_phase =
      85              :           Parallel::local_branch(
      86              :               Parallel::get_parallel_component<ParallelComponent>(cache))
      87              :               ->phase();
      88              :       ASSERT(element_collection->count(element_to_execute_on) == 1,
      89              :              "ElementId " << element_to_execute_on << " is not on node "
      90              :                           << Parallel::my_node<size_t>(cache););
      91              :       auto& element = element_collection->at(element_to_execute_on);
      92              :       const std::lock_guard element_lock(element.element_lock());
      93              :       // We always force the phase to start because if a previous phase
      94              :       // terminated properly, then this does nothing. But if a phase didn't
      95              :       // terminate properly, then it likely went into deadlock analysis or
      96              :       // post-failure cleanup, in which case we want to run code after a
      97              :       // failure, so we must force the phase to start.
      98              :       element.start_phase(current_phase, true);
      99              :     } else {
     100              :       auto& element = element_collection->at(element_to_execute_on);
     101              :       std::unique_lock element_lock(element.element_lock(), std::defer_lock);
     102              :       if (element_lock.try_lock()) {
     103              :         element.perform_algorithm();
     104              :       } else {
     105              :         const size_t my_node = Parallel::my_node<size_t>(cache);
     106              :         auto& my_proxy =
     107              :             Parallel::get_parallel_component<ParallelComponent>(cache);
     108              :         Parallel::threaded_action<Parallel::Actions::ReceiveDataForElement<>>(
     109              :             my_proxy[my_node], element_to_execute_on);
     110              :       }
     111              :     }
     112              :   }
     113              : };
     114              : }  // namespace Parallel::Actions
        

Generated by: LCOV version 2.0-1