16 #ifndef dealii_cuda_hanging_nodes_internal_h
17 #define dealii_cuda_hanging_nodes_internal_h
21 #ifdef DEAL_II_COMPILER_CUDA_AWARE
59 template <
typename CellIterator>
62 std::vector<types::global_dof_index> & dof_indices,
63 const CellIterator & cell,
64 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner,
65 unsigned int & mask)
const;
79 unsigned int n_dofs_1d,
80 std::vector<types::global_dof_index> &dofs)
const;
85 unsigned int n_dofs_1d)
const;
97 std::vector<std::vector<std::pair<cell_iterator, unsigned int>>>
107 # define DEAL_II_MAX_ELEM_DEGREE 10
149 std::vector<unsigned int> mapping =
150 FETools::lexicographic_to_hierarchic_numbering<1>(fe_degree);
156 mapped_matrix(i, j) = interpolation_matrix(mapping[i], mapping[j]);
158 cudaError_t error_code =
160 &mapped_matrix[0][0],
171 unsigned int fe_degree,
173 const std::vector<unsigned int> &lexicographic_mapping)
174 : n_raw_lines(dof_handler.get_triangulation().n_raw_lines())
175 , line_to_cells(dim == 3 ? n_raw_lines : 0)
176 , lexicographic_mapping(lexicographic_mapping)
177 , fe_degree(fe_degree)
178 , dof_handler(dof_handler)
183 internal::setup_constraint_weigths<dim>(
fe_degree);
205 const unsigned int line_to_children[12][2] = {{0, 2},
218 std::vector<std::vector<std::pair<cell_iterator, unsigned int>>>
219 line_to_inactive_cells(n_raw_lines);
222 for (
const auto &cell : dof_handler.cell_iterators())
224 for (
unsigned int line = 0; line < GeometryInfo<3>::lines_per_cell;
227 const unsigned int line_idx = cell->line(line)->index();
228 if (cell->is_active())
229 line_to_cells[line_idx].push_back(std::make_pair(cell, line));
231 line_to_inactive_cells[line_idx].push_back(
232 std::make_pair(cell, line));
239 for (
unsigned int line_idx = 0; line_idx < n_raw_lines; ++line_idx)
241 if ((line_to_cells[line_idx].size() > 0) &&
242 line_to_inactive_cells[line_idx].size() > 0)
247 line_to_inactive_cells[line_idx][0].first;
248 const unsigned int neighbor_line =
249 line_to_inactive_cells[line_idx][0].second;
251 for (
unsigned int c = 0; c < 2; ++c)
254 inactive_cell->child(line_to_children[neighbor_line][c]);
255 const unsigned int child_line_idx =
256 child->line(neighbor_line)->index();
259 for (
const auto cl : line_to_cells[line_idx])
260 line_to_cells[child_line_idx].push_back(cl);
269 template <
typename CellIterator>
272 std::vector<types::global_dof_index> & dof_indices,
273 const CellIterator & cell,
274 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner,
275 unsigned int & mask)
const
278 const unsigned int n_dofs_1d = fe_degree + 1;
279 const unsigned int dofs_per_face =
282 std::vector<types::global_dof_index> neighbor_dofs(dofs_per_face);
284 const auto lex_face_mapping =
289 if ((!cell->at_boundary(face)) &&
290 (cell->neighbor(face)->has_children() ==
false))
295 if (neighbor->level() < cell->level())
297 const unsigned int neighbor_face =
298 cell->neighbor_face_no(face);
301 unsigned int subface = 0;
302 for (; subface < GeometryInfo<dim>::max_children_per_face;
304 if (neighbor->neighbor_child_on_subface(neighbor_face,
309 neighbor->face(neighbor_face)->get_dof_indices(neighbor_dofs);
313 for (
auto &index : neighbor_dofs)
339 unsigned int offset = (face % 2 == 1) ? fe_degree : 0;
341 for (
unsigned int i = 0; i < n_dofs_1d; ++i)
343 unsigned int idx = 0;
346 idx = n_dofs_1d * offset + i;
349 idx = n_dofs_1d * i + offset;
351 dof_indices[idx] = neighbor_dofs[lex_face_mapping[i]];
356 const bool transpose = !(cell->face_orientation(face));
360 if (cell->face_rotation(face))
362 if (cell->face_flip(face))
365 rotate_face(
rotate, n_dofs_1d, neighbor_dofs);
366 rotate_subface_index(
rotate, subface);
370 transpose_face(neighbor_dofs);
371 transpose_subface_index(subface);
380 if (subface % 2 == 0)
382 if (subface / 2 == 0)
391 if (subface % 2 == 0)
393 if (subface / 2 == 0)
402 if (subface % 2 == 0)
404 if (subface / 2 == 0)
409 unsigned int offset = (face % 2 == 1) ? fe_degree : 0;
411 for (
unsigned int i = 0; i < n_dofs_1d; ++i)
413 for (
unsigned int j = 0; j < n_dofs_1d; ++j)
415 unsigned int idx = 0;
419 idx = n_dofs_1d * n_dofs_1d * i +
420 n_dofs_1d * j + offset;
424 idx = n_dofs_1d * n_dofs_1d * j +
425 n_dofs_1d * offset + i;
429 idx = n_dofs_1d * n_dofs_1d * offset +
433 neighbor_dofs[lex_face_mapping[n_dofs_1d * i +
451 const unsigned int line_to_edge[12][4] = {
501 for (
unsigned int local_line = 0;
502 local_line < GeometryInfo<dim>::lines_per_cell;
506 if (!(mask & line_to_edge[local_line][0]))
509 const unsigned int line = cell->line(local_line)->index();
510 for (
const auto edge_neighbor : line_to_cells[line])
514 if (neighbor_cell->level() < cell->level())
516 const unsigned int local_line_neighbor =
517 edge_neighbor.second;
518 mask |= line_to_edge[local_line][1] |
519 line_to_edge[local_line][2];
521 bool flipped =
false;
522 if (cell->line(local_line)->vertex_index(0) ==
523 neighbor_cell->line(local_line_neighbor)
528 mask |= line_to_edge[local_line][3];
530 else if (cell->line(local_line)->vertex_index(1) ==
531 neighbor_cell->line(local_line_neighbor)
536 else if (cell->line(local_line)->vertex_index(1) ==
537 neighbor_cell->line(local_line_neighbor)
543 else if (cell->line(local_line)->vertex_index(0) ==
544 neighbor_cell->line(local_line_neighbor)
548 mask |= line_to_edge[local_line][3];
555 neighbor_dofs.resize(n_dofs_1d * n_dofs_1d *
557 neighbor_cell->get_dof_indices(neighbor_dofs);
561 for (
auto &index : neighbor_dofs)
564 for (
unsigned int i = 0; i < n_dofs_1d; ++i)
567 const unsigned int idx =
568 line_dof_idx(local_line, i, n_dofs_1d);
569 dof_indices[idx] = neighbor_dofs
570 [lexicographic_mapping[line_dof_idx(
572 flipped ? fe_degree - i : i,
590 unsigned int &subface_index)
const
592 const unsigned int rot_mapping[4] = {2, 0, 3, 1};
595 times = times < 0 ? times + 4 : times;
596 for (
int t = 0; t < times; ++t)
597 subface_index = rot_mapping[subface_index];
606 unsigned int n_dofs_1d,
607 std::vector<types::global_dof_index> &dofs)
const
609 const unsigned int rot_mapping[4] = {2, 0, 3, 1};
612 times = times < 0 ? times + 4 : times;
614 std::vector<types::global_dof_index>
copy(dofs.size());
615 for (
int t = 0; t < times; ++t)
620 for (
unsigned int i = 0; i < 4; ++i)
621 dofs[rot_mapping[i]] =
copy[i];
624 const unsigned int n_int = n_dofs_1d - 2;
625 unsigned int offset = 4;
626 for (
unsigned int i = 0; i < n_int; ++i)
629 dofs[offset + i] =
copy[offset + 2 * n_int + (n_int - 1 - i)];
631 dofs[offset + n_int + i] =
632 copy[offset + 3 * n_int + (n_int - 1 - i)];
634 dofs[offset + 2 * n_int + i] =
copy[offset + n_int + i];
636 dofs[offset + 3 * n_int + i] =
copy[offset + i];
642 for (
unsigned int i = 0; i < n_int; ++i)
643 for (
unsigned int j = 0; j < n_int; ++j)
644 dofs[offset + i * n_int + j] =
645 copy[offset + j * n_int + (n_int - 1 - i)];
655 unsigned int n_dofs_1d)
const
657 unsigned int x, y, z;
662 (local_line % 4 == 0) ? 0 : (local_line % 4 == 1) ? fe_degree : dof;
664 (local_line % 4 == 2) ? 0 : (local_line % 4 == 3) ? fe_degree : dof;
665 z = (local_line / 4) * fe_degree;
669 x = ((local_line - 8) % 2) * fe_degree;
670 y = ((local_line - 8) / 2) * fe_degree;
674 return n_dofs_1d * n_dofs_1d * z + n_dofs_1d * y + x;
682 std::vector<types::global_dof_index> &dofs)
const
684 const std::vector<types::global_dof_index>
copy(dofs);
691 const unsigned int n_int = fe_degree - 1;
692 unsigned int offset = 4;
693 for (
unsigned int i = 0; i < n_int; ++i)
696 dofs[offset + i] =
copy[offset + 2 * n_int + i];
698 dofs[offset + n_int + i] =
copy[offset + 3 * n_int + i];
700 dofs[offset + 2 * n_int + i] =
copy[offset + i];
702 dofs[offset + 3 * n_int + i] =
copy[offset + n_int + i];
707 for (
unsigned int i = 0; i < n_int; ++i)
708 for (
unsigned int j = 0; j < n_int; ++j)
709 dofs[offset + i * n_int + j] =
copy[offset + j * n_int + i];
720 else if (subface == 2)
731 template <
unsigned int size>
732 __device__
inline unsigned int
740 template <
unsigned int size>
741 __device__
inline unsigned int
742 index3(
unsigned int i,
unsigned int j,
unsigned int k)
744 return i + size * j + size * size * k;
749 template <
unsigned int fe_degree,
750 unsigned int direction,
753 __device__
inline void
757 const unsigned int x_idx = threadIdx.x % (fe_degree + 1);
758 const unsigned int y_idx = threadIdx.y;
760 const unsigned int this_type =
763 const unsigned int interp_idx = (direction == 0) ? x_idx : y_idx;
768 const bool constrained_face =
776 const bool constrained_dof =
779 (y_idx == fe_degree))) ||
782 (x_idx == fe_degree)));
784 if (constrained_face && constrained_dof)
786 const bool type = constraint_mask & this_type;
790 for (
unsigned int i = 0; i <= fe_degree; ++i)
792 const unsigned int real_idx =
793 (direction == 0) ? index2<fe_degree + 1>(i, y_idx) :
794 index2<fe_degree + 1>(x_idx, i);
803 t +=
w * values[real_idx];
808 for (
unsigned int i = 0; i <= fe_degree; ++i)
810 const unsigned int real_idx =
811 (direction == 0) ? index2<fe_degree + 1>(i, y_idx) :
812 index2<fe_degree + 1>(x_idx, i);
818 fe_degree - interp_idx] :
822 t +=
w * values[real_idx];
830 if (constrained_face && constrained_dof)
831 values[index2<fe_degree + 1>(x_idx, y_idx)] = t;
838 template <
unsigned int fe_degree,
839 unsigned int direction,
842 __device__
inline void
846 const unsigned int x_idx = threadIdx.x % (fe_degree + 1);
847 const unsigned int y_idx = threadIdx.y;
848 const unsigned int z_idx = threadIdx.z;
850 const unsigned int this_type =
854 const unsigned int face1_type =
858 const unsigned int face2_type =
877 const unsigned int constrained_face =
878 constraint_mask & (face1 | face2 | edge);
880 const unsigned int interp_idx =
881 (direction == 0) ? x_idx : (direction == 1) ? y_idx : z_idx;
882 const unsigned int face1_idx =
883 (direction == 0) ? y_idx : (direction == 1) ? z_idx : x_idx;
884 const unsigned int face2_idx =
885 (direction == 0) ? z_idx : (direction == 1) ? x_idx : y_idx;
888 const bool on_face1 = (constraint_mask & face1_type) ?
890 (face1_idx == fe_degree);
891 const bool on_face2 = (constraint_mask & face2_type) ?
893 (face2_idx == fe_degree);
894 const bool constrained_dof =
895 (((constraint_mask & face1) && on_face1) ||
896 ((constraint_mask & face2) && on_face2) ||
897 ((constraint_mask & edge) && on_face1 && on_face2));
899 if (constrained_face && constrained_dof)
901 const bool type = constraint_mask & this_type;
904 for (
unsigned int i = 0; i <= fe_degree; ++i)
906 const unsigned int real_idx =
908 index3<fe_degree + 1>(i, y_idx, z_idx) :
910 index3<fe_degree + 1>(x_idx, i, z_idx) :
911 index3<fe_degree + 1>(x_idx, y_idx, i);
920 t +=
w * values[real_idx];
925 for (
unsigned int i = 0; i <= fe_degree; ++i)
927 const unsigned int real_idx =
929 index3<fe_degree + 1>(i, y_idx, z_idx) :
931 index3<fe_degree + 1>(x_idx, i, z_idx) :
932 index3<fe_degree + 1>(x_idx, y_idx, i);
938 fe_degree - interp_idx] :
942 t +=
w * values[real_idx];
951 if (constrained_face && constrained_dof)
952 values[index3<fe_degree + 1>(x_idx, y_idx, z_idx)] = t;
968 template <
int dim,
int fe_degree,
bool transpose,
typename Number>
974 internal::interpolate_boundary_2d<fe_degree, 0, transpose>(
975 constraint_mask, values);
977 internal::interpolate_boundary_2d<fe_degree, 1, transpose>(
978 constraint_mask, values);
983 internal::interpolate_boundary_3d<fe_degree, 0, transpose>(
984 constraint_mask, values);
986 internal::interpolate_boundary_3d<fe_degree, 1, transpose>(
987 constraint_mask, values);
989 internal::interpolate_boundary_3d<fe_degree, 2, transpose>(
990 constraint_mask, values);