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