Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <algorithm> 7 : #include <array> 8 : #include <cstddef> 9 : #include <unordered_map> 10 : 11 : #include "DataStructures/DataBox/DataBox.hpp" 12 : #include "Domain/Amr/Flag.hpp" 13 : #include "Domain/Amr/Tags/Flags.hpp" 14 : #include "Domain/Amr/Tags/NeighborFlags.hpp" 15 : #include "Domain/Amr/UpdateAmrDecision.hpp" 16 : #include "Domain/Structure/Element.hpp" 17 : #include "Domain/Structure/ElementId.hpp" 18 : #include "Domain/Structure/Neighbors.hpp" 19 : #include "Domain/Tags.hpp" 20 : #include "Parallel/GlobalCache.hpp" 21 : #include "Parallel/Invoke.hpp" 22 : #include "Utilities/Algorithm.hpp" 23 : #include "Utilities/ErrorHandling/Error.hpp" 24 : #include "Utilities/Gsl.hpp" 25 : #include "Utilities/PrettyType.hpp" 26 : #include "Utilities/TMPL.hpp" 27 : 28 : namespace amr::Actions { 29 : /// \brief Given the AMR decision of a neighboring Element, potentially update 30 : /// the AMR decision of the target Element. 31 : /// 32 : /// DataBox: 33 : /// - Uses: 34 : /// * domain::Tags::Element<volume_dim> 35 : /// - Modifies: 36 : /// * amr::Tags::NeighborFlags 37 : /// * amr::Tags::Flags (if AMR decision is updated) 38 : /// 39 : /// Invokes: 40 : /// - amr::Actions::UpdateAmrDecision on all neighboring Element%s (if AMR 41 : /// decision is updated) 42 : /// 43 : /// \details This Element calls amr::update_amr_decision to see if its 44 : /// AMR decision needs to be updated. If it does, the Element will call 45 : /// amr::Actions::UpdateAmrDecision on its neighbors. 46 : /// 47 1 : struct UpdateAmrDecision { 48 : template <typename ParallelComponent, typename DbTagList, 49 : typename Metavariables> 50 0 : static void apply(db::DataBox<DbTagList>& box, 51 : Parallel::GlobalCache<Metavariables>& cache, 52 : const ElementId<Metavariables::volume_dim>& /*element_id*/, 53 : const ElementId<Metavariables::volume_dim>& neighbor_id, 54 : const std::array<amr::Flag, Metavariables::volume_dim>& 55 : neighbor_amr_flags) { 56 : constexpr size_t volume_dim = Metavariables::volume_dim; 57 : auto& my_amr_flags = 58 : db::get_mutable_reference<amr::Tags::Flags<volume_dim>>( 59 : make_not_null(&box)); 60 : auto& my_neighbors_amr_flags = 61 : db::get_mutable_reference<amr::Tags::NeighborFlags<volume_dim>>( 62 : make_not_null(&box)); 63 : 64 : // Actions can be executed in any order. Therefore we need to check: 65 : // - If we received flags from a neighbor multiple times, but not in the 66 : // order they were sent. Neighbor flags should only be sent again if 67 : // they have changed to a higher priority (i.e. higher integral value of 68 : // the flag). 69 : if (1 == my_neighbors_amr_flags.count(neighbor_id)) { 70 : const auto& previously_received_flags = 71 : my_neighbors_amr_flags.at(neighbor_id); 72 : if (not std::lexicographical_compare(previously_received_flags.begin(), 73 : previously_received_flags.end(), 74 : neighbor_amr_flags.begin(), 75 : neighbor_amr_flags.end())) { 76 : return; 77 : } 78 : } 79 : 80 : my_neighbors_amr_flags.insert_or_assign(neighbor_id, neighbor_amr_flags); 81 : 82 : // Actions can be executed in any order. Therefore we need to check: 83 : // - If we have evaluated our own AMR decision. If not, return. 84 : if (amr::Flag::Undefined == my_amr_flags[0]) { 85 : using ::operator<<; 86 : ASSERT(volume_dim == alg::count(my_amr_flags, amr::Flag::Undefined), 87 : "Flags should be all Undefined, not " << my_amr_flags); 88 : return; 89 : } 90 : 91 : const auto& element = get<::domain::Tags::Element<volume_dim>>(box); 92 : 93 : const bool my_amr_decision_changed = amr::update_amr_decision( 94 : make_not_null(&my_amr_flags), element, neighbor_id, neighbor_amr_flags); 95 : 96 : if (my_amr_decision_changed) { 97 : auto& amr_element_array = 98 : Parallel::get_parallel_component<ParallelComponent>(cache); 99 : for (const auto& direction_neighbors : element.neighbors()) { 100 : for (const auto& id : direction_neighbors.second.ids()) { 101 : Parallel::simple_action<UpdateAmrDecision>( 102 : amr_element_array[id], element.id(), my_amr_flags); 103 : } 104 : } 105 : } 106 : } 107 : }; 108 : } // namespace amr::Actions