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