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
|