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 : const std::string& file_name) { 57 : if constexpr (Parallel::is_dg_element_collection_v<ParallelComponent>) { 58 : auto& element = 59 : Parallel::local_synchronous_action< 60 : Parallel::Actions::GetItemFromDistributedOject< 61 : typename ParallelComponent::element_collection_tag>>( 62 : Parallel::get_parallel_component<ParallelComponent>(cache)) 63 : ->at(array_index); 64 : apply<ParallelComponent>(box, cache, array_index, &element, file_name); 65 : } else { 66 : apply<ParallelComponent>( 67 : box, cache, array_index, 68 : Parallel::local(Parallel::get_parallel_component<ParallelComponent>( 69 : cache)[array_index]), file_name); 70 : } 71 : } 72 : 73 : private: 74 : template <typename ParallelComponent, typename DbTags, typename Metavariables, 75 : typename ArrayIndex, typename T> 76 0 : static void apply(db::DataBox<DbTags>& box, 77 : const Parallel::GlobalCache<Metavariables>& /*cache*/, 78 : const ArrayIndex& array_index, T* local_object_ptr, 79 : const std::string& file_name) { 80 : auto& local_object = *local_object_ptr; 81 : 82 : const bool terminated = local_object.get_terminate(); 83 : 84 : std::stringstream ss{}; 85 : ss << std::scientific << std::setprecision(16); 86 : ss << "Element " << array_index 87 : << (terminated ? " terminated" : " did NOT terminate") << " at time " 88 : << db::get<::Tags::Time>(box) << "."; 89 : 90 : // Only print stuff if this element didn't terminate properly 91 : if (not terminated) { 92 : const std::string& next_action = 93 : local_object.deadlock_analysis_next_iterable_action(); 94 : ss << " Next action: " << next_action << "\n"; 95 : 96 : // Start with time step and next time 97 : const auto& step = db::get<::Tags::TimeStep>(box); 98 : // The time step only prints a slab (beginning/end) and a fraction so we 99 : // also print the approx numerical value of the step for easier reading 100 : ss << " Time step: " << step << ":" << step.value() << "\n"; 101 : ss << " Next time: " 102 : << db::get<::Tags::Next<::Tags::TimeStepId>>(box).substep_time() 103 : << "\n"; 104 : 105 : ss << " Inboxes:\n"; 106 : 107 : const auto& inboxes = local_object.get_inboxes(); 108 : 109 : const std::string mortar_inbox = Parallel::output_inbox< 110 : evolution::dg::Tags::BoundaryCorrectionAndGhostCellsInbox< 111 : 3, Parallel::is_dg_element_collection_v<ParallelComponent>>>( 112 : inboxes, 2_st); 113 : ss << mortar_inbox; 114 : 115 : ss << " Mortars:\n"; 116 : 117 : const auto& mortar_next_temporal_id = 118 : db::get<evolution::dg::Tags::MortarNextTemporalId<3>>(box); 119 : 120 : ss << " MortarNextTemporalId\n"; 121 : for (const auto& [key, next_id] : mortar_next_temporal_id) { 122 : ss << " Key: " << key << ", next time: " << next_id.substep_time() 123 : << "\n"; 124 : } 125 : 126 : if constexpr (Metavariables::local_time_stepping) { 127 : const auto& mortar_data_history = 128 : db::get<evolution::dg::Tags::MortarDataHistory< 129 : 3, typename db::add_tag_prefix< 130 : ::Tags::dt, 131 : typename Metavariables::system::variables_tag>::type>>( 132 : box); 133 : ss << " MortarDataHistory:\n"; 134 : 135 : for (const auto& [key, history] : mortar_data_history) { 136 : ss << " Key: " << key << ", history:\n"; 137 : history.template print<false>(ss, 4_st); 138 : } 139 : } 140 : } else { 141 : ss << "\n"; 142 : } 143 : 144 : Parallel::fprintf(file_name, "%s", ss.str()); 145 : } 146 : }; 147 : } // namespace deadlock