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],
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>>>
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)
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();
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)
314 index = partitioner->global_to_local(index);
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))
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] = {
459 internal::constr_type_y},
467 internal::constr_type_x},
471 internal::constr_type_y},
475 internal::constr_type_y},
479 internal::constr_type_x},
483 internal::constr_type_x},
491 internal::constr_type_z},
495 internal::constr_type_z},
499 internal::constr_type_z}};
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();
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)
562 index = partitioner->global_to_local(index);
564 for (
unsigned int i = 0; i < n_dofs_1d; ++i)
567 const unsigned int idx =
569 dof_indices[idx] = neighbor_dofs
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;
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;
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;
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) ?
891 const bool on_face2 = (constraint_mask & face2_type) ?
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);
void resolve_hanging_nodes(const unsigned int constraint_mask, Number *values)
__constant__ double constraint_weights[(DEAL_II_MAX_ELEM_DEGREE+1) *(DEAL_II_MAX_ELEM_DEGREE+1)]
void rotate_subface_index(int times, unsigned int &subface_index) const
void setup_constraint_weigths(unsigned int fe_degree)
void setup_line_to_cell()
typename DoFHandler< dim >::active_cell_iterator active_cell_iterator
constexpr unsigned int constr_edge_zx
constexpr unsigned int constr_edge_xy
void transpose_face(std::vector< types::global_dof_index > &dofs) const
#define DEAL_II_MAX_ELEM_DEGREE
constexpr unsigned int constr_face_x
void interpolate_boundary_3d(const unsigned int constraint_mask, Number *values)
constexpr unsigned int constr_type_z
constexpr unsigned int constr_type_x
HangingNodes(unsigned int fe_degree, const DoFHandler< dim > &dof_handler, const std::vector< unsigned int > &lexicographic_mapping)
const unsigned int n_raw_lines
const unsigned int fe_degree
#define AssertCuda(error_code)
unsigned int index2(unsigned int i, unsigned int j)
void setup_constraints(std::vector< types::global_dof_index > &dof_indices, const CellIterator &cell, const std::shared_ptr< const Utilities::MPI::Partitioner > &partitioner, unsigned int &mask) const
constexpr unsigned int constr_edge_yz
const DoFHandler< dim > & dof_handler
#define DEAL_II_NAMESPACE_CLOSE
std::vector< std::vector< std::pair< cell_iterator, unsigned int > > > line_to_cells
virtual void get_subface_interpolation_matrix(const FiniteElement< dim, spacedim > &source, const unsigned int subface, FullMatrix< double > &matrix) const override
void transpose_subface_index(unsigned int &subface) const
Tensor< 2, dim, Number > w(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
constexpr unsigned int constr_type_y
constexpr unsigned int constr_face_z
void swap(MemorySpaceData< Number, MemorySpace > &, MemorySpaceData< Number, MemorySpace > &)
const std::vector< unsigned int > & lexicographic_mapping
#define DEAL_II_NAMESPACE_OPEN
constexpr unsigned int constr_face_y
const unsigned int dofs_per_face
typename DoFHandler< dim >::cell_iterator cell_iterator
static ::ExceptionBase & ExcNotImplemented()
IteratorRange< cell_iterator > cell_iterators() const
void copy(const T *begin, const T *end, U *dest)
void interpolate_boundary_2d(const unsigned int constraint_mask, Number *values)
void rotate_face(int times, unsigned int n_dofs_1d, std::vector< types::global_dof_index > &dofs) const
unsigned int line_dof_idx(int local_line, unsigned int dof, unsigned int n_dofs_1d) const
unsigned int index3(unsigned int i, unsigned int j, unsigned int k)
static ::ExceptionBase & ExcInternalError()