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 "Evolution/DiscontinuousGalerkin/InboxTags.hpp" 13 : #include "Evolution/DiscontinuousGalerkin/MortarTags.hpp" 14 : #include "Parallel/ArrayCollection/IsDgElementCollection.hpp" 15 : #include "Parallel/GlobalCache.hpp" 16 : #include "Parallel/OutputInbox.hpp" 17 : #include "Parallel/Printf/Printf.hpp" 18 : #include "ParallelAlgorithms/Actions/GetItemFromDistributedObject.hpp" 19 : #include "Time/Tags/Time.hpp" 20 : #include "Time/Tags/TimeStep.hpp" 21 : #include "Time/Tags/TimeStepId.hpp" 22 : #include "Utilities/TaggedTuple.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 : if constexpr (Metavariables::local_time_stepping) { 126 : const auto& mortar_data_history = 127 : db::get<evolution::dg::Tags::MortarDataHistory<3>>(box); 128 : ss << " MortarDataHistory:\n"; 129 : 130 : for (const auto& [key, history] : mortar_data_history) { 131 : ss << " Key: " << key << ", history:\n"; 132 : history.template print<false>(ss, 4_st); 133 : } 134 : } 135 : } else { 136 : ss << "\n"; 137 : } 138 : 139 : Parallel::fprintf(file_name, "%s", ss.str()); 140 : } 141 : }; 142 : } // namespace deadlock