Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <cstddef> 7 : #include <map> 8 : #include <optional> 9 : #include <string> 10 : #include <unordered_set> 11 : 12 : #include "DataStructures/DataBox/Tag.hpp" 13 : #include "Domain/Structure/ElementId.hpp" 14 : #include "Domain/Tags.hpp" 15 : #include "IO/Observer/Tags.hpp" 16 : #include "NumericalAlgorithms/Spectral/Mesh.hpp" 17 : #include "Options/Auto.hpp" 18 : #include "Options/String.hpp" 19 : #include "Parallel/Tags/Section.hpp" 20 : #include "Utilities/Gsl.hpp" 21 : #include "Utilities/TMPL.hpp" 22 : 23 : /// Options for AMR 24 : namespace amr::OptionTags { 25 : 26 0 : struct AmrGroup { 27 0 : static std::string name() { return "Amr"; } 28 0 : static constexpr Options::String help = 29 : "Options for adaptive mesh refinement (AMR)"; 30 : }; 31 : 32 0 : struct MaxCoarseLevels { 33 0 : using type = Options::Auto<size_t>; 34 0 : static constexpr Options::String help = 35 : "Maximum number of coarser AMR levels to keep. A value of '0' means that " 36 : "only the finest grid is kept, and 'Auto' means the number of levels " 37 : "is not restricted."; 38 0 : using group = AmrGroup; 39 : }; 40 : 41 : } // namespace amr::OptionTags 42 : 43 : /// AMR tags 44 : namespace amr::Tags { 45 : 46 : /// Maximum number of AMR levels that will be kept. A value of '0' means that 47 : /// only the finest grid is kept, and `std::nullopt` means the number of levels 48 : /// is not restricted. 49 1 : struct MaxCoarseLevels : db::SimpleTag { 50 0 : using type = std::optional<size_t>; 51 0 : static constexpr bool pass_metavariables = false; 52 0 : using option_tags = tmpl::list<OptionTags::MaxCoarseLevels>; 53 0 : static type create_from_options(const type value) { return value; }; 54 : }; 55 : 56 : /// All element IDs grouped by grid index are stored in this tag. The element 57 : /// IDs are registered and deregistered during AMR. 58 : template <size_t Dim> 59 1 : struct AllElementIds : db::SimpleTag { 60 0 : using type = std::map<size_t, std::unordered_set<ElementId<Dim>>>; 61 : }; 62 : 63 : /// The ID of the element that covers the same region or more on the coarser 64 : /// (parent) grid. Only important if AMR is configured to keep coarse grids 65 : /// around. 66 : template <size_t Dim> 67 1 : struct ParentId : db::SimpleTag { 68 0 : using type = std::optional<ElementId<Dim>>; 69 : }; 70 : 71 : /// The IDs of the elements that cover the same region on the finer (child) 72 : /// grid. Only important if AMR is configured to keep coarse grids around. 73 : template <size_t Dim> 74 1 : struct ChildIds : db::SimpleTag { 75 0 : using type = std::unordered_set<ElementId<Dim>>; 76 : }; 77 : 78 : /// The mesh of the parent element. Needed for projections between grids. 79 : /// Only important if AMR is configured to keep coarse grids around. 80 : template <size_t Dim> 81 1 : struct ParentMesh : db::SimpleTag { 82 0 : using type = std::optional<Mesh<Dim>>; 83 : }; 84 : 85 : /// The AMR level of the element. This is used to tag a 86 : /// `Parallel::Tags::Section` that contains all elements on the same grid. 87 : /// Only important if AMR is configured to keep coarse grids around. 88 1 : struct GridIndex { 89 0 : using type = size_t; 90 : }; 91 : 92 : /// True on the finest AMR grid (the one with the highest grid index), false on 93 : /// all other grids. This is used to tag a `Parallel::Tags::Section` that 94 : /// contains all elements on the finest grid. 95 : /// Only important if AMR is configured to keep coarse grids around. 96 1 : struct IsFinestGrid { 97 0 : using type = bool; 98 : }; 99 : 100 : /// An `observers::Tags::ObservationKey` that identifies the grid index. 101 : /// Can be used to tag observations with the grid index. 102 : template <size_t Dim> 103 1 : struct GridIndexObservationKeyCompute 104 : : db::ComputeTag, 105 : observers::Tags::ObservationKey<GridIndex> { 106 0 : using base = observers::Tags::ObservationKey<GridIndex>; 107 0 : using return_type = typename base::type; 108 0 : using argument_tags = 109 : tmpl::list<domain::Tags::Element<Dim>, amr::Tags::ChildIds<Dim>>; 110 0 : static void function( 111 : const gsl::not_null<std::optional<std::string>*> observation_key, 112 : const Element<Dim>& element, 113 : const std::unordered_set<ElementId<Dim>>& child_ids) { 114 : const auto& element_id = element.id(); 115 : const bool is_finest_grid = child_ids.empty(); 116 : *observation_key = 117 : is_finest_grid 118 : ? std::string{""} 119 : : (std::string{"Level"} + std::to_string(element_id.grid_index())); 120 : } 121 : }; 122 : 123 : /// An `observers::Tags::ObservationKey` that identifies the finest grid. 124 : /// Can be used to observe things only on the finest grid. 125 : template <size_t Dim> 126 1 : struct IsFinestGridObservationKeyCompute 127 : : db::ComputeTag, 128 : observers::Tags::ObservationKey<IsFinestGrid> { 129 0 : using base = observers::Tags::ObservationKey<IsFinestGrid>; 130 0 : using return_type = typename base::type; 131 0 : using argument_tags = tmpl::list<amr::Tags::ChildIds<Dim>>; 132 0 : static void function( 133 : const gsl::not_null<std::optional<std::string>*> observation_key, 134 : const std::unordered_set<ElementId<Dim>>& child_ids) { 135 : const bool is_finest_grid = child_ids.empty(); 136 : if (is_finest_grid) { 137 : *observation_key = std::string{""}; 138 : } else { 139 : *observation_key = std::nullopt; 140 : } 141 : } 142 : }; 143 : 144 : } // namespace amr::Tags