Tags.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <array>
7 #include <cstddef>
8 #include <string>
9 
10 #include "DataStructures/DataBox/Subitems.hpp"
11 #include "DataStructures/DataBox/Tag.hpp"
12 #include "DataStructures/DataVector.hpp"
15 #include "Options/Auto.hpp"
16 #include "Options/Options.hpp"
17 #include "Parallel/Serialize.hpp"
18 #include "ParallelAlgorithms/LinearSolver/Schwarz/OverlapHelpers.hpp"
19 #include "Utilities/Gsl.hpp"
20 #include "Utilities/TMPL.hpp"
21 
22 namespace LinearSolver::Schwarz {
23 
24 /// Option tags related to the Schwarz solver
25 namespace OptionTags {
26 
27 template <typename OptionsGroup>
28 struct MaxOverlap {
29  using type = size_t;
30  using group = OptionsGroup;
31  static constexpr Options::String help =
32  "Number of points that subdomains can extend into neighbors";
33 };
34 
35 template <typename SolverType, typename OptionsGroup>
37  using type = SolverType;
38  using group = OptionsGroup;
39  static constexpr Options::String help = "The linear solver on subdomains";
40 };
41 
42 template <typename OptionsGroup>
44  static std::string name() noexcept { return "SkipResets"; }
45  using type = bool;
46  using group = OptionsGroup;
47  static constexpr Options::String help =
48  "Skip resets of the subdomain solver. This only has an effect in cases "
49  "where the operator changes, e.g. between nonlinear-solver iterations. "
50  "Skipping resets avoids expensive re-building of the operator, but comes "
51  "at the cost of less accurate preconditioning and thus potentially more "
52  "preconditioned iterations. Whether or not this helps convergence "
53  "overall is highly problem-dependent.";
54 };
55 
56 } // namespace OptionTags
57 
58 /// Tags related to the Schwarz solver
59 namespace Tags {
60 
61 /// Number of points a subdomain can overlap with its neighbor
62 template <typename OptionsGroup>
64  static std::string name() noexcept {
65  return "MaxOverlap(" + Options::name<OptionsGroup>() + ")";
66  }
67  using type = size_t;
68  static constexpr bool pass_metavariables = false;
69  using option_tags = tmpl::list<OptionTags::MaxOverlap<OptionsGroup>>;
70  static type create_from_options(const type& value) noexcept { return value; }
71 };
72 
73 /// The serial linear solver used to solve subdomain operators
74 template <typename OptionsGroup>
76  static std::string name() noexcept {
77  return "SubdomainSolver(" + Options::name<OptionsGroup>() + ")";
78  }
79 };
80 
81 /// The serial linear solver of type `SolverType` used to solve subdomain
82 /// operators
83 template <typename SolverType, typename OptionsGroup>
85  using type = SolverType;
86  static constexpr bool pass_metavariables = false;
87  using option_tags =
88  tmpl::list<OptionTags::SubdomainSolver<SolverType, OptionsGroup>>;
89  static type create_from_options(const type& value) noexcept {
90  return deserialize<type>(serialize<type>(value).data());
91  }
92 };
93 
94 /// Skip resets of the subdomain solver.
95 ///
96 /// \see LinearSolver::Schwarz::Actions::ResetSubdomainSolver
97 template <typename OptionsGroup>
99  using type = bool;
100  static constexpr bool pass_metavariables = false;
101  using option_tags =
102  tmpl::list<OptionTags::SkipSubdomainSolverResets<OptionsGroup>>;
103  static bool create_from_options(const bool value) noexcept { return value; }
104 };
105 
106 /*!
107  * \brief The `Tag` on the overlap region with each neighbor, i.e. on a region
108  * extruding from the central element.
109  *
110  * Note that data on an overlap with a neighbor is typically oriented according
111  * to the neighbor's orientation, so re-orientation needs to happen whenever
112  * the data cross element boundaries.
113  */
114 template <typename Tag, size_t Dim, typename OptionsGroup>
116  static std::string name() noexcept {
117  return "Overlaps(" + db::tag_name<Tag>() + ", " +
118  Options::name<OptionsGroup>() + ")";
119  }
120  using tag = Tag;
122 };
123 
124 /// The number of points a neighbor's subdomain extends into the element
125 template <size_t Dim, typename OptionsGroup>
127  static std::string name() noexcept {
128  return "IntrudingExtents(" + Options::name<OptionsGroup>() + ")";
129  }
131 };
132 
133 /// The width in element-logical coordinates that a neighbor's subdomain extends
134 /// into the element
135 template <size_t Dim, typename OptionsGroup>
137  static std::string name() noexcept {
138  return "IntrudingOverlapWidths(" + Options::name<OptionsGroup>() + ")";
139  }
141 };
142 
143 /// Weighting field for combining data from multiple overlapping subdomains
144 template <typename OptionsGroup>
146  static std::string name() noexcept {
147  return "Weight(" + Options::name<OptionsGroup>() + ")";
148  }
149  using type = Scalar<DataVector>;
150 };
151 
152 /*!
153  * \brief A diagnostic quantity to check that weights are conserved
154  *
155  * This quantity and the `Tags::Weight` on the element should sum to one on all
156  * grid points. Residual values indicate that overlap data from neighboring
157  * subdomains and data on the element are combined in a non-conservative way.
158  */
159 template <typename OptionsGroup>
161  static std::string name() noexcept {
162  return "SummedIntrudingOverlapWeights(" + Options::name<OptionsGroup>() +
163  ")";
164  }
165  using type = Scalar<DataVector>;
166 };
167 
168 } // namespace Tags
169 } // namespace LinearSolver::Schwarz
170 
171 namespace db {
172 namespace detail {
173 // This implementation mirrors the interface tag subitems in `Domain/Tags.hpp`.
174 // Please see that implementation for details.
175 template <typename VariablesTag, size_t Dim, typename OptionsGroup,
176  typename Tags = typename VariablesTag::type::tags_list>
177 struct OverlapSubitemsImpl;
178 
179 template <typename VariablesTag, size_t Dim, typename OptionsGroup,
180  typename... Tags>
181 struct OverlapSubitemsImpl<VariablesTag, Dim, OptionsGroup,
182  tmpl::list<Tags...>> {
183  using type = tmpl::list<
185  using tag =
187  using return_type = NoSuchType;
188  template <typename Subtag>
189  static void create_item(
190  const gsl::not_null<typename tag::type*> parent_value,
191  const gsl::not_null<typename Subtag::type*> sub_value) noexcept {
192  sub_value->clear();
193  for (auto& [overlap_id, parent_overlap_vars] : *parent_value) {
194  auto& parent_overlap_field =
195  get<typename Subtag::tag>(parent_overlap_vars);
196  auto& sub_overlap_field = (*sub_value)[overlap_id];
197  for (size_t i = 0; i < parent_overlap_field.size(); ++i) {
198  sub_overlap_field[i].set_data_ref(&parent_overlap_field[i]);
199  }
200  }
201  }
202  template <typename Subtag>
203  static void create_compute_item(
205  const typename tag::type& parent_value) noexcept {
206  for (const auto& [overlap_id, parent_overlap_vars] : parent_value) {
207  const auto& parent_overlap_field =
208  get<typename Subtag::tag>(parent_overlap_vars);
209  auto& sub_overlap_field = (*sub_value)[overlap_id];
210  for (size_t i = 0; i < parent_overlap_field.size(); ++i) {
211  // clang-tidy: do not use const_cast
212  // The DataBox will only give out a const reference to the result of a
213  // compute item. Here, that is a reference to a const map to Tensors of
214  // DataVectors. There is no (publicly visible) indirection there, so
215  // having the map const will allow only const access to the contained
216  // DataVectors, so no modification through the pointer cast here is
217  // possible. See the implementation of subitems in `Domain/Tags.hpp` for
218  // details.
219  sub_overlap_field[i].set_data_ref(
220  const_cast<DataVector*>(&parent_overlap_field[i])); // NOLINT
221  }
222  }
223  }
224 };
225 } // namespace detail
226 
227 template <typename VariablesTag, size_t Dim, typename OptionsGroup>
228 struct Subitems<
229  LinearSolver::Schwarz::Tags::Overlaps<VariablesTag, Dim, OptionsGroup>,
230  Requires<tt::is_a_v<Variables, typename VariablesTag::type>>>
231  : detail::OverlapSubitemsImpl<VariablesTag, Dim, OptionsGroup> {};
232 
233 } // namespace db
NoSuchType
Used to mark "no type" or "bad state" for metaprogramming.
Definition: NoSuchType.hpp:10
LinearSolver::Schwarz::OptionTags::SkipSubdomainSolverResets
Definition: Tags.hpp:43
std::string
Options.hpp
LinearSolver::Schwarz::Tags::MaxOverlap
Number of points a subdomain can overlap with its neighbor.
Definition: Tags.hpp:63
LinearSolver::Schwarz::Tags::IntrudingExtents
The number of points a neighbor's subdomain extends into the element.
Definition: Tags.hpp:126
Serialize.hpp
db::SimpleTag
Mark a struct as a simple tag by inheriting from this.
Definition: Tag.hpp:36
LinearSolver::Schwarz
Items related to the Schwarz linear solver.
Definition: CommunicateOverlapFields.hpp:37
LinearSolver::Schwarz::Tags::SubdomainSolverBase
The serial linear solver used to solve subdomain operators.
Definition: Tags.hpp:75
cstddef
LinearSolver::Schwarz::Tags::SkipSubdomainSolverResets
Skip resets of the subdomain solver.
Definition: Tags.hpp:98
array
LinearSolver::Schwarz::OptionTags::MaxOverlap
Definition: Tags.hpp:28
DataVector
Stores a collection of function values.
Definition: DataVector.hpp:46
LinearSolver::Schwarz::Tags::Weight
Weighting field for combining data from multiple overlapping subdomains.
Definition: Tags.hpp:145
LinearSolver::Schwarz::OptionTags::SubdomainSolver
Definition: Tags.hpp:36
db::BaseTag
Mark a (usually) empty struct as a base tag by inheriting from this.
Definition: Tag.hpp:69
LinearSolver::Schwarz::Tags::Overlaps
The Tag on the overlap region with each neighbor, i.e. on a region extruding from the central element...
Definition: Tags.hpp:115
Variables.hpp
LinearSolver::Schwarz::Tags::SummedIntrudingOverlapWeights
A diagnostic quantity to check that weights are conserved.
Definition: Tags.hpp:160
Scalar
Tensor< T, Symmetry<>, index_list<> > Scalar
Definition: TypeAliases.hpp:21
LinearSolver
Functionality for solving linear systems of equations.
Definition: ExplicitInverse.hpp:20
Gsl.hpp
Options::String
const char *const String
The string used in option structs.
Definition: Options.hpp:32
Tensor.hpp
db::Subitems
Definition: Subitems.hpp:32
LinearSolver::Schwarz::Tags::SubdomainSolver
The serial linear solver of type SolverType used to solve subdomain operators.
Definition: Tags.hpp:84
Requires
typename Requires_detail::requires_impl< B >::template_error_type_failed_to_meet_requirements_on_template_parameters Requires
Express requirements on the template parameters of a function or class, replaces std::enable_if_t
Definition: Requires.hpp:67
FixedHashMap
A hash table with a compile-time specified maximum size and ability to efficiently handle perfect has...
Definition: FixedHashMap.hpp:82
TMPL.hpp
db
Namespace for DataBox related things.
Definition: DataBox.hpp:44
gsl::not_null
Require a pointer to not be a nullptr
Definition: ReadSpecThirdOrderPiecewisePolynomial.hpp:13
LinearSolver::Schwarz::Tags::IntrudingOverlapWidths
The width in element-logical coordinates that a neighbor's subdomain extends into the element.
Definition: Tags.hpp:136
string