Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <iomanip>
7 : #include <sstream>
8 : #include <string>
9 :
10 : #include "DataStructures/DataBox/DataBox.hpp"
11 : #include "DataStructures/DataBox/Prefixes.hpp"
12 : #include "DataStructures/TaggedTuple.hpp"
13 : #include "Evolution/DiscontinuousGalerkin/InboxTags.hpp"
14 : #include "Evolution/DiscontinuousGalerkin/MortarTags.hpp"
15 : #include "Parallel/ArrayCollection/IsDgElementCollection.hpp"
16 : #include "Parallel/GlobalCache.hpp"
17 : #include "Parallel/OutputInbox.hpp"
18 : #include "Parallel/Printf/Printf.hpp"
19 : #include "ParallelAlgorithms/Actions/GetItemFromDistributedObject.hpp"
20 : #include "Time/Tags/Time.hpp"
21 : #include "Time/Tags/TimeStep.hpp"
22 : #include "Time/Tags/TimeStepId.hpp"
23 :
24 : /*!
25 : * \brief Namespace for actions related to debugging deadlocks in communication.
26 : *
27 : * \details These actions will typically be run in the
28 : * `run_deadlock_analysis_simple_actions` function in the metavariables (if it
29 : * exists).
30 : */
31 1 : namespace deadlock {
32 : /*!
33 : * \brief Simple action that will print a variety of information on evolution DG
34 : * elements
35 : *
36 : * \details This will print the contents of the following inbox or DataBox tags:
37 : *
38 : * - `evolution::dg::Tags::BoundaryCorrectionAndGhostCellsInbox<3>`
39 : * - `evolution::dg::Tags::MortarNextTemporalId<3>`
40 : * - `evolution::dg::Tags::MortarDataHistory` (for LTS only)
41 : * - `evolution::dg::Tags::MortarData<3>` (for GTS only)
42 : *
43 : * Inbox tags are printed using the `Parallel::output_inbox` function. The
44 : * DataBox tags are printed with nice indenting for easy readability in the
45 : * stdout file.
46 : *
47 : * This can be generalized in the future to other dimensions if needed.
48 : */
49 1 : struct PrintElementInfo {
50 : template <typename ParallelComponent, typename DbTags, typename Metavariables,
51 : typename ArrayIndex>
52 0 : static void apply(db::DataBox<DbTags>& box,
53 : Parallel::GlobalCache<Metavariables>& cache,
54 : const ArrayIndex& array_index,
55 : const std::string& file_name) {
56 : if constexpr (Parallel::is_dg_element_collection_v<ParallelComponent>) {
57 : auto& element =
58 : Parallel::local_synchronous_action<
59 : Parallel::Actions::GetItemFromDistributedOject<
60 : typename ParallelComponent::element_collection_tag>>(
61 : Parallel::get_parallel_component<ParallelComponent>(cache))
62 : ->at(array_index);
63 : apply<ParallelComponent>(box, cache, array_index, &element, file_name);
64 : } else {
65 : apply<ParallelComponent>(
66 : box, cache, array_index,
67 : Parallel::local(Parallel::get_parallel_component<ParallelComponent>(
68 : cache)[array_index]), file_name);
69 : }
70 : }
71 :
72 : private:
73 : template <typename ParallelComponent, typename DbTags, typename Metavariables,
74 : typename ArrayIndex, typename T>
75 0 : static void apply(db::DataBox<DbTags>& box,
76 : const Parallel::GlobalCache<Metavariables>& /*cache*/,
77 : const ArrayIndex& array_index, T* local_object_ptr,
78 : const std::string& file_name) {
79 : auto& local_object = *local_object_ptr;
80 :
81 : const bool terminated = local_object.get_terminate();
82 :
83 : std::stringstream ss{};
84 : ss << std::scientific << std::setprecision(16);
85 : ss << "Element " << array_index
86 : << (terminated ? " terminated" : " did NOT terminate") << " at time "
87 : << db::get<::Tags::Time>(box) << ".";
88 :
89 : // Only print stuff if this element didn't terminate properly
90 : if (not terminated) {
91 : const std::string& next_action =
92 : local_object.deadlock_analysis_next_iterable_action();
93 : ss << " Next action: " << next_action << "\n";
94 :
95 : // Start with time step and next time
96 : const auto& step = db::get<::Tags::TimeStep>(box);
97 : // The time step only prints a slab (beginning/end) and a fraction so we
98 : // also print the approx numerical value of the step for easier reading
99 : ss << " Time step: " << step << ":" << step.value() << "\n";
100 : ss << " Next time: "
101 : << db::get<::Tags::Next<::Tags::TimeStepId>>(box).substep_time()
102 : << "\n";
103 :
104 : ss << " Inboxes:\n";
105 :
106 : const auto& inboxes = local_object.get_inboxes();
107 :
108 : const std::string mortar_inbox = Parallel::output_inbox<
109 : evolution::dg::Tags::BoundaryCorrectionAndGhostCellsInbox<
110 : 3, Parallel::is_dg_element_collection_v<ParallelComponent>>>(
111 : inboxes, 2_st);
112 : ss << mortar_inbox;
113 :
114 : ss << " Mortars:\n";
115 :
116 : const auto& mortar_next_temporal_id =
117 : db::get<evolution::dg::Tags::MortarNextTemporalId<3>>(box);
118 :
119 : ss << " MortarNextTemporalId\n";
120 : for (const auto& [key, next_id] : mortar_next_temporal_id) {
121 : ss << " Key: " << key << ", next time: " << next_id.substep_time()
122 : << "\n";
123 : }
124 :
125 : const auto& mortar_data_history =
126 : db::get<evolution::dg::Tags::MortarDataHistory<3>>(box);
127 : ss << " MortarDataHistory:\n";
128 :
129 : for (const auto& [key, history] : mortar_data_history) {
130 : ss << " Key: " << key << ", history:\n";
131 : history.template print<false>(ss, 4_st);
132 : }
133 : } else {
134 : ss << "\n";
135 : }
136 :
137 : Parallel::fprintf(file_name, "%s", ss.str());
138 : }
139 : };
140 : } // namespace deadlock
|