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 "Domain/Structure/ElementId.hpp" 11 : #include "Parallel/ArrayCollection/Tags/ElementLocations.hpp" 12 : #include "Parallel/GlobalCache.hpp" 13 : #include "Parallel/Info.hpp" 14 : #include "Parallel/Invoke.hpp" 15 : #include "Parallel/NodeLock.hpp" 16 : #include "Utilities/Gsl.hpp" 17 : 18 : namespace Parallel::Actions { 19 : /// \brief A threaded action that calls the simple action `SimpleActionToCall` 20 : /// on either the specified element or broadcasts to the nodegroup. 21 : /// 22 : /// If `Block` is `true` then the action will wait until the element is free 23 : /// to be operated on. If it is `false` then a message will be sent to the 24 : /// nodegroup to try invoking the element again. 25 : /// 26 : /// This is a threaded action intended to be run on the DG nodegroup. 27 : template <typename SimpleActionToCall, bool Block> 28 1 : struct SimpleActionOnElement { 29 : /// \brief Invoke the simple action on a single element 30 : template <typename ParallelComponent, typename DbTagsList, 31 : typename Metavariables, typename ArrayIndex, 32 : typename DistributedObject, size_t Dim, typename... Args> 33 1 : static void apply(db::DataBox<DbTagsList>& box, 34 : Parallel::GlobalCache<Metavariables>& cache, 35 : const ArrayIndex& /*array_index*/, 36 : const gsl::not_null<Parallel::NodeLock*> /*node_lock*/, 37 : const DistributedObject* /*distributed_object*/, 38 : const ElementId<Dim>& element_to_execute_on, 39 : Args&&... args) { 40 : const size_t my_node = Parallel::my_node<size_t>(cache); 41 : auto& my_proxy = Parallel::get_parallel_component<ParallelComponent>(cache); 42 : 43 : auto& element_collection = db::get_mutable_reference< 44 : typename ParallelComponent::element_collection_tag>( 45 : make_not_null(&box)); 46 : auto& element = element_collection.at(element_to_execute_on); 47 : std::unique_lock element_lock(element.element_lock(), std::defer_lock); 48 : if constexpr (Block) { 49 : element_lock.lock(); 50 : element.template simple_action<SimpleActionToCall>( 51 : std::forward<Args>(args)...); 52 : } else { 53 : if (element_lock.try_lock()) { 54 : element.template simple_action<SimpleActionToCall>( 55 : std::forward<Args>(args)...); 56 : } else { 57 : Parallel::threaded_action<Parallel::Actions::SimpleActionOnElement< 58 : SimpleActionToCall, Block>>(my_proxy[my_node], 59 : element_to_execute_on, 60 : std::forward<Args>(args)...); 61 : } 62 : } 63 : } 64 : 65 : /// \brief Invoke the simple action on all elements 66 : /// 67 : /// \note This loops over all elements and spawns a message for each element. 68 : template <typename ParallelComponent, typename DbTagsList, 69 : typename Metavariables, typename ArrayIndex, 70 : typename DistributedObject, typename... Args> 71 1 : static void apply(db::DataBox<DbTagsList>& box, 72 : Parallel::GlobalCache<Metavariables>& cache, 73 : const ArrayIndex& /*array_index*/, 74 : const gsl::not_null<Parallel::NodeLock*> /*node_lock*/, 75 : const DistributedObject* /*distributed_object*/, 76 : const Args&... args) { 77 : auto& my_proxy = Parallel::get_parallel_component<ParallelComponent>(cache); 78 : 79 : auto& element_locations = db::get_mutable_reference< 80 : Parallel::Tags::ElementLocations<Metavariables::volume_dim>>( 81 : make_not_null(&box)); 82 : for (const auto& [element_id, node_id] : element_locations) { 83 : if (node_id == Parallel::my_node<size_t>(cache)) { 84 : Parallel::threaded_action<Parallel::Actions::SimpleActionOnElement< 85 : SimpleActionToCall, Block>>(my_proxy[node_id], element_id, args...); 86 : } 87 : } 88 : } 89 : }; 90 : } // namespace Parallel::Actions