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/PrefixHelpers.hpp" 12 : #include "DataStructures/DataBox/Prefixes.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 : #include "Utilities/TaggedTuple.hpp" 24 : 25 : /*! 26 : * \brief Namespace for actions related to debugging deadlocks in communication. 27 : * 28 : * \details These actions will typically be run in the 29 : * `run_deadlock_analysis_simple_actions` function in the metavariables (if it 30 : * exists). 31 : */ 32 1 : namespace deadlock { 33 : /*! 34 : * \brief Simple action that will print a variety of information on evolution DG 35 : * elements 36 : * 37 : * \details This will print the contents of the following inbox or DataBox tags: 38 : * 39 : * - `evolution::dg::Tags::BoundaryCorrectionAndGhostCellsInbox<3>` 40 : * - `evolution::dg::Tags::MortarNextTemporalId<3>` 41 : * - `evolution::dg::Tags::MortarDataHistory` (for LTS only) 42 : * - `evolution::dg::Tags::MortarData<3>` (for GTS only) 43 : * 44 : * Inbox tags are printed using the `Parallel::output_inbox` function. The 45 : * DataBox tags are printed with nice indenting for easy readability in the 46 : * stdout file. 47 : * 48 : * This can be generalized in the future to other dimensions if needed. 49 : */ 50 1 : struct PrintElementInfo { 51 : template <typename ParallelComponent, typename DbTags, typename Metavariables, 52 : typename ArrayIndex> 53 0 : static void apply(db::DataBox<DbTags>& box, 54 : Parallel::GlobalCache<Metavariables>& cache, 55 : const ArrayIndex& array_index) { 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); 64 : } else { 65 : apply<ParallelComponent>( 66 : box, cache, array_index, 67 : Parallel::local(Parallel::get_parallel_component<ParallelComponent>( 68 : cache)[array_index])); 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 : auto& local_object = *local_object_ptr; 79 : 80 : const bool terminated = local_object.get_terminate(); 81 : 82 : std::stringstream ss{}; 83 : ss << std::scientific << std::setprecision(16); 84 : ss << "Element " << array_index 85 : << (terminated ? " terminated" : " did NOT terminate") << " at time " 86 : << db::get<::Tags::Time>(box) << "."; 87 : 88 : // Only print stuff if this element didn't terminate properly 89 : if (not terminated) { 90 : const std::string& next_action = 91 : local_object.deadlock_analysis_next_iterable_action(); 92 : ss << " Next action: " << next_action << "\n"; 93 : 94 : // Start with time step and next time 95 : const auto& step = db::get<::Tags::TimeStep>(box); 96 : // The time step only prints a slab (beginning/end) and a fraction so we 97 : // also print the approx numerical value of the step for easier reading 98 : ss << " Time step: " << step << ":" << step.value() << "\n"; 99 : ss << " Next time: " 100 : << db::get<::Tags::Next<::Tags::TimeStepId>>(box).substep_time() 101 : << "\n"; 102 : 103 : ss << " Inboxes:\n"; 104 : 105 : const auto& inboxes = local_object.get_inboxes(); 106 : 107 : const std::string mortar_inbox = Parallel::output_inbox< 108 : evolution::dg::Tags::BoundaryCorrectionAndGhostCellsInbox< 109 : 3, Parallel::is_dg_element_collection_v<ParallelComponent>>>( 110 : inboxes, 2_st); 111 : ss << mortar_inbox; 112 : 113 : ss << " Mortars:\n"; 114 : 115 : const auto& mortar_next_temporal_id = 116 : db::get<evolution::dg::Tags::MortarNextTemporalId<3>>(box); 117 : 118 : ss << " MortarNextTemporalId\n"; 119 : for (const auto& [key, next_id] : mortar_next_temporal_id) { 120 : ss << " Key: " << key << ", next time: " << next_id.substep_time() 121 : << "\n"; 122 : } 123 : 124 : if constexpr (Metavariables::local_time_stepping) { 125 : const auto& mortar_data_history = 126 : db::get<evolution::dg::Tags::MortarDataHistory< 127 : 3, typename db::add_tag_prefix< 128 : ::Tags::dt, 129 : typename Metavariables::system::variables_tag>::type>>( 130 : box); 131 : ss << " MortarDataHistory:\n"; 132 : 133 : for (const auto& [key, history] : mortar_data_history) { 134 : ss << " Key: " << key << ", history:\n"; 135 : history.template print<false>(ss, 4_st); 136 : } 137 : } 138 : } else { 139 : ss << "\n"; 140 : } 141 : 142 : Parallel::printf("%s", ss.str()); 143 : } 144 : }; 145 : } // namespace deadlock