deal.II version GIT relicensing-2863-gb18dd3416c 2025-03-19 12:40:00+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
portable_hanging_nodes_internal.h
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 2021 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_portable_hanging_nodes_internal_h
16#define dealii_portable_hanging_nodes_internal_h
17
18#include <deal.II/base/config.h>
19
21
22#include <Kokkos_Core.hpp>
23
24
26namespace Portable
27{
28 namespace internal
29 {
30 //------------------------------------------------------------------------//
31 // Functions for resolving the hanging node constraints on the GPU //
32 //------------------------------------------------------------------------//
33 template <unsigned int size>
34 DEAL_II_HOST_DEVICE inline unsigned int
35 index2(unsigned int i, unsigned int j)
36 {
37 return i + size * j;
38 }
39
40
41
42 template <unsigned int size>
43 DEAL_II_HOST_DEVICE inline unsigned int
44 index3(unsigned int i, unsigned int j, unsigned int k)
45 {
46 return i + size * j + size * size * k;
47 }
48
49
50
51 template <unsigned int fe_degree, unsigned int direction>
52 DEAL_II_HOST_DEVICE inline bool
54 const ::internal::MatrixFreeFunctions::ConstraintKinds
55 &constraint_mask,
56 const unsigned int x_idx,
57 const unsigned int y_idx)
58 {
59 return ((direction == 0) &&
60 (((constraint_mask & ::internal::MatrixFreeFunctions::
61 ConstraintKinds::subcell_y) !=
63 unconstrained) ?
64 (y_idx == 0) :
65 (y_idx == fe_degree))) ||
66 ((direction == 1) &&
67 (((constraint_mask & ::internal::MatrixFreeFunctions::
70 unconstrained) ?
71 (x_idx == 0) :
72 (x_idx == fe_degree)));
73 }
74
75 template <unsigned int fe_degree, unsigned int direction>
76 DEAL_II_HOST_DEVICE inline bool
78 const ::internal::MatrixFreeFunctions::ConstraintKinds
79 &constraint_mask,
80 const unsigned int x_idx,
81 const unsigned int y_idx,
82 const unsigned int z_idx,
83 const ::internal::MatrixFreeFunctions::ConstraintKinds face1_type,
84 const ::internal::MatrixFreeFunctions::ConstraintKinds face2_type,
85 const ::internal::MatrixFreeFunctions::ConstraintKinds face1,
86 const ::internal::MatrixFreeFunctions::ConstraintKinds face2,
87 const ::internal::MatrixFreeFunctions::ConstraintKinds edge)
88 {
89 const unsigned int face1_idx = (direction == 0) ? y_idx :
90 (direction == 1) ? z_idx :
91 x_idx;
92 const unsigned int face2_idx = (direction == 0) ? z_idx :
93 (direction == 1) ? x_idx :
94 y_idx;
95
96 const bool on_face1 = ((constraint_mask & face1_type) !=
97 ::internal::MatrixFreeFunctions::
98 ConstraintKinds::unconstrained) ?
99 (face1_idx == 0) :
100 (face1_idx == fe_degree);
101 const bool on_face2 = ((constraint_mask & face2_type) !=
102 ::internal::MatrixFreeFunctions::
103 ConstraintKinds::unconstrained) ?
104 (face2_idx == 0) :
105 (face2_idx == fe_degree);
106 return (
107 (((constraint_mask & face1) != ::internal::MatrixFreeFunctions::
108 ConstraintKinds::unconstrained) &&
109 on_face1) ||
110 (((constraint_mask & face2) != ::internal::MatrixFreeFunctions::
111 ConstraintKinds::unconstrained) &&
112 on_face2) ||
113 (((constraint_mask & edge) != ::internal::MatrixFreeFunctions::
114 ConstraintKinds::unconstrained) &&
115 on_face1 && on_face2));
116 }
117
118
119
120 template <unsigned int fe_degree,
121 unsigned int direction,
122 bool transpose,
123 typename Number,
124 typename ViewType>
125 DEAL_II_HOST_DEVICE inline void
127 const Kokkos::TeamPolicy<
128 MemorySpace::Default::kokkos_space::execution_space>::member_type
129 &team_member,
130 Kokkos::View<Number *, MemorySpace::Default::kokkos_space>
131 constraint_weights,
132 const ::internal::MatrixFreeFunctions::ConstraintKinds
133 &constraint_mask,
134 ViewType values)
135 {
136 constexpr unsigned int n_q_points_1d = fe_degree + 1;
137 constexpr unsigned int n_q_points = Utilities::pow(n_q_points_1d, 2);
138
139 // Flag is true if dof is constrained for the given direction and the
140 // given face.
141 const bool constrained_face =
142 (constraint_mask &
143 (((direction == 0) ?
147 ((direction == 1) ?
150 unconstrained))) !=
152
153 Number tmp[n_q_points];
154 Kokkos::parallel_for(
155 Kokkos::TeamThreadRange(team_member, n_q_points),
156 [&](const int &q_point) {
157 const unsigned int x_idx = q_point % n_q_points_1d;
158 const unsigned int y_idx = q_point / n_q_points_1d;
159
160 const auto this_type =
161 (direction == 0) ?
163 subcell_x :
165
166 const unsigned int interp_idx = (direction == 0) ? x_idx : y_idx;
167 tmp[q_point] = 0;
168
169 // Flag is true if for the given direction, the dof is constrained
170 // with the right type and is on the correct side (left (= 0) or right
171 // (= fe_degree))
172 const bool constrained_dof =
173 is_constrained_dof_2d<fe_degree, direction>(constraint_mask,
174 x_idx,
175 y_idx);
176
177 if (constrained_face && constrained_dof)
178 {
179 const bool type = (constraint_mask & this_type) !=
180 ::internal::MatrixFreeFunctions::
181 ConstraintKinds::unconstrained;
182
183 if (type)
184 {
185 for (unsigned int i = 0; i <= fe_degree; ++i)
186 {
187 const unsigned int real_idx =
188 (direction == 0) ? index2<n_q_points_1d>(i, y_idx) :
189 index2<n_q_points_1d>(x_idx, i);
190
191 const Number w =
192 transpose ?
193 constraint_weights[i * n_q_points_1d + interp_idx] :
194 constraint_weights[interp_idx * n_q_points_1d + i];
195 tmp[q_point] += w * values[real_idx];
196 }
197 }
198 else
199 {
200 for (unsigned int i = 0; i <= fe_degree; ++i)
201 {
202 const unsigned int real_idx =
203 (direction == 0) ? index2<n_q_points_1d>(i, y_idx) :
204 index2<n_q_points_1d>(x_idx, i);
205
206 const Number w =
207 transpose ?
208 constraint_weights[(fe_degree - i) * n_q_points_1d +
209 fe_degree - interp_idx] :
210 constraint_weights[(fe_degree - interp_idx) *
211 n_q_points_1d +
212 fe_degree - i];
213 tmp[q_point] += w * values[real_idx];
214 }
215 }
216 }
217 });
218
219 // The synchronization is done for all the threads in one team with
220 // each team being assigned to one element.
221 team_member.team_barrier();
222 Kokkos::parallel_for(Kokkos::TeamThreadRange(team_member, n_q_points),
223 [&](const int &q_point) {
224 const unsigned int x_idx = q_point % n_q_points_1d;
225 const unsigned int y_idx = q_point / n_q_points_1d;
226 const bool constrained_dof =
227 is_constrained_dof_2d<fe_degree, direction>(
228 constraint_mask, x_idx, y_idx);
229 if (constrained_face && constrained_dof)
230 values[index2<fe_degree + 1>(x_idx, y_idx)] =
231 tmp[q_point];
232 });
233
234 team_member.team_barrier();
235 }
236
237
238
239 template <unsigned int fe_degree,
240 unsigned int direction,
241 bool transpose,
242 typename Number,
243 typename ViewType>
244 DEAL_II_HOST_DEVICE inline void
246 const Kokkos::TeamPolicy<
247 MemorySpace::Default::kokkos_space::execution_space>::member_type
248 &team_member,
249 Kokkos::View<Number *, MemorySpace::Default::kokkos_space>
250 constraint_weights,
251 const ::internal::MatrixFreeFunctions::ConstraintKinds
252 constraint_mask,
253 ViewType values)
254 {
255 constexpr unsigned int n_q_points_1d = fe_degree + 1;
256 constexpr unsigned int n_q_points = Utilities::pow(n_q_points_1d, 3);
257
258 const auto this_type =
259 (direction == 0) ?
261 (direction == 1) ?
264 const auto face1_type =
265 (direction == 0) ?
267 (direction == 1) ?
270 const auto face2_type =
271 (direction == 0) ?
273 (direction == 1) ?
276
277 // If computing in x-direction, need to match against face_y or
278 // face_z
279 const auto face1 =
280 (direction == 0) ?
282 (direction == 1) ?
285 const auto face2 =
286 (direction == 0) ?
288 (direction == 1) ?
291 const auto edge =
292 (direction == 0) ?
294 (direction == 1) ?
297 const auto constrained_face = constraint_mask & (face1 | face2 | edge);
298
299 Number tmp[n_q_points];
300 Kokkos::parallel_for(
301 Kokkos::TeamThreadRange(team_member, n_q_points),
302 [&](const int &q_point) {
303 const unsigned int x_idx = q_point % n_q_points_1d;
304 const unsigned int y_idx = (q_point / n_q_points_1d) % n_q_points_1d;
305 const unsigned int z_idx = q_point / (n_q_points_1d * n_q_points_1d);
306
307 const unsigned int interp_idx = (direction == 0) ? x_idx :
308 (direction == 1) ? y_idx :
309 z_idx;
310 const bool constrained_dof =
311 is_constrained_dof_3d<fe_degree, direction>(constraint_mask,
312 x_idx,
313 y_idx,
314 z_idx,
315 face1_type,
316 face2_type,
317 face1,
318 face2,
319 edge);
320 tmp[q_point] = 0;
321 if ((constrained_face != ::internal::MatrixFreeFunctions::
322 ConstraintKinds::unconstrained) &&
323 constrained_dof)
324 {
325 const bool type = (constraint_mask & this_type) !=
326 ::internal::MatrixFreeFunctions::
327 ConstraintKinds::unconstrained;
328 if (type)
329 {
330 for (unsigned int i = 0; i <= fe_degree; ++i)
331 {
332 const unsigned int real_idx =
333 (direction == 0) ?
334 index3<fe_degree + 1>(i, y_idx, z_idx) :
335 (direction == 1) ?
336 index3<fe_degree + 1>(x_idx, i, z_idx) :
337 index3<fe_degree + 1>(x_idx, y_idx, i);
338
339 const Number w =
340 transpose ?
341 constraint_weights[i * n_q_points_1d + interp_idx] :
342 constraint_weights[interp_idx * n_q_points_1d + i];
343 tmp[q_point] += w * values[real_idx];
344 }
345 }
346 else
347 {
348 for (unsigned int i = 0; i <= fe_degree; ++i)
349 {
350 const unsigned int real_idx =
351 (direction == 0) ?
352 index3<n_q_points_1d>(i, y_idx, z_idx) :
353 (direction == 1) ?
354 index3<n_q_points_1d>(x_idx, i, z_idx) :
355 index3<n_q_points_1d>(x_idx, y_idx, i);
356
357 const Number w =
358 transpose ?
359 constraint_weights[(fe_degree - i) * n_q_points_1d +
360 fe_degree - interp_idx] :
361 constraint_weights[(fe_degree - interp_idx) *
362 n_q_points_1d +
363 fe_degree - i];
364 tmp[q_point] += w * values[real_idx];
365 }
366 }
367 }
368 });
369
370 // The synchronization is done for all the threads in one team with
371 // each team being assigned to one element.
372 team_member.team_barrier();
373
374 Kokkos::parallel_for(
375 Kokkos::TeamThreadRange(team_member, n_q_points),
376 [&](const int &q_point) {
377 const unsigned int x_idx = q_point % n_q_points_1d;
378 const unsigned int y_idx = (q_point / n_q_points_1d) % n_q_points_1d;
379 const unsigned int z_idx = q_point / (n_q_points_1d * n_q_points_1d);
380 const bool constrained_dof =
381 is_constrained_dof_3d<fe_degree, direction>(constraint_mask,
382 x_idx,
383 y_idx,
384 z_idx,
385 face1_type,
386 face2_type,
387 face1,
388 face2,
389 edge);
390 if ((constrained_face != ::internal::MatrixFreeFunctions::
391 ConstraintKinds::unconstrained) &&
392 constrained_dof)
393 values[index3<fe_degree + 1>(x_idx, y_idx, z_idx)] = tmp[q_point];
394 });
395
396 team_member.team_barrier();
397 }
398
399
400
408 template <int dim,
409 int fe_degree,
410 bool transpose,
411 typename Number,
412 typename ViewType>
415 const Kokkos::TeamPolicy<
416 MemorySpace::Default::kokkos_space::execution_space>::member_type
417 &team_member,
418 Kokkos::View<Number *, MemorySpace::Default::kokkos_space>
419 constraint_weights,
420 const ::internal::MatrixFreeFunctions::ConstraintKinds
421 constraint_mask,
422 ViewType values)
423 {
424 if constexpr (dim == 2)
425 {
426 interpolate_boundary_2d<fe_degree, 0, transpose>(team_member,
427 constraint_weights,
428 constraint_mask,
429 values);
430
431 interpolate_boundary_2d<fe_degree, 1, transpose>(team_member,
432 constraint_weights,
433 constraint_mask,
434 values);
435 }
436 else if constexpr (dim == 3)
437 {
438 // Interpolate y and z faces (x-direction)
439 interpolate_boundary_3d<fe_degree, 0, transpose>(team_member,
440 constraint_weights,
441 constraint_mask,
442 values);
443 // Interpolate x and z faces (y-direction)
444 interpolate_boundary_3d<fe_degree, 1, transpose>(team_member,
445 constraint_weights,
446 constraint_mask,
447 values);
448 // Interpolate x and y faces (z-direction)
449 interpolate_boundary_3d<fe_degree, 2, transpose>(team_member,
450 constraint_weights,
451 constraint_mask,
452 values);
453 }
454 }
455 } // namespace internal
456} // namespace Portable
457
459#endif
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:40
#define DEAL_II_HOST_DEVICE
Definition config.h:169
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:41
DerivativeForm< 1, spacedim, dim, Number > transpose(const DerivativeForm< 1, dim, spacedim, Number > &DF)
std::size_t size
Definition mpi.cc:745
bool is_constrained_dof_2d(const ::internal::MatrixFreeFunctions::ConstraintKinds &constraint_mask, const unsigned int x_idx, const unsigned int y_idx)
void interpolate_boundary_3d(const Kokkos::TeamPolicy< MemorySpace::Default::kokkos_space::execution_space >::member_type &team_member, Kokkos::View< Number *, MemorySpace::Default::kokkos_space > constraint_weights, const ::internal::MatrixFreeFunctions::ConstraintKinds constraint_mask, ViewType values)
bool is_constrained_dof_3d(const ::internal::MatrixFreeFunctions::ConstraintKinds &constraint_mask, const unsigned int x_idx, const unsigned int y_idx, const unsigned int z_idx, const ::internal::MatrixFreeFunctions::ConstraintKinds face1_type, const ::internal::MatrixFreeFunctions::ConstraintKinds face2_type, const ::internal::MatrixFreeFunctions::ConstraintKinds face1, const ::internal::MatrixFreeFunctions::ConstraintKinds face2, const ::internal::MatrixFreeFunctions::ConstraintKinds edge)
unsigned int index3(unsigned int i, unsigned int j, unsigned int k)
void resolve_hanging_nodes(const Kokkos::TeamPolicy< MemorySpace::Default::kokkos_space::execution_space >::member_type &team_member, Kokkos::View< Number *, MemorySpace::Default::kokkos_space > constraint_weights, const ::internal::MatrixFreeFunctions::ConstraintKinds constraint_mask, ViewType values)
unsigned int index2(unsigned int i, unsigned int j)
void interpolate_boundary_2d(const Kokkos::TeamPolicy< MemorySpace::Default::kokkos_space::execution_space >::member_type &team_member, Kokkos::View< Number *, MemorySpace::Default::kokkos_space > constraint_weights, const ::internal::MatrixFreeFunctions::ConstraintKinds &constraint_mask, ViewType values)
constexpr T pow(const T base, const int iexp)
Definition utilities.h:967