Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <array> 7 : #include <cstddef> 8 : #include <optional> 9 : #include <string> 10 : #include <unordered_set> 11 : #include <vector> 12 : 13 : #include "DataStructures/DataBox/PrefixHelpers.hpp" 14 : #include "DataStructures/DataBox/Tag.hpp" 15 : #include "DataStructures/Variables.hpp" 16 : #include "Domain/Creators/Tags/InitialRefinementLevels.hpp" 17 : #include "NumericalAlgorithms/Spectral/Mesh.hpp" 18 : #include "Options/Auto.hpp" 19 : #include "Options/String.hpp" 20 : #include "Utilities/PrettyType.hpp" 21 : #include "Utilities/Serialization/PupStlCpp17.hpp" 22 : #include "Utilities/TMPL.hpp" 23 : 24 : namespace LinearSolver::multigrid { 25 : 26 0 : namespace OptionTags { 27 : 28 : template <typename OptionsGroup> 29 0 : struct MaxLevels { 30 0 : using type = Options::Auto<size_t>; 31 0 : static constexpr Options::String help = 32 : "Maximum number of levels in the multigrid hierarchy. Includes the " 33 : "finest grid, i.e. set to '1' to disable multigrids. Set to 'Auto' to " 34 : "coarsen all the way up to single-element blocks."; 35 0 : using group = OptionsGroup; 36 : }; 37 : 38 : template <typename OptionsGroup> 39 0 : struct OutputVolumeData { 40 0 : using type = bool; 41 0 : static constexpr Options::String help = 42 : "Record volume data for debugging purposes."; 43 0 : using group = OptionsGroup; 44 0 : static bool suggested_value() { return false; } 45 : }; 46 : 47 : template <typename OptionsGroup> 48 0 : struct EnablePreSmoothing { 49 0 : static std::string name() { return "PreSmoothing"; } 50 0 : using type = bool; 51 0 : static constexpr Options::String help = 52 : "Set to 'False' to disable pre-smoothing altogether (\"cascading " 53 : "multigrid\"). Note that pre-smoothing can be necessary to remove " 54 : "high-frequency modes in the data that get restricted to coarser grids, " 55 : "since such high-frequency modes can introduce aliasing. However, when " 56 : "running only a single V-cycle as preconditioner, the initial field is " 57 : "typically zero, so pre-smoothing may not be worthwile."; 58 0 : using group = OptionsGroup; 59 : }; 60 : 61 : template <typename OptionsGroup> 62 0 : struct EnablePostSmoothingAtBottom { 63 0 : static std::string name() { return "PostSmoothingAtBottom"; } 64 0 : using type = bool; 65 0 : static constexpr Options::String help = 66 : "Set to 'False' to skip post-smoothing on the coarsest grid. This means " 67 : "only pre-smoothing runs on the coarsest grid, so the coarsest grid " 68 : "experiences less smoothing altogether. This is typically only " 69 : "desirable if the coarsest grid covers the domain with a single " 70 : "element, or very few, so pre-smoothing is already exceptionally " 71 : "effective and hence post-smoothing is unnecessary on the coarsest grid."; 72 0 : using group = OptionsGroup; 73 : }; 74 : 75 : } // namespace OptionTags 76 : 77 : /// DataBox tags for the `LinearSolver::multigrid::Multigrid` linear solver 78 : namespace Tags { 79 : 80 : /// Initial refinement of the next-finer (child) grid 81 : template <size_t Dim> 82 1 : struct ChildrenRefinementLevels : db::SimpleTag { 83 : private: 84 0 : using base = domain::Tags::InitialRefinementLevels<Dim>; 85 : 86 : public: 87 0 : using type = typename base::type; 88 0 : static constexpr bool pass_metavariables = base::pass_metavariables; 89 0 : using option_tags = typename base::option_tags; 90 0 : static constexpr auto create_from_options = base::create_from_options; 91 : }; 92 : 93 : /// Initial refinement of the next-coarser (parent) grid 94 : template <size_t Dim> 95 1 : struct ParentRefinementLevels : db::SimpleTag { 96 : private: 97 0 : using base = domain::Tags::InitialRefinementLevels<Dim>; 98 : 99 : public: 100 0 : using type = typename base::type; 101 0 : static constexpr bool pass_metavariables = base::pass_metavariables; 102 0 : using option_tags = typename base::option_tags; 103 0 : static constexpr auto create_from_options = base::create_from_options; 104 : }; 105 : 106 : /// Maximum number of multigrid levels that will be created. A value of '1' 107 : /// effectively disables the multigrid, and `std::nullopt` means the number 108 : /// of multigrid levels is not capped. 109 : template <typename OptionsGroup> 110 1 : struct MaxLevels : db::SimpleTag { 111 0 : using type = std::optional<size_t>; 112 0 : static constexpr bool pass_metavariables = false; 113 0 : using option_tags = tmpl::list<OptionTags::MaxLevels<OptionsGroup>>; 114 0 : static type create_from_options(const type value) { return value; }; 115 0 : static std::string name() { 116 : return "MaxLevels(" + pretty_type::name<OptionsGroup>() + ")"; 117 : } 118 : }; 119 : 120 : /// Whether or not volume data should be recorded for debugging purposes 121 : template <typename OptionsGroup> 122 1 : struct OutputVolumeData : db::SimpleTag { 123 0 : using type = bool; 124 0 : static constexpr bool pass_metavariables = false; 125 0 : using option_tags = tmpl::list<OptionTags::OutputVolumeData<OptionsGroup>>; 126 0 : static type create_from_options(const type value) { return value; }; 127 0 : static std::string name() { 128 : return "OutputVolumeData(" + pretty_type::name<OptionsGroup>() + ")"; 129 : } 130 : }; 131 : 132 : /// Enable pre-smoothing. A value of `false` means that pre-smoothing is skipped 133 : /// altogether ("cascading multigrid"). 134 : template <typename OptionsGroup> 135 1 : struct EnablePreSmoothing : db::SimpleTag { 136 0 : using type = bool; 137 0 : static constexpr bool pass_metavariables = false; 138 0 : using option_tags = 139 : tmpl::list<OptionTags::EnablePreSmoothing<OptionsGroup>>; 140 0 : static type create_from_options(const type value) { return value; }; 141 0 : static std::string name() { 142 : return "EnablePreSmoothing(" + pretty_type::name<OptionsGroup>() + ")"; 143 : } 144 : }; 145 : 146 : /// Enable post-smoothing on the coarsest grid. A value of `false` means that 147 : /// post-smoothing is skipped on the coarsest grid, so it runs only 148 : /// pre-smoothing. 149 : template <typename OptionsGroup> 150 1 : struct EnablePostSmoothingAtBottom : db::SimpleTag { 151 0 : using type = bool; 152 0 : static constexpr bool pass_metavariables = false; 153 0 : using option_tags = 154 : tmpl::list<OptionTags::EnablePostSmoothingAtBottom<OptionsGroup>>; 155 0 : static type create_from_options(const type value) { return value; }; 156 0 : static std::string name() { 157 : return "EnablePostSmoothingAtBottom(" + pretty_type::name<OptionsGroup>() + 158 : ")"; 159 : } 160 : }; 161 : 162 : /// The multigrid level. The finest grid is always level 0 and the coarsest grid 163 : /// has the highest level. 164 1 : struct MultigridLevel : db::SimpleTag { 165 0 : using type = size_t; 166 : }; 167 : 168 : /// Indicates the root of the multigrid hierarchy, i.e. level 0. 169 1 : struct IsFinestGrid : db::SimpleTag { 170 0 : using type = bool; 171 : }; 172 : 173 : /// The ID of the element that covers the same region or more on the coarser 174 : /// (parent) grid 175 : template <size_t Dim> 176 1 : struct ParentId : db::SimpleTag { 177 0 : using type = std::optional<ElementId<Dim>>; 178 : }; 179 : 180 : /// The IDs of the elements that cover the same region on the finer (child) grid 181 : template <size_t Dim> 182 1 : struct ChildIds : db::SimpleTag { 183 0 : using type = std::unordered_set<ElementId<Dim>>; 184 : }; 185 : 186 : /// The mesh of the parent element. Needed for projections between grids. 187 : template <size_t Dim> 188 1 : struct ParentMesh : db::SimpleTag { 189 0 : using type = std::optional<Mesh<Dim>>; 190 : }; 191 : 192 : // The following tags are related to volume data output 193 : 194 : /// Continuously incrementing ID for volume observations 195 : template <typename OptionsGroup> 196 1 : struct ObservationId : db::SimpleTag { 197 0 : using type = size_t; 198 0 : static std::string name() { 199 : return "ObservationId(" + pretty_type::name<OptionsGroup>() + ")"; 200 : } 201 : }; 202 : /// @{ 203 : /// Prefix tag for recording volume data in 204 : /// `LinearSolver::multigrid::Tags::VolumeDataForOutput` 205 : template <typename Tag> 206 1 : struct PreSmoothingInitial : db::PrefixTag, db::SimpleTag { 207 0 : using type = typename Tag::type; 208 0 : using tag = Tag; 209 : }; 210 : template <typename Tag> 211 0 : struct PreSmoothingSource : db::PrefixTag, db::SimpleTag { 212 0 : using type = typename Tag::type; 213 0 : using tag = Tag; 214 : }; 215 : template <typename Tag> 216 0 : struct PreSmoothingResult : db::PrefixTag, db::SimpleTag { 217 0 : using type = typename Tag::type; 218 0 : using tag = Tag; 219 : }; 220 : template <typename Tag> 221 0 : struct PreSmoothingResidual : db::PrefixTag, db::SimpleTag { 222 0 : using type = typename Tag::type; 223 0 : using tag = Tag; 224 : }; 225 : template <typename Tag> 226 0 : struct PostSmoothingInitial : db::PrefixTag, db::SimpleTag { 227 0 : using type = typename Tag::type; 228 0 : using tag = Tag; 229 : }; 230 : template <typename Tag> 231 0 : struct PostSmoothingSource : db::PrefixTag, db::SimpleTag { 232 0 : using type = typename Tag::type; 233 0 : using tag = Tag; 234 : }; 235 : template <typename Tag> 236 0 : struct PostSmoothingResult : db::PrefixTag, db::SimpleTag { 237 0 : using type = typename Tag::type; 238 0 : using tag = Tag; 239 : }; 240 : template <typename Tag> 241 0 : struct PostSmoothingResidual : db::PrefixTag, db::SimpleTag { 242 0 : using type = typename Tag::type; 243 0 : using tag = Tag; 244 : }; 245 : /// @} 246 : /// Buffer for recording volume data 247 : template <typename OptionsGroup, typename FieldsTag> 248 1 : struct VolumeDataForOutput : db::SimpleTag { 249 0 : using fields_tags = typename FieldsTag::type::tags_list; 250 0 : using type = Variables< 251 : tmpl::append<db::wrap_tags_in<PreSmoothingInitial, fields_tags>, 252 : db::wrap_tags_in<PreSmoothingSource, fields_tags>, 253 : db::wrap_tags_in<PreSmoothingResult, fields_tags>, 254 : db::wrap_tags_in<PreSmoothingResidual, fields_tags>, 255 : db::wrap_tags_in<PostSmoothingInitial, fields_tags>, 256 : db::wrap_tags_in<PostSmoothingSource, fields_tags>, 257 : db::wrap_tags_in<PostSmoothingResult, fields_tags>, 258 : db::wrap_tags_in<PostSmoothingResidual, fields_tags>>>; 259 0 : static std::string name() { 260 : return "VolumeDataForOutput(" + pretty_type::name<OptionsGroup>() + ")"; 261 : } 262 : }; 263 : 264 : } // namespace Tags 265 : } // namespace LinearSolver::multigrid