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
|