16#ifndef dealii_face_setup_internal_h
17#define dealii_face_setup_internal_h
82 const ::Triangulation<dim> &triangulation,
83 const unsigned int mg_level,
84 const bool hold_all_faces_to_owned_cells,
85 const bool build_inner_faces,
86 std::vector<std::pair<unsigned int, unsigned int>> &cell_levels);
96 const ::Triangulation<dim> &triangulation,
97 const std::vector<std::pair<unsigned int, unsigned int>> &cell_levels,
108 const unsigned int face_no,
109 const typename ::Triangulation<dim>::cell_iterator &cell,
110 const unsigned int number_cell_interior,
111 const typename ::Triangulation<dim>::cell_iterator &neighbor,
112 const unsigned int number_cell_exterior,
113 const bool is_mixed_mesh);
143 template <
int vectorization_w
idth>
147 const std::vector<bool> &hard_vectorization_boundary,
148 std::vector<unsigned int> &face_partition_data,
159 : use_active_cells(true)
166 FaceSetup<dim>::initialize(
167 const ::Triangulation<dim> &triangulation,
168 const unsigned int mg_level,
169 const bool hold_all_faces_to_owned_cells,
170 const bool build_inner_faces,
171 std::vector<std::pair<unsigned int, unsigned int>> &cell_levels)
178 if (use_active_cells)
179 for (
const auto &cell_level : cell_levels)
181 typename ::Triangulation<dim>::cell_iterator dcell(
182 &triangulation, cell_level.first, cell_level.second);
190 at_processor_boundary.resize(cell_levels.size(),
false);
191 face_is_owned.resize(dim > 1 ? triangulation.n_raw_faces() :
192 triangulation.n_vertices(),
193 FaceCategory::locally_active_done_elsewhere);
197 std::map<types::subdomain_id, FaceIdentifier>
198 inner_faces_at_proc_boundary;
199 if (triangulation.locally_owned_subdomain() !=
203 triangulation.locally_owned_subdomain();
204 for (
unsigned int i = 0; i < cell_levels.size(); ++i)
206 if (i > 0 && cell_levels[i] == cell_levels[i - 1])
208 typename ::Triangulation<dim>::cell_iterator dcell(
209 &triangulation, cell_levels[i].first, cell_levels[i].second);
210 for (
const unsigned int f : dcell->face_indices())
212 if (dcell->at_boundary(f) && !dcell->has_periodic_neighbor(f))
214 typename ::Triangulation<dim>::cell_iterator neighbor =
215 dcell->neighbor_or_periodic_neighbor(f);
221 const CellId id_mine = dcell->id();
222 if (use_active_cells && neighbor->has_children())
223 for (
unsigned int c = 0;
224 c < (dcell->has_periodic_neighbor(f) ?
225 dcell->periodic_neighbor(f)
226 ->face(dcell->periodic_neighbor_face_no(f))
228 dcell->face(f)->n_children());
231 typename ::Triangulation<dim>::cell_iterator
233 dcell->at_boundary(f) ?
234 dcell->periodic_neighbor_child_on_subface(f, c) :
235 dcell->neighbor_child_on_subface(f, c);
237 neighbor_c->subdomain_id();
238 if (my_domain < neigh_domain)
239 inner_faces_at_proc_boundary[neigh_domain]
240 .n_hanging_faces_larger_subdomain++;
241 else if (my_domain > neigh_domain)
242 inner_faces_at_proc_boundary[neigh_domain]
243 .n_hanging_faces_smaller_subdomain++;
248 use_active_cells ? neighbor->subdomain_id() :
249 neighbor->level_subdomain_id();
250 if (neighbor->level() < dcell->level() &&
253 if (my_domain < neigh_domain)
254 inner_faces_at_proc_boundary[neigh_domain]
255 .n_hanging_faces_smaller_subdomain++;
256 else if (my_domain > neigh_domain)
257 inner_faces_at_proc_boundary[neigh_domain]
258 .n_hanging_faces_larger_subdomain++;
260 else if (neighbor->level() == dcell->level() &&
261 my_domain != neigh_domain)
267 const CellId id_neigh = neighbor->id();
268 if (my_domain < neigh_domain)
269 inner_faces_at_proc_boundary[neigh_domain]
270 .shared_faces.emplace_back(id_mine, id_neigh);
272 inner_faces_at_proc_boundary[neigh_domain]
273 .shared_faces.emplace_back(id_neigh, id_mine);
282 for (
auto &inner_face : inner_faces_at_proc_boundary)
284 Assert(inner_face.first != my_domain,
286 std::sort(inner_face.second.shared_faces.begin(),
287 inner_face.second.shared_faces.end());
288 inner_face.second.shared_faces.erase(
289 std::unique(inner_face.second.shared_faces.begin(),
290 inner_face.second.shared_faces.end()),
291 inner_face.second.shared_faces.end());
296# if defined(DEAL_II_WITH_MPI) && defined(DEBUG)
297 MPI_Comm comm = MPI_COMM_SELF;
298 if (const ::parallel::TriangulationBase<dim> *ptria =
299 dynamic_cast<const ::parallel::TriangulationBase<dim>
301 comm = ptria->get_mpi_communicator();
304 unsigned int mysize = inner_face.second.shared_faces.size();
307 int ierr = MPI_Sendrecv(&mysize,
316 600 + inner_face.first,
321 mysize = inner_face.second.n_hanging_faces_smaller_subdomain;
322 ierr = MPI_Sendrecv(&mysize,
331 700 + inner_face.first,
336 mysize = inner_face.second.n_hanging_faces_larger_subdomain;
337 ierr = MPI_Sendrecv(&mysize,
346 800 + inner_face.first,
368 std::vector<std::tuple<CellId, CellId, unsigned int>> other_range(
369 inner_face.second.shared_faces.size());
370 for (
unsigned int i = 0; i < other_range.size(); ++i)
372 std::make_tuple(inner_face.second.shared_faces[i].second,
373 inner_face.second.shared_faces[i].first,
375 std::sort(other_range.begin(), other_range.end());
383 unsigned int n_faces_lower_proc = 0, n_faces_higher_proc = 0;
384 std::vector<signed char> assignment(other_range.size(), 0);
385 if (inner_face.second.shared_faces.size() > 0)
389 unsigned int count = 0;
390 for (
unsigned int i = 1;
391 i < inner_face.second.shared_faces.size();
393 if (inner_face.second.shared_faces[i].first ==
394 inner_face.second.shared_faces[i - 1 - count].first)
401 for (
unsigned int k = 0; k <= count; ++k)
402 assignment[i - 1 - k] = 1;
403 n_faces_higher_proc += count + 1;
413 for (
unsigned int i = 1; i < other_range.size(); ++i)
414 if (std::get<0>(other_range[i]) ==
415 std::get<0>(other_range[i - 1 - count]))
422 for (
unsigned int k = 0; k <= count; ++k)
425 .shared_faces[std::get<2>(
429 .shared_faces[std::get<2>(
430 other_range[i - 1 - k])]
435 if (assignment[std::get<2>(
436 other_range[i - 1 - k])] == 0)
438 assignment[std::get<2>(
439 other_range[i - 1 - k])] = -1;
440 ++n_faces_lower_proc;
454 n_faces_lower_proc +=
455 inner_face.second.n_hanging_faces_smaller_subdomain;
456 n_faces_higher_proc +=
457 inner_face.second.n_hanging_faces_larger_subdomain;
458 const unsigned int n_total_faces_at_proc_boundary =
459 (inner_face.second.shared_faces.size() +
460 inner_face.second.n_hanging_faces_smaller_subdomain +
461 inner_face.second.n_hanging_faces_larger_subdomain);
462 unsigned int split_index = n_total_faces_at_proc_boundary / 2;
463 if (split_index < n_faces_lower_proc)
465 else if (split_index <
466 n_total_faces_at_proc_boundary - n_faces_higher_proc)
467 split_index -= n_faces_lower_proc;
469 split_index = n_total_faces_at_proc_boundary -
470 n_faces_higher_proc - n_faces_lower_proc;
473# if defined(DEAL_II_WITH_MPI) && defined(DEBUG)
474 ierr = MPI_Sendrecv(&split_index,
483 900 + inner_face.first,
488 ierr = MPI_Sendrecv(&n_faces_lower_proc,
497 1000 + inner_face.first,
502 ierr = MPI_Sendrecv(&n_faces_higher_proc,
511 1100 + inner_face.first,
519 std::vector<std::pair<CellId, CellId>> owned_faces_lower,
521 for (
unsigned int i = 0; i < assignment.size(); ++i)
522 if (assignment[i] < 0)
523 owned_faces_lower.push_back(
524 inner_face.second.shared_faces[i]);
525 else if (assignment[i] > 0)
526 owned_faces_higher.push_back(
527 inner_face.second.shared_faces[i]);
529 inner_face.second.shared_faces.size() + 1 -
530 owned_faces_lower.size() -
531 owned_faces_higher.size());
533 unsigned int i = 0, c = 0;
534 for (; i < assignment.size() && c < split_index; ++i)
535 if (assignment[i] == 0)
537 owned_faces_lower.push_back(
538 inner_face.second.shared_faces[i]);
541 for (; i < assignment.size(); ++i)
542 if (assignment[i] == 0)
544 owned_faces_higher.push_back(
545 inner_face.second.shared_faces[i]);
551 std::vector<std::pair<CellId, CellId>> check_faces;
552 check_faces.insert(check_faces.end(),
553 owned_faces_lower.begin(),
554 owned_faces_lower.end());
555 check_faces.insert(check_faces.end(),
556 owned_faces_higher.begin(),
557 owned_faces_higher.end());
558 std::sort(check_faces.begin(), check_faces.end());
560 inner_face.second.shared_faces.size());
561 for (
unsigned int i = 0; i < check_faces.size(); ++i)
562 Assert(check_faces[i] == inner_face.second.shared_faces[i],
567 if (my_domain < inner_face.first)
568 inner_face.second.shared_faces.swap(owned_faces_lower);
570 inner_face.second.shared_faces.swap(owned_faces_higher);
572 std::sort(inner_face.second.shared_faces.begin(),
573 inner_face.second.shared_faces.end());
579 std::set<std::pair<unsigned int, unsigned int>> ghost_cells;
580 for (
unsigned int i = 0; i < cell_levels.size(); ++i)
582 typename ::Triangulation<dim>::cell_iterator dcell(
583 &triangulation, cell_levels[i].first, cell_levels[i].second);
584 if (use_active_cells)
586 for (
const auto f : dcell->face_indices())
588 if (dcell->at_boundary(f) && !dcell->has_periodic_neighbor(f))
589 face_is_owned[dcell->face(f)->index()] =
590 FaceCategory::locally_active_at_boundary;
591 else if (!build_inner_faces)
596 else if ((dcell->at_boundary(f) ==
false ||
597 dcell->has_periodic_neighbor(f)) &&
599 dcell->neighbor_or_periodic_neighbor(f)->level() <
602 face_is_owned[dcell->face(f)->index()] =
603 FaceCategory::multigrid_refinement_edge;
607 typename ::Triangulation<dim>::cell_iterator neighbor =
608 dcell->neighbor_or_periodic_neighbor(f);
611 if (use_active_cells && neighbor->has_children() &&
612 hold_all_faces_to_owned_cells ==
false)
615 bool add_to_ghost =
false;
617 id1 = use_active_cells ? dcell->subdomain_id() :
618 dcell->level_subdomain_id(),
619 id2 = use_active_cells ?
620 (neighbor->has_children() ?
621 dcell->neighbor_child_on_subface(f, 0)
623 neighbor->subdomain_id()) :
624 neighbor->level_subdomain_id();
632 (use_active_cells ==
false || neighbor->is_active())) ||
633 dcell->level() > neighbor->level() ||
635 inner_faces_at_proc_boundary[id2].shared_faces.begin(),
636 inner_faces_at_proc_boundary[id2].shared_faces.end(),
637 std::make_pair(id1 < id2 ? dcell->
id() : neighbor->id(),
638 id1 < id2 ? neighbor->
id() :
641 face_is_owned[dcell->face(f)->index()] =
642 FaceCategory::locally_active_done_here;
643 if (dcell->level() == neighbor->level() ||
644 dcell->has_periodic_neighbor(f))
647 ->face(dcell->has_periodic_neighbor(f) ?
648 dcell->periodic_neighbor_face_no(f) :
649 dcell->neighbor_face_no(f))
651 FaceCategory::locally_active_done_here;
657 if (use_active_cells)
659 (dcell->subdomain_id() != neighbor->subdomain_id());
661 add_to_ghost = (dcell->level_subdomain_id() !=
662 neighbor->level_subdomain_id());
664 else if (hold_all_faces_to_owned_cells ==
true)
667 face_is_owned[dcell->face(f)->index()] =
668 FaceCategory::ghosted;
669 if (use_active_cells)
671 if (neighbor->has_children())
672 for (
unsigned int s = 0;
673 s < dcell->face(f)->n_children();
675 if (dcell->at_boundary(f))
678 ->periodic_neighbor_child_on_subface(f,
681 dcell->subdomain_id())
686 if (dcell->neighbor_child_on_subface(f, s)
688 dcell->subdomain_id())
692 add_to_ghost = (dcell->subdomain_id() !=
693 neighbor->subdomain_id());
696 add_to_ghost = (dcell->level_subdomain_id() !=
697 neighbor->level_subdomain_id());
702 if (use_active_cells && neighbor->has_children())
703 for (
unsigned int s = 0;
704 s < dcell->face(f)->n_children();
707 typename ::Triangulation<dim>::cell_iterator
709 dcell->at_boundary(f) ?
710 dcell->periodic_neighbor_child_on_subface(f,
712 dcell->neighbor_child_on_subface(f, s);
713 if (neighbor_child->subdomain_id() !=
714 dcell->subdomain_id())
716 std::pair<unsigned int, unsigned int>(
717 neighbor_child->level(),
718 neighbor_child->index()));
722 std::pair<unsigned int, unsigned int>(
723 neighbor->level(), neighbor->index()));
724 at_processor_boundary[i] =
true;
732 for (
const auto &ghost_cell : ghost_cells)
733 cell_levels.push_back(ghost_cell);
740 FaceSetup<dim>::generate_faces(
741 const ::Triangulation<dim> &triangulation,
742 const std::vector<std::pair<unsigned int, unsigned int>> &cell_levels,
745 const bool is_mixed_mesh = triangulation.is_mixed_mesh();
749 std::map<std::pair<unsigned int, unsigned int>,
unsigned int>
751 for (
unsigned int cell = 0; cell < cell_levels.size(); ++cell)
752 if (cell == 0 || cell_levels[cell] != cell_levels[cell - 1])
754 typename ::Triangulation<dim>::cell_iterator dcell(
756 cell_levels[cell].first,
757 cell_levels[cell].second);
758 std::pair<unsigned int, unsigned int> level_index(dcell->level(),
760 map_to_vectorized[level_index] = cell;
764 const unsigned int vectorization_length = task_info.vectorization_length;
765 task_info.face_partition_data.resize(
766 task_info.cell_partition_data.size() - 1, 0);
767 task_info.boundary_partition_data.resize(
768 task_info.cell_partition_data.size() - 1, 0);
769 std::vector<unsigned char> face_visited(face_is_owned.size(), 0);
770 for (
unsigned int partition = 0;
771 partition < task_info.cell_partition_data.size() - 2;
774 unsigned int boundary_counter = 0;
775 unsigned int inner_counter = 0;
776 for (
unsigned int cell = task_info.cell_partition_data[partition] *
777 vectorization_length;
778 cell < task_info.cell_partition_data[partition + 1] *
779 vectorization_length;
781 if (cell == 0 || cell_levels[cell] != cell_levels[cell - 1])
783 typename ::Triangulation<dim>::cell_iterator dcell(
785 cell_levels[cell].first,
786 cell_levels[cell].second);
787 for (
const auto f : dcell->face_indices())
790 if (face_is_owned[dcell->face(f)->index()] ==
791 FaceCategory::locally_active_at_boundary)
795 FaceToCellTopology<1> info;
796 info.cells_interior[0] = cell;
798 info.interior_face_no = f;
799 info.exterior_face_no = dcell->face(f)->boundary_id();
807 info.face_orientation = 0;
808 boundary_faces.push_back(info);
810 face_visited[dcell->face(f)->index()]++;
815 typename ::Triangulation<dim>::cell_iterator
816 neighbor = dcell->neighbor_or_periodic_neighbor(f);
817 if (use_active_cells && neighbor->has_children())
819 const unsigned int n_children =
820 (dim == 1) ? 1 : dcell->face(f)->n_children();
821 for (
unsigned int c = 0; c < n_children; ++c)
823 typename ::Triangulation<
827 (dcell->at_boundary(f) ?
829 ->periodic_neighbor_child_on_subface(
831 dcell->neighbor_child_on_subface(f, c));
836 neighbor_c = neighbor->child(1 - f);
837 while (!neighbor_c->is_active())
838 neighbor_c = neighbor_c->child(1 - f);
841 neighbor_c->subdomain_id();
842 const unsigned int neighbor_face_no =
843 dcell->has_periodic_neighbor(f) ?
844 dcell->periodic_neighbor_face_no(f) :
845 dcell->neighbor_face_no(f);
846 const unsigned int child_face_index =
847 dim > 1 ? dcell->face(f)->child(c)->index() :
848 dcell->face(f)->index();
849 if (neigh_domain != dcell->subdomain_id() ||
850 face_visited[child_face_index] == 1)
852 std::pair<unsigned int, unsigned int>
853 level_index(neighbor_c->level(),
854 neighbor_c->index());
855 if (face_is_owned[child_face_index] ==
856 FaceCategory::locally_active_done_here)
859 inner_faces.push_back(create_face(
862 map_to_vectorized[level_index],
867 else if (face_is_owned[child_face_index] ==
868 FaceCategory::ghosted ||
869 face_is_owned[dcell->face(f)
871 FaceCategory::ghosted)
873 inner_ghost_faces.push_back(create_face(
876 map_to_vectorized[level_index],
882 Assert(face_is_owned[dcell->face(f)
885 locally_active_done_elsewhere,
890 face_visited[child_face_index] = 1;
891 if (dcell->has_periodic_neighbor(f))
892 face_visited[dcell->face(f)->index()] = 1;
899 use_active_cells ? dcell->subdomain_id() :
900 dcell->level_subdomain_id();
902 use_active_cells ? neighbor->subdomain_id() :
903 neighbor->level_subdomain_id();
904 const unsigned int face_index =
905 dcell->face(f)->index();
906 if (neigh_domain != my_domain ||
907 face_visited[face_index] == 1)
909 std::pair<unsigned int, unsigned int>
910 level_index(neighbor->level(),
912 if (face_is_owned[dcell->face(f)->index()] ==
913 FaceCategory::locally_active_done_here)
915 Assert(use_active_cells ||
920 inner_faces.push_back(create_face(
925 map_to_vectorized[level_index],
928 else if (face_is_owned[face_index] ==
929 FaceCategory::ghosted)
931 inner_ghost_faces.push_back(create_face(
936 map_to_vectorized[level_index],
942 face_visited[face_index] = 1;
943 if (dcell->has_periodic_neighbor(f))
947 dcell->periodic_neighbor_face_no(f))
950 if (face_is_owned[face_index] ==
951 FaceCategory::multigrid_refinement_edge)
953 refinement_edge_faces.push_back(
958 refinement_edge_faces.size(),
965 task_info.face_partition_data[
partition + 1] =
966 task_info.face_partition_data[
partition] + inner_counter;
967 task_info.boundary_partition_data[
partition + 1] =
968 task_info.boundary_partition_data[
partition] + boundary_counter;
970 task_info.ghost_face_partition_data.resize(2);
971 task_info.ghost_face_partition_data[0] = 0;
972 task_info.ghost_face_partition_data[1] = inner_ghost_faces.size();
973 task_info.refinement_edge_face_partition_data.resize(2);
974 task_info.refinement_edge_face_partition_data[0] = 0;
975 task_info.refinement_edge_face_partition_data[1] =
976 refinement_edge_faces.size();
982 FaceToCellTopology<1>
983 FaceSetup<dim>::create_face(
984 const unsigned int face_no,
985 const typename ::Triangulation<dim>::cell_iterator &cell,
986 const unsigned int number_cell_interior,
987 const typename ::Triangulation<dim>::cell_iterator &neighbor,
988 const unsigned int number_cell_exterior,
989 const bool is_mixed_mesh)
991 FaceToCellTopology<1> info;
992 info.cells_interior[0] = number_cell_interior;
993 info.cells_exterior[0] = number_cell_exterior;
994 info.interior_face_no = face_no;
995 if (cell->has_periodic_neighbor(face_no))
996 info.exterior_face_no = cell->periodic_neighbor_face_no(face_no);
998 info.exterior_face_no = cell->neighbor_face_no(face_no);
1000 info.face_type = is_mixed_mesh ?
1009 if (dim > 1 && cell->level() > neighbor->level())
1011 if (cell->has_periodic_neighbor(face_no))
1012 info.subface_index =
1013 cell->periodic_neighbor_of_coarser_periodic_neighbor(face_no)
1016 info.subface_index =
1017 cell->neighbor_of_coarser_neighbor(face_no).second;
1021 if (cell->has_periodic_neighbor(face_no))
1023 info.face_orientation = cell->get_triangulation()
1024 .get_periodic_face_map()
1025 .at({cell, face_no})
1030 const auto interior_face_orientation =
1031 cell->combined_face_orientation(face_no);
1032 const auto exterior_face_orientation =
1033 neighbor->combined_face_orientation(info.exterior_face_no);
1034 if (interior_face_orientation !=
1037 info.face_orientation = 8 + interior_face_orientation;
1038 Assert(exterior_face_orientation ==
1041 "Face seems to be wrongly oriented from both sides"));
1044 info.face_orientation = exterior_face_orientation;
1048 if (cell->level() > neighbor->level() &&
1049 exterior_face_orientation > 0)
1051 const Table<2, unsigned int> orientation =
1052 ShapeInfo<double>::compute_orientation_table(2);
1053 const auto face_reference_cell =
1054 cell->face(face_no)->reference_cell();
1055 info.subface_index = orientation(
1056 face_reference_cell.get_inverse_combined_orientation(
1057 exterior_face_orientation),
1058 info.subface_index);
1074 compare_faces_for_vectorization(
1075 const FaceToCellTopology<1> &face1,
1076 const FaceToCellTopology<1> &face2,
1077 const std::vector<unsigned int> &active_fe_indices,
1078 const unsigned int length)
1080 if (face1.interior_face_no != face2.interior_face_no)
1082 if (face1.exterior_face_no != face2.exterior_face_no)
1084 if (face1.subface_index != face2.subface_index)
1086 if (face1.face_orientation != face2.face_orientation)
1088 if (face1.face_type != face2.face_type)
1091 if (active_fe_indices.size() > 0)
1093 if (active_fe_indices[face1.cells_interior[0] / length] !=
1094 active_fe_indices[face2.cells_interior[0] / length])
1098 if (active_fe_indices[face1.cells_exterior[0] / length] !=
1099 active_fe_indices[face2.cells_exterior[0] / length])
1114 template <
int length>
1115 struct FaceComparator
1117 FaceComparator(
const std::vector<unsigned int> &active_fe_indices)
1118 : active_fe_indices(active_fe_indices)
1122 operator()(
const FaceToCellTopology<length> &face1,
1123 const FaceToCellTopology<length> &face2)
const
1126 if (face1.face_type < face2.face_type)
1128 else if (face1.face_type > face2.face_type)
1132 if (active_fe_indices.size() > 0)
1135 if (active_fe_indices[face1.cells_interior[0] / length] <
1136 active_fe_indices[face2.cells_interior[0] / length])
1138 else if (active_fe_indices[face1.cells_interior[0] / length] >
1139 active_fe_indices[face2.cells_interior[0] / length])
1145 if (active_fe_indices[face1.cells_exterior[0] / length] <
1146 active_fe_indices[face2.cells_exterior[0] / length])
1148 else if (active_fe_indices[face1.cells_exterior[0] / length] >
1149 active_fe_indices[face2.cells_exterior[0] / length])
1154 for (
unsigned int i = 0; i < length; ++i)
1155 if (face1.cells_interior[i] < face2.cells_interior[i])
1157 else if (face1.cells_interior[i] > face2.cells_interior[i])
1159 for (
unsigned int i = 0; i < length; ++i)
1160 if (face1.cells_exterior[i] < face2.cells_exterior[i])
1162 else if (face1.cells_exterior[i] > face2.cells_exterior[i])
1164 if (face1.interior_face_no < face2.interior_face_no)
1166 else if (face1.interior_face_no > face2.interior_face_no)
1168 if (face1.exterior_face_no < face2.exterior_face_no)
1170 else if (face1.exterior_face_no > face2.exterior_face_no)
1183 const std::vector<unsigned int> &active_fe_indices;
1188 template <
int vectorization_w
idth>
1191 const std::vector<FaceToCellTopology<1>> &faces_in,
1192 const std::vector<bool> &hard_vectorization_boundary,
1193 std::vector<unsigned int> &face_partition_data,
1194 std::vector<FaceToCellTopology<vectorization_width>> &faces_out,
1195 const std::vector<unsigned int> &active_fe_indices)
1197 FaceToCellTopology<vectorization_width> face_batch;
1198 std::vector<std::vector<unsigned int>> faces_type;
1200 unsigned int face_start = face_partition_data[0],
1201 face_end = face_partition_data[0];
1203 face_partition_data[0] = faces_out.size();
1204 for (
unsigned int partition = 0;
1205 partition < face_partition_data.size() - 1;
1208 std::vector<std::vector<unsigned int>> new_faces_type;
1211 face_start = face_end;
1212 face_end = face_partition_data[
partition + 1];
1219 for (
unsigned int face = face_start; face < face_end; ++face)
1221 for (
auto &face_type : faces_type)
1224 if (compare_faces_for_vectorization(faces_in[face],
1225 faces_in[face_type[0]],
1227 vectorization_width))
1229 face_type.push_back(face);
1233 faces_type.emplace_back(1, face);
1239 FaceComparator<vectorization_width> face_comparator(
1241 std::set<FaceToCellTopology<vectorization_width>,
1242 FaceComparator<vectorization_width>>
1243 new_faces(face_comparator);
1244 for (
const auto &face_type : faces_type)
1246 face_batch.face_type = faces_in[face_type[0]].face_type;
1247 face_batch.interior_face_no =
1248 faces_in[face_type[0]].interior_face_no;
1249 face_batch.exterior_face_no =
1250 faces_in[face_type[0]].exterior_face_no;
1251 face_batch.subface_index = faces_in[face_type[0]].subface_index;
1252 face_batch.face_orientation =
1253 faces_in[face_type[0]].face_orientation;
1254 unsigned int no_faces = face_type.size();
1255 std::vector<unsigned char> touched(no_faces, 0);
1261 unsigned int n_vectorized = 0;
1262 for (
unsigned int f = 0; f < no_faces; ++f)
1263 if (faces_in[face_type[f]].cells_interior[0] %
1264 vectorization_width ==
1267 bool is_contiguous =
true;
1268 if (f + vectorization_width > no_faces)
1269 is_contiguous =
false;
1271 for (
unsigned int v = 1; v < vectorization_width; ++v)
1272 if (faces_in[face_type[f + v]].cells_interior[0] !=
1273 faces_in[face_type[f]].cells_interior[0] + v)
1274 is_contiguous =
false;
1279 vectorization_width + 1);
1280 for (
unsigned int v = 0; v < vectorization_width; ++v)
1282 face_batch.cells_interior[v] =
1283 faces_in[face_type[f + v]].cells_interior[0];
1284 face_batch.cells_exterior[v] =
1285 faces_in[face_type[f + v]].cells_exterior[0];
1288 new_faces.insert(face_batch);
1289 f += vectorization_width - 1;
1290 n_vectorized += vectorization_width;
1294 std::vector<unsigned int> untouched;
1295 untouched.reserve(no_faces - n_vectorized);
1296 for (
unsigned int f = 0; f < no_faces; ++f)
1297 if (touched[f] == 0)
1298 untouched.push_back(f);
1300 for (
const auto f : untouched)
1302 face_batch.cells_interior[v] =
1303 faces_in[face_type[f]].cells_interior[0];
1304 face_batch.cells_exterior[v] =
1305 faces_in[face_type[f]].cells_exterior[0];
1307 if (v == vectorization_width)
1309 new_faces.insert(face_batch);
1313 if (v > 0 && v < vectorization_width)
1316 if (hard_vectorization_boundary[partition + 1] ||
1317 partition == face_partition_data.size() - 2)
1319 for (; v < vectorization_width; ++v)
1322 face_batch.cells_interior[v] =
1324 face_batch.cells_exterior[v] =
1327 new_faces.insert(face_batch);
1332 std::vector<unsigned int> untreated(v);
1333 for (
unsigned int f = 0; f < v; ++f)
1334 untreated[f] = face_type[*(untouched.end() - 1 - f)];
1335 new_faces_type.push_back(untreated);
1341 for (
auto it = new_faces.begin(); it != new_faces.end(); ++it)
1342 faces_out.push_back(*it);
1343 face_partition_data[
partition + 1] += new_faces.size();
1346 faces_type = std::move(new_faces_type);
1352 for (
const auto &face_type : faces_type)
1356 unsigned int nfaces = 0;
1357 for (
unsigned int i = face_partition_data[0];
1358 i < face_partition_data.back();
1360 for (
unsigned int v = 0; v < vectorization_width; ++v)
1361 nfaces += (faces_out[i].cells_interior[v] !=
1365 std::vector<std::pair<unsigned int, unsigned int>> in_faces,
1367 for (
const auto &face_in : faces_in)
1368 in_faces.emplace_back(face_in.cells_interior[0],
1369 face_in.cells_exterior[0]);
1370 for (
unsigned int i = face_partition_data[0];
1371 i < face_partition_data.back();
1373 for (
unsigned int v = 0;
1374 v < vectorization_width && faces_out[i].cells_interior[v] !=
1377 out_faces.emplace_back(faces_out[i].cells_interior[v],
1378 faces_out[i].cells_exterior[v]);
1379 std::sort(in_faces.begin(), in_faces.end());
1380 std::sort(out_faces.begin(), out_faces.end());
1382 for (
unsigned int i = 0; i < in_faces.size(); ++i)
#define DEAL_II_NAMESPACE_OPEN
constexpr bool running_in_debug_mode()
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
typename ActiveSelector::cell_iterator cell_iterator
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell &reference_cell)
constexpr const ReferenceCell & get_hypercube()
void collect_faces_vectorization(const std::vector< FaceToCellTopology< 1 > > &faces_in, const std::vector< bool > &hard_vectorization_boundary, std::vector< unsigned int > &face_partition_data, std::vector< FaceToCellTopology< vectorization_width > > &faces_out)
constexpr unsigned int invalid_unsigned_int
constexpr types::subdomain_id invalid_subdomain_id
constexpr types::geometric_orientation default_geometric_orientation
unsigned int subdomain_id
static constexpr unsigned int max_children_per_cell
unsigned int n_hanging_faces_smaller_subdomain
unsigned int n_hanging_faces_larger_subdomain
std::vector< std::pair< CellId, CellId > > shared_faces
std::vector< FaceToCellTopology< 1 > > inner_faces
std::vector< bool > at_processor_boundary
std::vector< FaceToCellTopology< 1 > > boundary_faces
std::vector< FaceToCellTopology< 1 > > refinement_edge_faces
FaceToCellTopology< 1 > create_face(const unsigned int face_no, const typename ::Triangulation< dim >::cell_iterator &cell, const unsigned int number_cell_interior, const typename ::Triangulation< dim >::cell_iterator &neighbor, const unsigned int number_cell_exterior, const bool is_mixed_mesh)
std::vector< FaceCategory > face_is_owned
@ locally_active_done_here
@ multigrid_refinement_edge
@ locally_active_at_boundary
@ locally_active_done_elsewhere
void initialize(const ::Triangulation< dim > &triangulation, const unsigned int mg_level, const bool hold_all_faces_to_owned_cells, const bool build_inner_faces, std::vector< std::pair< unsigned int, unsigned int > > &cell_levels)
std::vector< FaceToCellTopology< 1 > > inner_ghost_faces
void generate_faces(const ::Triangulation< dim > &triangulation, const std::vector< std::pair< unsigned int, unsigned int > > &cell_levels, TaskInfo &task_info)