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 "ParallelAlgorithms/LinearSolver/Tags.hpp" 21 : #include "Utilities/PrettyType.hpp" 22 : #include "Utilities/Serialization/PupStlCpp17.hpp" 23 : #include "Utilities/TMPL.hpp" 24 : 25 : namespace LinearSolver::multigrid { 26 : 27 0 : namespace OptionTags { 28 : 29 : template <typename OptionsGroup> 30 0 : struct InitialCoarseLevels { 31 0 : using type = Options::Auto<size_t>; 32 0 : static constexpr Options::String help = 33 : "Maximum number of coarser levels in the initial multigrid hierarchy. " 34 : "Set to '0' to create no coarser levels initially. Set to 'Auto' to " 35 : "coarsen all the way up to single-element blocks. " 36 : "AMR may create additional levels later."; 37 0 : using group = OptionsGroup; 38 : }; 39 : 40 : template <typename OptionsGroup> 41 0 : struct OutputVolumeData { 42 0 : using type = bool; 43 0 : static constexpr Options::String help = 44 : "Record volume data for debugging purposes."; 45 0 : using group = OptionsGroup; 46 0 : static bool suggested_value() { return false; } 47 : }; 48 : 49 : template <typename OptionsGroup> 50 0 : struct EnablePreSmoothing { 51 0 : static std::string name() { return "PreSmoothing"; } 52 0 : using type = bool; 53 0 : static constexpr Options::String help = 54 : "Set to 'False' to disable pre-smoothing altogether (\"cascading " 55 : "multigrid\"). Note that pre-smoothing can be necessary to remove " 56 : "high-frequency modes in the data that get restricted to coarser grids, " 57 : "since such high-frequency modes can introduce aliasing. However, when " 58 : "running only a single V-cycle as preconditioner, the initial field is " 59 : "typically zero, so pre-smoothing may not be worthwile."; 60 0 : using group = OptionsGroup; 61 : }; 62 : 63 : template <typename OptionsGroup> 64 0 : struct UseBottomSolver { 65 0 : using type = bool; 66 0 : static constexpr Options::String help = 67 : "Set to 'True' to use a separate bottom solver on the coarsest level " 68 : "instead of pre-smoothing. The bottom solver typically builds the matrix " 69 : "explicitly and inverts it directly. Use the bottom solver if " 70 : "pre-smoothing is not sufficiently effective on the bottom grid. " 71 : "The bottom solver can significantly cut down the number of iterations " 72 : "needed to converge to the solution at the cost of building the matrix " 73 : "explicitly and inverting it directly on the coarsest level."; 74 0 : using group = OptionsGroup; 75 : }; 76 : 77 : template <typename OptionsGroup> 78 0 : struct EnablePostSmoothingAtBottom { 79 0 : static std::string name() { return "PostSmoothingAtBottom"; } 80 0 : using type = bool; 81 0 : static constexpr Options::String help = 82 : "Set to 'False' to skip post-smoothing on the coarsest grid. This means " 83 : "only pre-smoothing runs on the coarsest grid, so the coarsest grid " 84 : "experiences less smoothing altogether. This is typically only " 85 : "desirable if the coarsest grid covers the domain with a single " 86 : "element, or very few, so pre-smoothing is already exceptionally " 87 : "effective and hence post-smoothing is unnecessary on the coarsest grid."; 88 0 : using group = OptionsGroup; 89 : }; 90 : 91 : } // namespace OptionTags 92 : 93 : /// DataBox tags for the `LinearSolver::multigrid::Multigrid` linear solver 94 1 : namespace Tags { 95 : 96 : /// Initial refinement of the next-finer (child) grid 97 : template <size_t Dim> 98 1 : struct ChildrenRefinementLevels : db::SimpleTag { 99 : private: 100 0 : using base = domain::Tags::InitialRefinementLevels<Dim>; 101 : 102 : public: 103 0 : using type = typename base::type; 104 0 : static constexpr bool pass_metavariables = base::pass_metavariables; 105 0 : using option_tags = typename base::option_tags; 106 0 : static constexpr auto create_from_options = base::create_from_options; 107 : }; 108 : 109 : /// Initial refinement of the next-coarser (parent) grid 110 : template <size_t Dim> 111 1 : struct ParentRefinementLevels : db::SimpleTag { 112 : private: 113 0 : using base = domain::Tags::InitialRefinementLevels<Dim>; 114 : 115 : public: 116 0 : using type = typename base::type; 117 0 : static constexpr bool pass_metavariables = base::pass_metavariables; 118 0 : using option_tags = typename base::option_tags; 119 0 : static constexpr auto create_from_options = base::create_from_options; 120 : }; 121 : 122 : /// Maximum number of multigrid levels that will be created. A value of '1' 123 : /// effectively disables the multigrid, and `std::nullopt` means the number 124 : /// of multigrid levels is not capped. 125 : template <typename OptionsGroup> 126 1 : struct InitialCoarseLevels : db::SimpleTag { 127 0 : using type = std::optional<size_t>; 128 0 : static constexpr bool pass_metavariables = false; 129 0 : using option_tags = tmpl::list<OptionTags::InitialCoarseLevels<OptionsGroup>>; 130 0 : static type create_from_options(const type value) { return value; }; 131 0 : static std::string name() { 132 : return "InitialCoarseLevels(" + pretty_type::name<OptionsGroup>() + ")"; 133 : } 134 : }; 135 : 136 : /// Whether or not volume data should be recorded for debugging purposes 137 : template <typename OptionsGroup> 138 1 : struct OutputVolumeData : db::SimpleTag { 139 0 : using type = bool; 140 0 : static constexpr bool pass_metavariables = false; 141 0 : using option_tags = 142 : tmpl::list<LinearSolver::OptionTags::OutputVolumeData<OptionsGroup>>; 143 0 : static type create_from_options(const type value) { return value; }; 144 0 : static std::string name() { 145 : return "OutputVolumeData(" + pretty_type::name<OptionsGroup>() + ")"; 146 : } 147 : }; 148 : 149 : /// Enable pre-smoothing. A value of `false` means that pre-smoothing is skipped 150 : /// altogether ("cascading multigrid"). 151 : template <typename OptionsGroup> 152 1 : struct EnablePreSmoothing : db::SimpleTag { 153 0 : using type = bool; 154 0 : static constexpr bool pass_metavariables = false; 155 0 : using option_tags = 156 : tmpl::list<OptionTags::EnablePreSmoothing<OptionsGroup>>; 157 0 : static type create_from_options(const type value) { return value; }; 158 0 : static std::string name() { 159 : return "EnablePreSmoothing(" + pretty_type::name<OptionsGroup>() + ")"; 160 : } 161 : }; 162 : 163 : /// Enable the bottom solver 164 : template <typename OptionsGroup> 165 1 : struct UseBottomSolver : db::SimpleTag { 166 0 : using type = bool; 167 0 : static constexpr bool pass_metavariables = false; 168 0 : using option_tags = tmpl::list<OptionTags::UseBottomSolver<OptionsGroup>>; 169 0 : static type create_from_options(const type value) { return value; }; 170 0 : static std::string name() { 171 : return "UseBottomSolver(" + pretty_type::name<OptionsGroup>() + ")"; 172 : } 173 : }; 174 : 175 : /// Enable post-smoothing on the coarsest grid. A value of `false` means that 176 : /// post-smoothing is skipped on the coarsest grid, so it runs only 177 : /// pre-smoothing. 178 : template <typename OptionsGroup> 179 1 : struct EnablePostSmoothingAtBottom : db::SimpleTag { 180 0 : using type = bool; 181 0 : static constexpr bool pass_metavariables = false; 182 0 : using option_tags = 183 : tmpl::list<OptionTags::EnablePostSmoothingAtBottom<OptionsGroup>>; 184 0 : static type create_from_options(const type value) { return value; }; 185 0 : static std::string name() { 186 : return "EnablePostSmoothingAtBottom(" + pretty_type::name<OptionsGroup>() + 187 : ")"; 188 : } 189 : }; 190 : 191 : // The following tags are related to volume data output 192 : 193 : /// @{ 194 : /// Prefix tag for recording volume data in 195 : /// `LinearSolver::multigrid::Tags::VolumeDataForOutput` 196 : template <typename Tag> 197 1 : struct PreSmoothingInitial : db::PrefixTag, db::SimpleTag { 198 0 : using type = typename Tag::type; 199 0 : using tag = Tag; 200 : }; 201 : template <typename Tag> 202 0 : struct PreSmoothingSource : db::PrefixTag, db::SimpleTag { 203 0 : using type = typename Tag::type; 204 0 : using tag = Tag; 205 : }; 206 : template <typename Tag> 207 0 : struct PreSmoothingResult : db::PrefixTag, db::SimpleTag { 208 0 : using type = typename Tag::type; 209 0 : using tag = Tag; 210 : }; 211 : template <typename Tag> 212 0 : struct PreSmoothingResidual : db::PrefixTag, db::SimpleTag { 213 0 : using type = typename Tag::type; 214 0 : using tag = Tag; 215 : }; 216 : template <typename Tag> 217 0 : struct PostSmoothingInitial : db::PrefixTag, db::SimpleTag { 218 0 : using type = typename Tag::type; 219 0 : using tag = Tag; 220 : }; 221 : template <typename Tag> 222 0 : struct PostSmoothingSource : db::PrefixTag, db::SimpleTag { 223 0 : using type = typename Tag::type; 224 0 : using tag = Tag; 225 : }; 226 : template <typename Tag> 227 0 : struct PostSmoothingResult : db::PrefixTag, db::SimpleTag { 228 0 : using type = typename Tag::type; 229 0 : using tag = Tag; 230 : }; 231 : template <typename Tag> 232 0 : struct PostSmoothingResidual : db::PrefixTag, db::SimpleTag { 233 0 : using type = typename Tag::type; 234 0 : using tag = Tag; 235 : }; 236 : /// @} 237 : /// Buffer for recording volume data 238 : template <typename OptionsGroup, typename FieldsTag> 239 1 : struct VolumeDataForOutput : db::SimpleTag { 240 0 : using fields_tags = typename FieldsTag::type::tags_list; 241 0 : using type = Variables< 242 : tmpl::append<db::wrap_tags_in<PreSmoothingInitial, fields_tags>, 243 : db::wrap_tags_in<PreSmoothingSource, fields_tags>, 244 : db::wrap_tags_in<PreSmoothingResult, fields_tags>, 245 : db::wrap_tags_in<PreSmoothingResidual, fields_tags>, 246 : db::wrap_tags_in<PostSmoothingInitial, fields_tags>, 247 : db::wrap_tags_in<PostSmoothingSource, fields_tags>, 248 : db::wrap_tags_in<PostSmoothingResult, fields_tags>, 249 : db::wrap_tags_in<PostSmoothingResidual, fields_tags>>>; 250 0 : static std::string name() { 251 : return "VolumeDataForOutput(" + pretty_type::name<OptionsGroup>() + ")"; 252 : } 253 : }; 254 : 255 : } // namespace Tags 256 : } // namespace LinearSolver::multigrid