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::vector<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
|