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/ArrayCollection/IsDgElementCollection.hpp" 21 : #include "Parallel/ArrayCollection/SimpleActionOnElement.hpp" 22 : #include "Parallel/ArrayCollection/Tags/ElementLocations.hpp" 23 : #include "Parallel/GlobalCache.hpp" 24 : #include "Parallel/Invoke.hpp" 25 : #include "ParallelAlgorithms/Actions/GetItemFromDistributedObject.hpp" 26 : #include "ParallelAlgorithms/Amr/Policies/Policies.hpp" 27 : #include "ParallelAlgorithms/Amr/Policies/Tags.hpp" 28 : #include "ParallelAlgorithms/Amr/Projectors/Mesh.hpp" 29 : #include "Utilities/Algorithm.hpp" 30 : #include "Utilities/ErrorHandling/Error.hpp" 31 : #include "Utilities/Gsl.hpp" 32 : #include "Utilities/PrettyType.hpp" 33 : #include "Utilities/TMPL.hpp" 34 : 35 : namespace amr::Actions { 36 : /// \brief Given the AMR decision of a neighboring Element, potentially update 37 : /// the AMR decision of the target Element. 38 : /// 39 : /// DataBox: 40 : /// - Uses: 41 : /// * domain::Tags::Element<volume_dim> 42 : /// - Modifies: 43 : /// * amr::Tags::NeighborInfo 44 : /// * amr::Tags::Info (if AMR decision is updated) 45 : /// 46 : /// Invokes: 47 : /// - amr::Actions::UpdateAmrDecision on all neighboring Element%s (if AMR 48 : /// decision is updated) 49 : /// 50 : /// \details This Element calls amr::update_amr_decision to see if its 51 : /// AMR decision needs to be updated. If it does, the Element will call 52 : /// amr::Actions::UpdateAmrDecision on its neighbors. 53 : /// 54 1 : struct UpdateAmrDecision { 55 : template <typename ParallelComponent, typename DbTagList, 56 : typename Metavariables> 57 0 : static void apply(db::DataBox<DbTagList>& box, 58 : Parallel::GlobalCache<Metavariables>& cache, 59 : const ElementId<Metavariables::volume_dim>& /*element_id*/, 60 : const ElementId<Metavariables::volume_dim>& neighbor_id, 61 : const Info<Metavariables::volume_dim>& neighbor_amr_info) { 62 : constexpr size_t volume_dim = Metavariables::volume_dim; 63 : auto& my_amr_info = db::get_mutable_reference<amr::Tags::Info<volume_dim>>( 64 : make_not_null(&box)); 65 : auto& my_neighbors_amr_info = 66 : db::get_mutable_reference<amr::Tags::NeighborInfo<volume_dim>>( 67 : make_not_null(&box)); 68 : 69 : // Actions can be executed in any order. Therefore we need to check: 70 : // - If we received info from a neighbor multiple times, but not in the 71 : // order they were sent. Neighbor info should only be sent again if 72 : // the flags have changed to a higher priority (i.e. higher integral value 73 : // of the flag) or the new mesh has a larger number of grid points. 74 : if (1 == my_neighbors_amr_info.count(neighbor_id)) { 75 : const auto& previously_received_info = 76 : my_neighbors_amr_info.at(neighbor_id); 77 : if (previously_received_info.new_mesh.number_of_grid_points() >= 78 : neighbor_amr_info.new_mesh.number_of_grid_points() and 79 : not std::lexicographical_compare( 80 : previously_received_info.flags.begin(), 81 : previously_received_info.flags.end(), 82 : neighbor_amr_info.flags.begin(), neighbor_amr_info.flags.end())) { 83 : return; 84 : } 85 : } 86 : 87 : my_neighbors_amr_info.insert_or_assign(neighbor_id, neighbor_amr_info); 88 : 89 : auto& my_amr_flags = my_amr_info.flags; 90 : // Actions can be executed in any order. Therefore we need to check: 91 : // - If we have evaluated our own AMR decision. If not, return. 92 : if (amr::Flag::Undefined == my_amr_flags[0]) { 93 : using ::operator<<; 94 : ASSERT(volume_dim == alg::count(my_amr_flags, amr::Flag::Undefined), 95 : "Flags should be all Undefined, not " << my_amr_flags); 96 : return; 97 : } 98 : 99 : const auto& element = get<::domain::Tags::Element<volume_dim>>(box); 100 : const auto my_initial_new_mesh = my_amr_info.new_mesh; 101 : 102 : const bool my_amr_decision_changed = amr::update_amr_decision( 103 : make_not_null(&my_amr_flags), element, neighbor_id, 104 : neighbor_amr_info.flags, 105 : get<amr::Tags::Policies>(box) 106 : .enforce_two_to_one_balance_in_normal_direction()); 107 : 108 : auto& my_new_mesh = my_amr_info.new_mesh; 109 : my_new_mesh = 110 : amr::projectors::new_mesh(get<::domain::Tags::Mesh<volume_dim>>(box), 111 : my_amr_flags, element, my_neighbors_amr_info); 112 : 113 : if (my_amr_decision_changed or my_new_mesh != my_initial_new_mesh) { 114 : auto& amr_element_array = 115 : Parallel::get_parallel_component<ParallelComponent>(cache); 116 : for (const auto& direction_neighbors : element.neighbors()) { 117 : for (const auto& id : direction_neighbors.second.ids()) { 118 : if constexpr (Parallel::is_dg_element_collection_v< 119 : ParallelComponent>) { 120 : const auto neighbor_location = static_cast<int>( 121 : Parallel::local_synchronous_action< 122 : Parallel::Actions::GetItemFromDistributedOject< 123 : Parallel::Tags::ElementLocations<volume_dim>>>( 124 : Parallel::get_parallel_component<ParallelComponent>(cache)) 125 : ->at(id)); 126 : Parallel::threaded_action<Parallel::Actions::SimpleActionOnElement< 127 : UpdateAmrDecision, true>>(amr_element_array[neighbor_location], 128 : id, element.id(), my_amr_info); 129 : } else { 130 : Parallel::simple_action<UpdateAmrDecision>( 131 : amr_element_array[id], element.id(), my_amr_info); 132 : } 133 : } 134 : } 135 : } 136 : } 137 : }; 138 : } // namespace amr::Actions