ElementCenteredSubdomainData.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <ostream>
8 #include <pup.h>
9 #include <string>
10 #include <tuple>
11 
14 #include "ParallelAlgorithms/LinearSolver/Schwarz/OverlapHelpers.hpp"
16 
18 
19 /*!
20  * \brief Data on an element-centered subdomain
21  *
22  * An element-centered subdomain consists of a central element and overlap
23  * regions with all neighboring elements. This class holds data on such a
24  * subdomain. It supports vector space operations (addition and scalar
25  * multiplication) and an inner product, which allows the use of this data type
26  * with linear solvers (see e.g. `LinearSolver::Serial::Gmres`).
27  */
28 template <size_t Dim, typename TagsList>
30  static constexpr size_t volume_dim = Dim;
31  using ElementData = Variables<TagsList>;
32  using OverlapData = ElementData;
33 
34  ElementCenteredSubdomainData() = default;
37  const ElementCenteredSubdomainData&) noexcept = default;
39  default;
41  ElementCenteredSubdomainData&&) noexcept = default;
42  ~ElementCenteredSubdomainData() noexcept = default;
43 
45  const size_t element_num_points) noexcept
46  : element_data{element_num_points} {}
47 
49  Variables<TagsList> local_element_data,
50  OverlapMap<Dim, Variables<TagsList>> local_overlap_data) noexcept
51  : element_data{std::move(local_element_data)},
52  overlap_data{std::move(local_overlap_data)} {}
53 
54  void pup(PUP::er& p) noexcept { // NOLINT
55  p | element_data;
56  p | overlap_data;
57  }
58 
59  template <typename RhsTagsList>
60  ElementCenteredSubdomainData& operator+=(
62  element_data += rhs.element_data;
63  for (auto& [overlap_id, data] : overlap_data) {
64  data += rhs.overlap_data.at(overlap_id);
65  }
66  return *this;
67  }
68 
69  template <typename RhsTagsList>
70  ElementCenteredSubdomainData& operator-=(
72  element_data -= rhs.element_data;
73  for (auto& [overlap_id, data] : overlap_data) {
74  data -= rhs.overlap_data.at(overlap_id);
75  }
76  return *this;
77  }
78 
79  ElementCenteredSubdomainData& operator*=(const double scalar) noexcept {
80  element_data *= scalar;
81  for (auto& [overlap_id, data] : overlap_data) {
82  data *= scalar;
83  // Silence unused-variable warning on GCC 7
84  (void)overlap_id;
85  }
86  return *this;
87  }
88 
89  ElementCenteredSubdomainData& operator/=(const double scalar) noexcept {
90  element_data /= scalar;
91  for (auto& [overlap_id, data] : overlap_data) {
92  data /= scalar;
93  // Silence unused-variable warning on GCC 7
94  (void)overlap_id;
95  }
96  return *this;
97  }
98 
99  ElementData element_data{};
100  OverlapMap<Dim, OverlapData> overlap_data{};
101 };
102 
103 template <size_t Dim, typename LhsTagsList, typename RhsTagsList>
104 decltype(auto) operator+(
105  ElementCenteredSubdomainData<Dim, LhsTagsList> lhs,
106  const ElementCenteredSubdomainData<Dim, RhsTagsList>& rhs) noexcept {
107  lhs += rhs;
108  return lhs;
109 }
110 
111 template <size_t Dim, typename LhsTagsList, typename RhsTagsList>
112 decltype(auto) operator-(
113  ElementCenteredSubdomainData<Dim, LhsTagsList> lhs,
114  const ElementCenteredSubdomainData<Dim, RhsTagsList>& rhs) noexcept {
115  lhs -= rhs;
116  return lhs;
117 }
118 
119 template <size_t Dim, typename TagsList>
120 decltype(auto) operator*(
121  const double scalar,
122  ElementCenteredSubdomainData<Dim, TagsList> data) noexcept {
123  data *= scalar;
124  return data;
125 }
126 
127 template <size_t Dim, typename TagsList>
128 decltype(auto) operator*(ElementCenteredSubdomainData<Dim, TagsList> data,
129  const double scalar) noexcept {
130  data *= scalar;
131  return data;
132 }
133 
134 template <size_t Dim, typename TagsList>
135 decltype(auto) operator/(ElementCenteredSubdomainData<Dim, TagsList> data,
136  const double scalar) noexcept {
137  data /= scalar;
138  return data;
139 }
140 
141 template <size_t Dim, typename TagsList>
142 std::ostream& operator<<(std::ostream& os,
143  const ElementCenteredSubdomainData<Dim, TagsList>&
144  subdomain_data) noexcept {
145  os << "Element data:\n"
146  << subdomain_data.element_data << "\nOverlap data:\n"
147  << subdomain_data.overlap_data;
148  return os;
149 }
150 
151 template <size_t Dim, typename TagsList>
152 bool operator==(
153  const ElementCenteredSubdomainData<Dim, TagsList>& lhs,
154  const ElementCenteredSubdomainData<Dim, TagsList>& rhs) noexcept {
155  return lhs.element_data == rhs.element_data and
156  lhs.overlap_data == rhs.overlap_data;
157 }
158 
159 template <size_t Dim, typename TagsList>
160 bool operator!=(
161  const ElementCenteredSubdomainData<Dim, TagsList>& lhs,
162  const ElementCenteredSubdomainData<Dim, TagsList>& rhs) noexcept {
163  return not(lhs == rhs);
164 }
165 
166 } // namespace LinearSolver::Schwarz
167 
169 
170 template <size_t Dim, typename LhsTagsList, typename RhsTagsList>
172  Schwarz::ElementCenteredSubdomainData<Dim, LhsTagsList>,
173  Schwarz::ElementCenteredSubdomainData<Dim, RhsTagsList>> {
174  static double apply(
177  rhs) noexcept {
178  double result = inner_product(lhs.element_data, rhs.element_data);
179  for (const auto& [overlap_id, lhs_data] : lhs.overlap_data) {
180  result += inner_product(lhs_data, rhs.overlap_data.at(overlap_id));
181  }
182  return result;
183  }
184 };
185 
186 } // namespace LinearSolver::InnerProductImpls
187 
188 namespace MakeWithValueImpls {
189 
190 template <size_t Dim, typename TagsListOut, typename TagsListIn>
192  LinearSolver::Schwarz::ElementCenteredSubdomainData<Dim, TagsListOut>,
194  using SubdomainDataIn =
196  using SubdomainDataOut =
199  apply(const SubdomainDataIn& input, const double value) noexcept {
200  SubdomainDataOut output{};
201  output.element_data =
202  make_with_value<typename SubdomainDataOut::ElementData>(
203  input.element_data, value);
204  for (const auto& [overlap_id, input_data] : input.overlap_data) {
205  output.overlap_data.emplace(
206  overlap_id, make_with_value<typename SubdomainDataOut::OverlapData>(
207  input_data, value));
208  }
209  return output;
210  }
211 };
212 
213 } // namespace MakeWithValueImpls
InnerProduct.hpp
std::rel_ops::operator!=
T operator!=(T... args)
MakeWithValueImpls::MakeWithValueImpl
Definition: MakeWithValue.hpp:64
LinearSolver::Schwarz::ElementCenteredSubdomainData
Data on an element-centered subdomain.
Definition: ElementCenteredSubdomainData.hpp:29
tuple
MakeWithValueImpls::MakeWithValueImpl::apply
static R apply(const T &input, const ValueType value) noexcept
The default implementation uses number_of_points and MakeWithSize.
Definition: MakeWithValue.hpp:67
LinearSolver::Schwarz
Items related to the Schwarz linear solver.
Definition: ElementCenteredSubdomainData.hpp:17
LinearSolver::inner_product
double inner_product(const Lhs &lhs, const Rhs &rhs) noexcept
The local part of the Euclidean inner product on the vector space w.r.t. which the addition and scala...
Definition: InnerProduct.hpp:71
SPECTRE_ALWAYS_INLINE
#define SPECTRE_ALWAYS_INLINE
Definition: ForceInline.hpp:16
std::ostream
cstddef
MakeWithValueImpls
Definition: DenseVector.hpp:61
MakeWithValue.hpp
LinearSolver::InnerProductImpls
Definition: InnerProduct.hpp:20
Variables.hpp
LinearSolver
Functionality for solving linear systems of equations.
Definition: Gmres.cpp:16
LinearSolver::InnerProductImpls::InnerProductImpl
The inner product between any types that have a dot product.
Definition: InnerProduct.hpp:24
FixedHashMap
A hash table with a compile-time specified maximum size and ability to efficiently handle perfect has...
Definition: FixedHashMap.hpp:81
ostream
std::data
T data(T... args)
string