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/Creators/OptionTags.hpp" 14 : #include "Domain/Structure/ElementId.hpp" 15 : #include "Domain/Tags.hpp" 16 : #include "IO/Observer/Tags.hpp" 17 : #include "NumericalAlgorithms/Spectral/Mesh.hpp" 18 : #include "Options/Auto.hpp" 19 : #include "Options/String.hpp" 20 : #include "Parallel/Tags/Section.hpp" 21 : #include "Utilities/Gsl.hpp" 22 : #include "Utilities/TMPL.hpp" 23 : 24 : /// Options for AMR 25 : namespace amr::OptionTags { 26 : 27 : /// Group for AMR options 28 1 : struct AmrGroup { 29 0 : static std::string name() { return "Amr"; } 30 0 : static constexpr Options::String help = 31 : "Options for adaptive mesh refinement (AMR)"; 32 : }; 33 : 34 : /// Maximum number of AMR levels to keep. 35 1 : struct MaxCoarseLevels { 36 0 : using type = Options::Auto<size_t>; 37 0 : static constexpr Options::String help = 38 : "Maximum number of coarser AMR levels to keep. A value of '0' means that " 39 : "only the finest grid is kept, and 'Auto' means the number of levels " 40 : "is not restricted."; 41 0 : using group = AmrGroup; 42 : }; 43 : 44 : /// Blocks in which AMR is enabled. 45 1 : struct AmrBlocks { 46 0 : static std::string name() { return "EnableInBlocks"; } 47 0 : struct All {}; 48 0 : using type = Options::Auto<std::vector<std::string>, All>; 49 0 : static constexpr Options::String help = 50 : "Blocks in which AMR is enabled. Note that blocks that do not have AMR " 51 : "enabled can still be refined to satisfy 2:1 balance. When this happens, " 52 : "they won't coarsen back since 'do nothing' has higher priority than " 53 : "coarsening. This behavior can be changed if needed."; 54 0 : using group = AmrGroup; 55 : }; 56 : 57 : } // namespace amr::OptionTags 58 : 59 : /// AMR tags 60 : namespace amr::Tags { 61 : 62 : /// Maximum number of AMR levels that will be kept. A value of '0' means that 63 : /// only the finest grid is kept, and `std::nullopt` means the number of levels 64 : /// is not restricted. 65 1 : struct MaxCoarseLevels : db::SimpleTag { 66 0 : using type = std::optional<size_t>; 67 0 : static constexpr bool pass_metavariables = false; 68 0 : using option_tags = tmpl::list<OptionTags::MaxCoarseLevels>; 69 0 : static type create_from_options(const type value) { return value; } 70 : }; 71 : 72 : /// The set of block IDs in which AMR is enabled. If `std::nullopt`, AMR is 73 : /// enabled in all blocks. 74 : template <size_t Dim> 75 1 : struct AmrBlocks : db::SimpleTag { 76 0 : using type = std::optional<std::unordered_set<size_t>>; 77 0 : static constexpr bool pass_metavariables = false; 78 0 : using option_tags = tmpl::list<OptionTags::AmrBlocks, 79 : ::domain::OptionTags::DomainCreator<Dim>>; 80 0 : static type create_from_options( 81 : const std::optional<std::vector<std::string>>& block_names, 82 : const std::unique_ptr<::DomainCreator<Dim>>& domain_creator); 83 : }; 84 : 85 : /// All element IDs grouped by grid index are stored in this tag. The element 86 : /// IDs are registered and deregistered during AMR. 87 : template <size_t Dim> 88 1 : struct AllElementIds : db::SimpleTag { 89 0 : using type = std::map<size_t, std::unordered_set<ElementId<Dim>>>; 90 : }; 91 : 92 : /// The ID of the element that covers the same region or more on the coarser 93 : /// (parent) grid. Only important if AMR is configured to keep coarse grids 94 : /// around. 95 : template <size_t Dim> 96 1 : struct ParentId : db::SimpleTag { 97 0 : using type = std::optional<ElementId<Dim>>; 98 : }; 99 : 100 : /// The IDs of the elements that cover the same region on the finer (child) 101 : /// grid. Only important if AMR is configured to keep coarse grids around. 102 : template <size_t Dim> 103 1 : struct ChildIds : db::SimpleTag { 104 0 : using type = std::unordered_set<ElementId<Dim>>; 105 : }; 106 : 107 : /// The mesh of the parent element. Needed for projections between grids. 108 : /// Only important if AMR is configured to keep coarse grids around. 109 : template <size_t Dim> 110 1 : struct ParentMesh : db::SimpleTag { 111 0 : using type = std::optional<Mesh<Dim>>; 112 : }; 113 : 114 : /// The AMR level of the element. This is used to tag a 115 : /// `Parallel::Tags::Section` that contains all elements on the same grid. 116 : /// Only important if AMR is configured to keep coarse grids around. 117 1 : struct GridIndex { 118 0 : using type = size_t; 119 : }; 120 : 121 : /// True on the finest AMR grid (the one with the highest grid index), false on 122 : /// all other grids. This is used to tag a `Parallel::Tags::Section` that 123 : /// contains all elements on the finest grid. 124 : /// Only important if AMR is configured to keep coarse grids around. 125 1 : struct IsFinestGrid { 126 0 : using type = bool; 127 : }; 128 : 129 : /// An `observers::Tags::ObservationKey` that identifies the grid index. 130 : /// Can be used to tag observations with the grid index. 131 : template <size_t Dim> 132 1 : struct GridIndexObservationKeyCompute 133 : : db::ComputeTag, 134 : observers::Tags::ObservationKey<GridIndex> { 135 0 : using base = observers::Tags::ObservationKey<GridIndex>; 136 0 : using return_type = typename base::type; 137 0 : using argument_tags = 138 : tmpl::list<domain::Tags::Element<Dim>, amr::Tags::ChildIds<Dim>>; 139 0 : static void function( 140 : const gsl::not_null<std::optional<std::string>*> observation_key, 141 : const Element<Dim>& element, 142 : const std::unordered_set<ElementId<Dim>>& child_ids) { 143 : const auto& element_id = element.id(); 144 : const bool is_finest_grid = child_ids.empty(); 145 : *observation_key = 146 : is_finest_grid 147 : ? std::string{""} 148 : : (std::string{"Level"} + std::to_string(element_id.grid_index())); 149 : } 150 : }; 151 : 152 : /// An `observers::Tags::ObservationKey` that identifies the finest grid. 153 : /// Can be used to observe things only on the finest grid. 154 : template <size_t Dim> 155 1 : struct IsFinestGridObservationKeyCompute 156 : : db::ComputeTag, 157 : observers::Tags::ObservationKey<IsFinestGrid> { 158 0 : using base = observers::Tags::ObservationKey<IsFinestGrid>; 159 0 : using return_type = typename base::type; 160 0 : using argument_tags = tmpl::list<amr::Tags::ChildIds<Dim>>; 161 0 : static void function( 162 : const gsl::not_null<std::optional<std::string>*> observation_key, 163 : const std::unordered_set<ElementId<Dim>>& child_ids) { 164 : const bool is_finest_grid = child_ids.empty(); 165 : if (is_finest_grid) { 166 : *observation_key = std::string{""}; 167 : } else { 168 : *observation_key = std::nullopt; 169 : } 170 : } 171 : }; 172 : 173 : } // namespace amr::Tags