IPPL (Independent Parallel Particle Layer)
IPPL
Loading...
Searching...
No Matches
LaplaceHelpers.h
Go to the documentation of this file.
1//
2// Helper functions used in PoissonCG.h
3//
4
5#ifndef IPPL_LAPLACE_HELPERS_H
6#define IPPL_LAPLACE_HELPERS_H
7namespace ippl {
8 namespace detail {
9 // Implements the poisson matrix acting on a d dimensional field
10 template <typename E>
11 struct meta_poisson : public Expression<meta_poisson<E>, sizeof(E)> {
12 constexpr static unsigned dim = E::dim;
13
14 KOKKOS_FUNCTION
15 meta_poisson(const E& u)
16 : u_m(u) {}
17
18 template <typename... Idx>
19 KOKKOS_INLINE_FUNCTION auto operator()(const Idx... args) const {
20 using index_type = std::tuple_element_t<0, std::tuple<Idx...>>;
21 using T = typename E::Mesh_t::value_type;
22 T res = 0;
23 index_type coords[dim] = {args...};
24 auto&& center = apply(u_m, coords);
25 for (unsigned d = 0; d < dim; d++) {
26 index_type coords[dim] = {args...};
27
28 coords[d] -= 1;
29 auto&& left = apply(u_m, coords);
30
31 coords[d] += 2;
32 auto&& right = apply(u_m, coords);
33 res += (2.0 * center - left - right);
34 }
35 return res;
36 }
37
38 private:
39 const E u_m;
40 };
41
42 template <typename E>
44 : public Expression<meta_lower_laplace<E>,
45 sizeof(E) + sizeof(typename E::Mesh_t::vector_type)
46 + 2 * sizeof(typename E::Layout_t::NDIndex_t)
47 + sizeof(unsigned)> {
48 constexpr static unsigned dim = E::dim;
49 using value_type = typename E::value_type;
50
51 KOKKOS_FUNCTION
52 meta_lower_laplace(const E& u, const typename E::Mesh_t::vector_type& hvector,
53 unsigned nghosts, const typename E::Layout_t::NDIndex_t& ldom,
54 const typename E::Layout_t::NDIndex_t& domain)
55 : u_m(u)
56 , hvector_m(hvector)
57 , nghosts_m(nghosts)
58 , ldom_m(ldom)
59 , domain_m(domain) {}
60
61 /*
62 * n-dimensional lower triangular Laplacian
63 */
64 template <typename... Idx>
65 KOKKOS_INLINE_FUNCTION auto operator()(const Idx... args) const {
66 using index_type = std::tuple_element_t<0, std::tuple<Idx...>>;
67 using T = typename E::Mesh_t::value_type;
68 T res = 0;
69
70 for (unsigned d = 0; d < dim; d++) {
71 index_type coords[dim] = {args...};
72 const int global_index = coords[d] + ldom_m[d].first() - nghosts_m;
73 const int size = domain_m.length()[d];
74 const bool not_left_boundary = (global_index != 0);
75 const bool right_boundary = (global_index == size - 1);
76
77 coords[d] -= 1;
78 auto&& left = apply(u_m, coords);
79
80 coords[d] += 2;
81 auto&& right = apply(u_m, coords);
82
83 // not_left_boundary and right_boundary are boolean values
84 // Because of periodic boundary conditions we need to add this boolean mask to
85 // obtain the lower triangular part of the Laplace Operator
86 res += hvector_m[d] * (not_left_boundary * left + right_boundary * right);
87 }
88 return res;
89 }
90
91 private:
92 using Mesh_t = typename E::Mesh_t;
93 using Layout_t = typename E::Layout_t;
95 using domain_type = typename Layout_t::NDIndex_t;
96 const E u_m;
98 const unsigned nghosts_m;
101 };
102
103 template <typename E>
105 : public Expression<meta_upper_laplace<E>,
106 sizeof(E) + sizeof(typename E::Mesh_t::vector_type)
107 + 2 * sizeof(typename E::Layout_t::NDIndex_t)
108 + sizeof(unsigned)> {
109 constexpr static unsigned dim = E::dim;
110 using value_type = typename E::value_type;
111
112 KOKKOS_FUNCTION
113 meta_upper_laplace(const E& u, const typename E::Mesh_t::vector_type& hvector,
114 unsigned nghosts, const typename E::Layout_t::NDIndex_t& ldom,
115 const typename E::Layout_t::NDIndex_t& domain)
116 : u_m(u)
117 , hvector_m(hvector)
118 , nghosts_m(nghosts)
119 , ldom_m(ldom)
120 , domain_m(domain) {}
121
122 /*
123 * n-dimensional upper triangular Laplacian
124 */
125 template <typename... Idx>
126 KOKKOS_INLINE_FUNCTION auto operator()(const Idx... args) const {
127 using index_type = std::tuple_element_t<0, std::tuple<Idx...>>;
128 using T = typename E::Mesh_t::value_type;
129 T res = 0;
130
131 for (unsigned d = 0; d < dim; d++) {
132 index_type coords[dim] = {args...};
133 const int global_index = coords[d] + ldom_m[d].first() - nghosts_m;
134 const int size = domain_m.length()[d];
135 const bool left_boundary = (global_index == 0);
136 const bool not_right_boundary = (global_index != size - 1);
137
138 coords[d] -= 1;
139 auto&& left = apply(u_m, coords);
140
141 coords[d] += 2;
142 auto&& right = apply(u_m, coords);
143
144 // left_boundary and not_right_boundary are boolean values
145 // Because of periodic boundary conditions we need to add this boolean mask to
146 // obtain the upper triangular part of the Laplace Operator
147 res += hvector_m[d] * (left_boundary * left + not_right_boundary * right);
148 }
149 return res;
150 }
151
152 private:
153 using Mesh_t = typename E::Mesh_t;
154 using Layout_t = typename E::Layout_t;
156 using domain_type = typename Layout_t::NDIndex_t;
157 const E u_m;
159 const unsigned nghosts_m;
162 };
163
164 template <typename E>
166 : public Expression<meta_upper_and_lower_laplace<E>,
167 sizeof(E) + sizeof(typename E::Mesh_t::vector_type)> {
168 constexpr static unsigned dim = E::dim;
169 using value_type = typename E::value_type;
170
171 KOKKOS_FUNCTION
172 meta_upper_and_lower_laplace(const E& u, const typename E::Mesh_t::vector_type& hvector)
173 : u_m(u)
174 , hvector_m(hvector) {}
175
176 /*
177 * n-dimensional upper+lower triangular Laplacian
178 */
179 template <typename... Idx>
180 KOKKOS_INLINE_FUNCTION auto operator()(const Idx... args) const {
181 using index_type = std::tuple_element_t<0, std::tuple<Idx...>>;
182 using T = typename E::Mesh_t::value_type;
183 T res = 0;
184 for (unsigned d = 0; d < dim; d++) {
185 index_type coords[dim] = {args...};
186 coords[d] -= 1;
187 auto&& left = apply(u_m, coords);
188 coords[d] += 2;
189 auto&& right = apply(u_m, coords);
190 res += hvector_m[d] * (left + right);
191 }
192 return res;
193 }
194
195 private:
196 using vector_type = typename E::Mesh_t::vector_type;
197 const E u_m;
199 };
200 } // namespace detail
201
206 template <typename Field>
208 constexpr unsigned Dim = Field::dim;
209
210 u.fillHalo();
211 BConds<Field, Dim>& bcField = u.getFieldBC();
212 bcField.apply(u);
213
215 }
216
221 template <typename Field>
223 constexpr unsigned Dim = Field::dim;
224
225 u.fillHalo();
226 BConds<Field, Dim>& bcField = u.getFieldBC();
227 bcField.apply(u);
228
229 return lower_laplace_no_comm(u);
230 }
231
236 template <typename Field>
238 constexpr unsigned Dim = Field::dim;
239
240 using mesh_type = typename Field::Mesh_t;
241 mesh_type& mesh = u.get_mesh();
242 typename mesh_type::vector_type hvector(0);
243 for (unsigned d = 0; d < Dim; d++) {
244 hvector[d] = 1.0 / Kokkos::pow(mesh.getMeshSpacing(d), 2);
245 }
246 const auto& layout = u.getLayout();
247 unsigned nghosts = u.getNghost();
248 const auto& ldom = layout.getLocalNDIndex();
249 const auto& domain = layout.getDomain();
250 return detail::meta_lower_laplace<Field>(u, hvector, nghosts, ldom, domain);
251 }
252
257 template <typename Field>
259 constexpr unsigned Dim = Field::dim;
260
261 u.fillHalo();
262 BConds<Field, Dim>& bcField = u.getFieldBC();
263 bcField.apply(u);
264
265 return upper_laplace_no_comm(u);
266 }
267
272 template <typename Field>
274 constexpr unsigned Dim = Field::dim;
275
276 using mesh_type = typename Field::Mesh_t;
277 mesh_type& mesh = u.get_mesh();
278 typename mesh_type::vector_type hvector(0);
279 for (unsigned d = 0; d < Dim; d++) {
280 hvector[d] = 1.0 / Kokkos::pow(mesh.getMeshSpacing(d), 2);
281 }
282 const auto& layout = u.getLayout();
283 unsigned nghosts = u.getNghost();
284 const auto& ldom = layout.getLocalNDIndex();
285 const auto& domain = layout.getDomain();
286 return detail::meta_upper_laplace<Field>(u, hvector, nghosts, ldom, domain);
287 }
288
293 template <typename Field>
295 constexpr unsigned Dim = Field::dim;
296
297 u.fillHalo();
298 BConds<Field, Dim>& bcField = u.getFieldBC();
299 bcField.apply(u);
300
302 }
303
308 template <typename Field>
310 constexpr unsigned Dim = Field::dim;
311
312 using mesh_type = typename Field::Mesh_t;
313 mesh_type& mesh = u.get_mesh();
314 typename mesh_type::vector_type hvector(0);
315 for (unsigned d = 0; d < Dim; d++) {
316 hvector[d] = 1.0 / Kokkos::pow(mesh.getMeshSpacing(d), 2);
317 }
319 }
320
327
328 template <typename Field>
330 constexpr unsigned Dim = Field::dim;
331 using mesh_type = typename Field::Mesh_t;
332 mesh_type& mesh = u.get_mesh();
333 double sum = 0.0;
334 double factor = 1.0;
335 typename mesh_type::vector_type hvector(0);
336 for (unsigned d = 0; d < Dim; ++d) {
337 hvector[d] = Kokkos::pow(mesh.getMeshSpacing(d), 2);
338 sum += hvector[d] * Kokkos::pow(mesh.getMeshSpacing((d + 1) % Dim), 2);
339 factor *= hvector[d];
340 }
341
342 return 0.5 * (factor / sum);
343 }
344
345 template <typename Field>
347 constexpr unsigned Dim = Field::dim;
348 using mesh_type = typename Field::Mesh_t;
349 mesh_type& mesh = u.get_mesh();
350 double sum = 0.0;
351 for (unsigned d = 0; d < Dim; ++d) {
352 sum += 1 / (Kokkos::pow(mesh.getMeshSpacing(d), 2));
353 }
354
355 // u = - 2.0 * sum * u;
356 return -2.0 * sum;
357 }
358
359 template <typename Field>
360 void mult(Field& u, const double c) {
361 using view_type = typename Field::view_type;
362
363 view_type view = u.getView();
364
365 Kokkos::parallel_for(
366 "Field_mult_const", u.getFieldRangePolicy(),
367 KOKKOS_LAMBDA(int i, int j, int k) { view(i, j, k) *= c; });
368 return;
369 }
370} // namespace ippl
371#endif // IPPL_LAPLACE_HELPERS_H
typename ippl::detail::ViewType< ippl::Vector< double, Dim >, 1 >::view_type view_type
constexpr unsigned Dim
Definition Archive.h:20
KOKKOS_INLINE_FUNCTION constexpr decltype(auto) apply(const View &view, const Coords &coords)
detail::meta_poisson< Field > poisson(Field &u)
detail::meta_upper_laplace< Field > upper_laplace(Field &u)
detail::meta_upper_and_lower_laplace< Field > upper_and_lower_laplace_no_comm(Field &u)
detail::meta_lower_laplace< Field > lower_laplace(Field &u)
double negative_inverse_diagonal_laplace(Field &u)
detail::meta_upper_laplace< Field > upper_laplace_no_comm(Field &u)
double diagonal_laplace(Field &u)
void mult(Field &u, const double c)
detail::meta_lower_laplace< Field > lower_laplace_no_comm(Field &u)
detail::meta_upper_and_lower_laplace< Field > upper_and_lower_laplace(Field &u)
Layout_t & getLayout() const
Definition BareField.h:134
int getNghost() const
Definition BareField.h:125
view_type & getView()
Definition BareField.h:169
policy_type< execution_space, PolicyArgs... > getFieldRangePolicy(const int nghost=0) const
Definition BareField.h:183
void apply(Field &field)
Definition BConds.hpp:29
KOKKOS_INLINE_FUNCTION Mesh_t & get_mesh() const
Definition Field.h:64
BConds_t & getFieldBC()
Definition Field.h:78
Mesh< double, Dim >::vector_type vector_type
static constexpr unsigned dim
KOKKOS_INLINE_FUNCTION auto operator()(const Idx... args) const
KOKKOS_FUNCTION meta_poisson(const E &u)
static constexpr unsigned dim
typename Mesh_t::vector_type vector_type
typename Layout_t::NDIndex_t domain_type
typename E::value_type value_type
KOKKOS_INLINE_FUNCTION auto operator()(const Idx... args) const
KOKKOS_FUNCTION meta_lower_laplace(const E &u, const typename E::Mesh_t::vector_type &hvector, unsigned nghosts, const typename E::Layout_t::NDIndex_t &ldom, const typename E::Layout_t::NDIndex_t &domain)
KOKKOS_INLINE_FUNCTION auto operator()(const Idx... args) const
typename E::value_type value_type
static constexpr unsigned dim
KOKKOS_FUNCTION meta_upper_laplace(const E &u, const typename E::Mesh_t::vector_type &hvector, unsigned nghosts, const typename E::Layout_t::NDIndex_t &ldom, const typename E::Layout_t::NDIndex_t &domain)
typename Layout_t::NDIndex_t domain_type
typename Mesh_t::vector_type vector_type
KOKKOS_INLINE_FUNCTION auto operator()(const Idx... args) const
KOKKOS_FUNCTION meta_upper_and_lower_laplace(const E &u, const typename E::Mesh_t::vector_type &hvector)
typename E::Mesh_t::vector_type vector_type