17 #ifndef dealii_face_setup_internal_h 18 #define dealii_face_setup_internal_h 20 #include <deal.II/base/utilities.h> 21 #include <deal.II/base/memory_consumption.h> 22 #include <deal.II/grid/tria.h> 23 #include <deal.II/grid/tria_accessor.h> 24 #include <deal.II/matrix_free/task_info.h> 25 #include <deal.II/matrix_free/face_info.h> 30 DEAL_II_NAMESPACE_OPEN
35 namespace MatrixFreeFunctions
47 n_hanging_faces_smaller_subdomain (0),
48 n_hanging_faces_larger_subdomain (0)
51 std::vector<std::pair<CellId,CellId> > shared_faces;
52 unsigned int n_hanging_faces_smaller_subdomain;
53 unsigned int n_hanging_faces_larger_subdomain;
79 template <
typename MFAddData>
80 void initialize(const ::Triangulation<dim> &triangulation,
81 const MFAddData &additional_data,
82 std::vector<std::pair<unsigned int,unsigned int> > &cell_levels);
92 const std::vector<std::pair<unsigned int,unsigned int> > &cell_levels,
103 const typename ::Triangulation<dim>::cell_iterator &cell,
104 const unsigned int number_cell_interior,
105 const typename ::Triangulation<dim>::cell_iterator &neighbor,
106 const unsigned int number_cell_exterior);
108 bool use_active_cells;
116 locally_active_at_boundary,
117 locally_active_done_here,
118 locally_active_done_elsewhere,
120 multigrid_refinement_edge
123 std::vector<FaceCategory> face_is_owned;
124 std::vector<bool> at_processor_boundary;
125 std::vector<unsigned int> cells_close_to_boundary;
126 std::vector<FaceToCellTopology<1> > inner_faces;
127 std::vector<FaceToCellTopology<1> > boundary_faces;
128 std::vector<FaceToCellTopology<1> > inner_ghost_faces;
129 std::vector<FaceToCellTopology<1> > refinement_edge_faces;
137 template <
int vectorization_w
idth>
139 collect_faces_vectorization
140 (
const std::vector<FaceToCellTopology<1> > &faces_in,
141 const std::vector<bool> &hard_vectorization_boundary,
142 std::vector<unsigned int> &face_partition_data,
143 std::vector<FaceToCellTopology<vectorization_width> > &faces_out);
152 FaceSetup<dim>::FaceSetup()
154 use_active_cells (true)
160 template <
typename MFAddData>
163 const MFAddData &additional_data,
164 std::vector<std::pair<unsigned int,unsigned int> > &cell_levels)
170 if (use_active_cells)
171 for (
unsigned int i=0; i<cell_levels.size(); ++i)
173 typename ::Triangulation<dim>::cell_iterator
174 dcell(&triangulation, cell_levels[i].first,
175 cell_levels[i].second);
183 at_processor_boundary.resize(cell_levels.size(),
false);
184 cells_close_to_boundary.clear();
185 face_is_owned.resize(dim > 1 ? triangulation.n_raw_faces() :
186 triangulation.n_vertices(), FaceCategory::locally_active_done_elsewhere);
190 std::map<types::subdomain_id, FaceIdentifier> inner_faces_at_proc_boundary;
194 for (
unsigned int i=0; i<cell_levels.size(); ++i)
196 if (i>0 && cell_levels[i] == cell_levels[i-1])
198 typename ::Triangulation<dim>::cell_iterator
199 dcell(&triangulation, cell_levels[i].first,
200 cell_levels[i].second);
201 for (
unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
203 if (dcell->at_boundary(f) && !dcell->has_periodic_neighbor(f))
205 typename ::Triangulation<dim>::cell_iterator
206 neighbor = dcell->neighbor_or_periodic_neighbor(f);
212 const CellId id_mine = dcell->id();
213 if (use_active_cells && neighbor->has_children())
214 for (
unsigned int c=0; c<dcell->face(f)->n_children(); ++c)
216 typename ::Triangulation<dim>::cell_iterator
217 neighbor_c = dcell->at_boundary(f) ?
218 dcell->periodic_neighbor_child_on_subface(f, c) :
219 dcell->neighbor_child_on_subface(f, c);
221 if (my_domain < neigh_domain)
222 inner_faces_at_proc_boundary[neigh_domain].n_hanging_faces_larger_subdomain++;
223 else if (my_domain > neigh_domain)
224 inner_faces_at_proc_boundary[neigh_domain].n_hanging_faces_smaller_subdomain++;
229 neighbor->subdomain_id() :
230 neighbor->level_subdomain_id();
231 if (neighbor->level() < dcell->level() &&
234 if (my_domain < neigh_domain)
235 inner_faces_at_proc_boundary[neigh_domain].n_hanging_faces_smaller_subdomain++;
236 else if (my_domain > neigh_domain)
237 inner_faces_at_proc_boundary[neigh_domain].n_hanging_faces_larger_subdomain++;
239 else if (neighbor->level() == dcell->level() &&
240 my_domain != neigh_domain)
246 const CellId id_neigh = neighbor->id();
247 if (my_domain < neigh_domain)
248 inner_faces_at_proc_boundary[neigh_domain].shared_faces.
249 emplace_back(id_mine, id_neigh);
251 inner_faces_at_proc_boundary[neigh_domain].shared_faces.
252 emplace_back(id_neigh, id_mine);
261 for (std::map<types::subdomain_id, FaceIdentifier>::iterator it
262 = inner_faces_at_proc_boundary.begin();
263 it != inner_faces_at_proc_boundary.end(); ++it)
265 Assert(it->first != my_domain,
267 std::sort(it->second.shared_faces.begin(), it->second.shared_faces.end());
268 it->second.shared_faces.erase(std::unique(it->second.shared_faces.begin(),
269 it->second.shared_faces.end()),
270 it->second.shared_faces.end());
275 #if defined(DEAL_II_WITH_MPI) && defined(DEBUG) 276 MPI_Comm comm = MPI_COMM_SELF;
279 comm = ptria->get_communicator();
282 unsigned int mysize = it->second.shared_faces.size();
284 MPI_Sendrecv(&mysize, 1, MPI_UNSIGNED, it->first, 600+my_domain,
285 &othersize, 1, MPI_UNSIGNED, it->first, 600+it->first,
288 mysize = it->second.n_hanging_faces_smaller_subdomain;
289 MPI_Sendrecv(&mysize, 1, MPI_UNSIGNED, it->first, 700+my_domain,
290 &othersize, 1, MPI_UNSIGNED, it->first, 700+it->first,
293 mysize = it->second.n_hanging_faces_larger_subdomain;
294 MPI_Sendrecv(&mysize, 1, MPI_UNSIGNED, it->first, 800+my_domain,
295 &othersize, 1, MPI_UNSIGNED, it->first, 800+it->first,
315 std::vector<std::tuple<CellId,CellId,unsigned int> > other_range(it->second.shared_faces.size());
316 for (
unsigned int i=0; i<other_range.size(); ++i)
317 other_range[i] = std::make_tuple(it->second.shared_faces[i].second,
318 it->second.shared_faces[i].first,
320 std::sort(other_range.begin(), other_range.end());
328 unsigned int n_faces_lower_proc = 0, n_faces_higher_proc = 0;
329 std::vector<char> assignment(other_range.size(), 0);
330 if (it->second.shared_faces.size() > 0)
334 unsigned int count = 0;
335 for (
unsigned int i=1; i<it->second.shared_faces.size(); ++i)
336 if (it->second.shared_faces[i].first ==
337 it->second.shared_faces[i-1-count].first)
344 for (
unsigned int k=0; k<=count; ++k)
345 assignment[i-1-k] = 1;
346 n_faces_higher_proc += count+1;
356 for (
unsigned int i=1; i<other_range.size(); ++i)
357 if (std::get<0>(other_range[i]) ==
358 std::get<0>(other_range[i-1-count]))
365 for (
unsigned int k=0; k<=count; ++k)
367 Assert(it->second.shared_faces[std::get<2>(other_range[i-1])].second ==
368 it->second.shared_faces[std::get<2>(other_range[i-1-k])].second,
372 if (assignment[std::get<2>(other_range[i-1-k])] == 0)
374 assignment[std::get<2>(other_range[i-1-k])] = -1;
375 ++n_faces_lower_proc;
389 n_faces_lower_proc += it->second.n_hanging_faces_smaller_subdomain;
390 n_faces_higher_proc += it->second.n_hanging_faces_larger_subdomain;
391 const unsigned int n_total_faces_at_proc_boundary =
392 (it->second.shared_faces.size() +
393 it->second.n_hanging_faces_smaller_subdomain +
394 it->second.n_hanging_faces_larger_subdomain);
395 unsigned int split_index = n_total_faces_at_proc_boundary/2;
396 if (split_index < n_faces_lower_proc)
398 else if (split_index < n_total_faces_at_proc_boundary -
400 split_index -= n_faces_lower_proc;
402 split_index = n_total_faces_at_proc_boundary - n_faces_higher_proc - n_faces_lower_proc;
405 #if defined(DEAL_II_WITH_MPI) && defined(DEBUG) 406 MPI_Sendrecv(&split_index, 1, MPI_UNSIGNED, it->first, 900+my_domain,
407 &othersize, 1, MPI_UNSIGNED, it->first, 900+it->first,
410 MPI_Sendrecv(&n_faces_lower_proc, 1, MPI_UNSIGNED, it->first, 1000+my_domain,
411 &othersize, 1, MPI_UNSIGNED, it->first, 1000+it->first,
414 MPI_Sendrecv(&n_faces_higher_proc, 1, MPI_UNSIGNED, it->first, 1100+my_domain,
415 &othersize, 1, MPI_UNSIGNED, it->first, 1100+it->first,
421 std::vector<std::pair<CellId,CellId> > owned_faces_lower, owned_faces_higher;
422 for (
unsigned int i=0; i<assignment.size(); ++i)
423 if (assignment[i] < 0)
424 owned_faces_lower.push_back(it->second.shared_faces[i]);
425 else if (assignment[i] > 0)
426 owned_faces_higher.push_back(it->second.shared_faces[i]);
428 owned_faces_lower.size() - owned_faces_higher.size());
430 unsigned int i=0, c=0;
431 for (; i<assignment.size() && c < split_index; ++i)
432 if (assignment[i] == 0)
434 owned_faces_lower.push_back(it->second.shared_faces[i]);
437 for ( ; i<assignment.size(); ++i)
438 if (assignment[i] == 0)
440 owned_faces_higher.push_back(it->second.shared_faces[i]);
445 std::vector<std::pair<CellId,CellId> > check_faces;
446 check_faces.insert(check_faces.end(), owned_faces_lower.begin(),
447 owned_faces_lower.end());
448 check_faces.insert(check_faces.end(), owned_faces_higher.begin(),
449 owned_faces_higher.end());
450 std::sort(check_faces.begin(), check_faces.end());
452 for (
unsigned int i=0; i<check_faces.size(); ++i)
457 if (my_domain < it->first)
458 it->second.shared_faces.swap(owned_faces_lower);
460 it->second.shared_faces.swap(owned_faces_higher);
462 std::sort(it->second.shared_faces.begin(), it->second.shared_faces.end());
468 std::set<std::pair<unsigned int, unsigned int> > ghost_cells;
469 for (
unsigned int i=0; i<cell_levels.size(); ++i)
471 typename ::Triangulation<dim>::cell_iterator
472 dcell(&triangulation, cell_levels[i].first,
473 cell_levels[i].second);
474 if (use_active_cells)
476 for (
unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
478 if (dcell->at_boundary(f) && !dcell->has_periodic_neighbor(f))
479 face_is_owned[dcell->face(f)->index()] = FaceCategory::locally_active_at_boundary;
483 else if ((dcell->at_boundary(f) ==
false ||
484 dcell->has_periodic_neighbor(f)) &&
487 dcell->neighbor_or_periodic_neighbor(f)->level() < dcell->level())
489 face_is_owned[dcell->face(f)->index()] = FaceCategory::multigrid_refinement_edge;
493 typename ::Triangulation<dim>::cell_iterator neighbor =
494 dcell->neighbor_or_periodic_neighbor(f);
497 if (use_active_cells && neighbor->has_children() &&
498 additional_data.hold_all_faces_to_owned_cells ==
false)
501 bool add_to_ghost =
false;
503 id1 = use_active_cells ? dcell->subdomain_id() : dcell->level_subdomain_id(),
504 id2 = use_active_cells ? (neighbor->has_children() ?
505 dcell->neighbor_child_on_subface(f,0)->subdomain_id() :
506 neighbor->subdomain_id()) :
507 neighbor->level_subdomain_id();
514 if ((id1 == id2 && (use_active_cells ==
false ||
515 neighbor->has_children() ==
false)) ||
516 dcell->level() > neighbor->level() ||
517 std::binary_search(inner_faces_at_proc_boundary[id2].shared_faces.begin(),
518 inner_faces_at_proc_boundary[id2].shared_faces.end(),
519 std::make_pair(id1<id2 ? dcell->
id() : neighbor->id(),
520 id1<id2 ? neighbor->id() : dcell->id())))
522 face_is_owned[dcell->face(f)->index()] = FaceCategory::locally_active_done_here;
523 if (dcell->level() == neighbor->level())
524 face_is_owned[neighbor->face(dcell->has_periodic_neighbor(f) ?
525 dcell->periodic_neighbor_face_no(f) :
526 dcell->neighbor_face_no(f))->index()]
527 = FaceCategory::locally_active_done_here;
532 if (use_active_cells)
533 add_to_ghost = (dcell->subdomain_id() !=
534 neighbor->subdomain_id());
536 add_to_ghost = (dcell->level_subdomain_id() !=
537 neighbor->level_subdomain_id());
539 else if (additional_data.hold_all_faces_to_owned_cells ==
false)
542 cells_close_to_boundary.emplace_back(i);
547 face_is_owned[dcell->face(f)->index()] = FaceCategory::ghosted;
548 if (use_active_cells)
550 if (neighbor->has_children())
551 for (
unsigned int s=0; s<dcell->face(f)->n_children(); ++s)
552 if (dcell->at_boundary(f))
554 if (dcell->periodic_neighbor_child_on_subface(f,s)->subdomain_id() !=
555 dcell->subdomain_id())
560 if (dcell->neighbor_child_on_subface(f,s)->subdomain_id() !=
561 dcell->subdomain_id())
565 add_to_ghost = (dcell->subdomain_id() !=
566 neighbor->subdomain_id());
569 add_to_ghost = (dcell->level_subdomain_id() !=
570 neighbor->level_subdomain_id());
576 (std::pair<unsigned int,unsigned int>
577 (neighbor->level(), neighbor->index()));
578 at_processor_boundary[i] =
true;
586 for (std::set<std::pair<unsigned int, unsigned int> >::iterator
587 it=ghost_cells.begin(); it!=ghost_cells.end(); ++it)
588 cell_levels.push_back(*it);
591 std::sort(cells_close_to_boundary.begin(), cells_close_to_boundary.end());
592 cells_close_to_boundary.erase(std::unique(cells_close_to_boundary.begin(),
593 cells_close_to_boundary.end()),
594 cells_close_to_boundary.end());
595 std::vector<unsigned int> final_cells;
596 final_cells.reserve(cells_close_to_boundary.size());
597 for (
unsigned int i=0; i<cells_close_to_boundary.size(); ++i)
598 if (at_processor_boundary[cells_close_to_boundary[i]] ==
false)
599 final_cells.push_back(cells_close_to_boundary[i]);
600 cells_close_to_boundary = std::move(final_cells);
609 const std::vector<std::pair<unsigned int,unsigned int> > &cell_levels,
614 std::map<std::pair<unsigned int,unsigned int>,
unsigned int>
616 for (
unsigned int cell=0; cell<cell_levels.size(); ++cell)
617 if (cell == 0 || cell_levels[cell] != cell_levels[cell-1])
619 typename ::Triangulation<dim>::cell_iterator dcell
620 (&triangulation, cell_levels[cell].first, cell_levels[cell].second);
621 std::pair<unsigned int,unsigned int> level_index(dcell->level(),
623 map_to_vectorized[level_index] = cell;
627 const unsigned int vectorization_length = task_info.vectorization_length;
628 task_info.face_partition_data.resize(task_info.cell_partition_data.size()-1, 0);
629 task_info.boundary_partition_data.resize(task_info.cell_partition_data.size()-1, 0);
630 std::vector<unsigned char> face_visited(face_is_owned.size(), 0);
631 for (
unsigned int partition=0;
partition<task_info.cell_partition_data.size()-2; ++
partition)
633 unsigned int boundary_counter = 0;
634 unsigned int inner_counter = 0;
635 for (
unsigned int cell=
636 task_info.cell_partition_data[partition]*vectorization_length;
637 cell<task_info.cell_partition_data[partition+1]*vectorization_length;
639 if (cell == 0 || cell_levels[cell] != cell_levels[cell-1])
641 typename ::Triangulation<dim>::cell_iterator dcell
642 (&triangulation, cell_levels[cell].first, cell_levels[cell].second);
643 for (
unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
646 if (face_is_owned[dcell->face(f)->index()] == FaceCategory::locally_active_at_boundary)
650 FaceToCellTopology<1> info;
651 info.cells_interior[0] = cell;
653 info.interior_face_no = f;
654 info.exterior_face_no = dcell->face(f)->boundary_id();
656 info.face_orientation = 0;
657 boundary_faces.push_back(info);
659 face_visited[dcell->face(f)->index()]++;
664 typename ::Triangulation<dim>::cell_iterator neighbor
665 = dcell->neighbor_or_periodic_neighbor(f);
666 if (use_active_cells && neighbor->has_children())
668 for (
unsigned int c=0; c<dcell->face(f)->n_children(); ++c)
670 typename ::Triangulation<dim>::cell_iterator
671 neighbor_c = dcell->at_boundary(f) ?
672 dcell->periodic_neighbor_child_on_subface(f, c) :
673 dcell->neighbor_child_on_subface(f, c);
675 const unsigned int neighbor_face_no =
676 dcell->has_periodic_neighbor(f) ?
677 dcell->periodic_neighbor_face_no(f) :
678 dcell->neighbor_face_no(f);
679 if (neigh_domain != dcell->subdomain_id() ||
680 face_visited[dcell->face(f)->child(c)->index()] == 1)
682 std::pair<unsigned int,unsigned int>
683 level_index(neighbor_c->level(), neighbor_c->index());
684 if (face_is_owned[dcell->face(f)->child(c)->index()]==
685 FaceCategory::locally_active_done_here)
689 push_back(create_face(neighbor_face_no, neighbor_c,
690 map_to_vectorized[level_index],
694 else if (face_is_owned[dcell->face(f)->child(c)->index()] ==
695 FaceCategory::ghosted)
698 push_back(create_face(neighbor_face_no, neighbor_c,
699 map_to_vectorized[level_index],
703 Assert(face_is_owned[dcell->face(f)->index()] ==
704 FaceCategory::locally_active_done_elsewhere,
709 face_visited[dcell->face(f)->child(c)->index()] = 1;
716 dcell->subdomain_id() : dcell->level_subdomain_id();
718 neighbor->subdomain_id() : neighbor->level_subdomain_id();
719 if (neigh_domain != my_domain ||
720 face_visited[dcell->face(f)->index()] == 1)
722 std::pair<unsigned int,unsigned int>
723 level_index(neighbor->level(), neighbor->index());
724 if (face_is_owned[dcell->face(f)->index()]==
725 FaceCategory::locally_active_done_here)
729 push_back(create_face(f, dcell, cell, neighbor,
730 map_to_vectorized[level_index]));
732 else if (face_is_owned[dcell->face(f)->index()] ==
733 FaceCategory::ghosted)
736 push_back(create_face(f, dcell, cell, neighbor,
737 map_to_vectorized[level_index]));
742 face_visited[dcell->face(f)->index()] = 1;
743 if (dcell->has_periodic_neighbor(f))
744 face_visited[neighbor->face(dcell->periodic_neighbor_face_no(f))->index()] = 1;
746 if (face_is_owned[dcell->face(f)->index()] ==
747 FaceCategory::multigrid_refinement_edge)
749 refinement_edge_faces.
750 push_back(create_face(f, dcell, cell, neighbor,
751 refinement_edge_faces.size()));
757 task_info.face_partition_data[
partition+1]=
758 task_info.face_partition_data[
partition] + inner_counter;
759 task_info.boundary_partition_data[
partition+1] =
760 task_info.boundary_partition_data[
partition] + boundary_counter;
762 task_info.ghost_face_partition_data.resize(2);
763 task_info.ghost_face_partition_data[0] = 0;
764 task_info.ghost_face_partition_data[1] = inner_ghost_faces.size();
765 task_info.refinement_edge_face_partition_data.resize(2);
766 task_info.refinement_edge_face_partition_data[0] = 0;
767 task_info.refinement_edge_face_partition_data[1] = refinement_edge_faces.size();
773 FaceToCellTopology<1>
776 const typename ::Triangulation<dim>::cell_iterator &cell,
777 const unsigned int number_cell_interior,
778 const typename ::Triangulation<dim>::cell_iterator &neighbor,
779 const unsigned int number_cell_exterior)
781 FaceToCellTopology<1> info;
783 info.cells_exterior[0] = number_cell_exterior;
784 info.interior_face_no = face_no;
785 if (cell->has_periodic_neighbor(face_no))
786 info.exterior_face_no = cell->periodic_neighbor_face_no(face_no);
788 info.exterior_face_no = cell->neighbor_face_no(face_no);
791 Assert(neighbor->level() <= cell->level(),
793 if (cell->level() > neighbor->level())
795 if (cell->has_periodic_neighbor(face_no))
797 cell->periodic_neighbor_of_coarser_periodic_neighbor(face_no).second;
800 cell->neighbor_of_coarser_neighbor(face_no).second;
803 info.face_orientation = 0;
804 const unsigned int left_face_orientation =
805 !cell->face_orientation(face_no) + 2 * cell->face_flip(face_no) +
806 4 * cell->face_rotation(face_no);
807 const unsigned int right_face_orientation =
808 !neighbor->face_orientation(info.exterior_face_no) +
809 2 * neighbor->face_flip(info.exterior_face_no) +
810 4 * neighbor->face_rotation(info.exterior_face_no);
811 if (left_face_orientation != 0)
813 info.face_orientation = 8 + left_face_orientation;
814 Assert(right_face_orientation == 0,
815 ExcMessage(
"Face seems to be wrongly oriented from both sides"));
818 info.face_orientation = right_face_orientation;
830 bool compare_faces_for_vectorization
831 (
const FaceToCellTopology<1> &face1,
832 const FaceToCellTopology<1> &face2)
834 if (face1.interior_face_no != face2.interior_face_no)
836 if (face1.exterior_face_no != face2.exterior_face_no)
838 if (face1.subface_index != face2.subface_index)
840 if (face1.face_orientation != face2.face_orientation)
853 template <
int length>
854 struct FaceComparator
856 bool operator() (
const FaceToCellTopology<length> &face1,
857 const FaceToCellTopology<length> &face2)
const 859 for (
unsigned int i=0; i<length; ++i)
860 if (face1.cells_interior[i] < face2.cells_interior[i])
862 else if (face1.cells_interior[i] > face2.cells_interior[i])
864 for (
unsigned int i=0; i<length; ++i)
865 if (face1.cells_exterior[i] < face2.cells_exterior[i])
867 else if (face1.cells_exterior[i] > face2.cells_exterior[i])
869 if (face1.interior_face_no < face2.interior_face_no)
871 else if (face1.interior_face_no > face2.interior_face_no)
873 if (face1.exterior_face_no < face2.exterior_face_no)
875 else if (face1.exterior_face_no > face2.exterior_face_no)
890 template <
int vectorization_w
idth>
892 collect_faces_vectorization
893 (
const std::vector<FaceToCellTopology<1> > &faces_in,
894 const std::vector<bool> &hard_vectorization_boundary,
895 std::vector<unsigned int> &face_partition_data,
896 std::vector<FaceToCellTopology<vectorization_width> > &faces_out)
898 FaceToCellTopology<vectorization_width> macro_face;
899 std::vector<std::vector<unsigned int> > faces_type;
901 unsigned int face_start = face_partition_data[0],
902 face_end = face_partition_data[0];
904 face_partition_data[0] = faces_out.size();
907 std::vector<std::vector<unsigned int> > new_faces_type;
910 face_start = face_end;
911 face_end = face_partition_data[
partition+1];
918 for (
unsigned int face=face_start; face<face_end; ++face)
920 for (
unsigned int type=0; type<faces_type.size(); ++type)
923 if ( compare_faces_for_vectorization(faces_in[face],
924 faces_in[faces_type[type][0]]) )
926 faces_type[type].push_back(face);
930 faces_type.emplace_back(1, face);
936 std::set<FaceToCellTopology<vectorization_width>,
937 FaceComparator<vectorization_width> > new_faces;
938 for (
unsigned int type=0; type<faces_type.size(); ++type)
940 macro_face.interior_face_no = faces_in[faces_type[type][0]].interior_face_no;
941 macro_face.exterior_face_no = faces_in[faces_type[type][0]].exterior_face_no;
942 macro_face.subface_index = faces_in[faces_type[type][0]].subface_index;
943 macro_face.face_orientation = faces_in[faces_type[type][0]].face_orientation;
944 unsigned int no_faces = faces_type[type].size();
945 std::vector<unsigned char> touched(no_faces, 0);
950 unsigned int n_vectorized = 0;
951 for (
unsigned int f=0; f<no_faces; ++f)
952 if (faces_in[faces_type[type][f]].cells_interior[0] % vectorization_width == 0)
954 bool is_contiguous =
true;
955 if (f + vectorization_width > no_faces)
956 is_contiguous =
false;
958 for (
unsigned int v=1; v<vectorization_width; ++v)
959 if (faces_in[faces_type[type][f+v]].cells_interior[0] !=
960 faces_in[faces_type[type][f]].cells_interior[0]+v)
961 is_contiguous =
false;
965 for (
unsigned int v=0; v<vectorization_width; ++v)
967 macro_face.cells_interior[v] = faces_in[faces_type[type][f+v]].cells_interior[0];
968 macro_face.cells_exterior[v] = faces_in[faces_type[type][f+v]].cells_exterior[0];
971 new_faces.insert(macro_face);
972 f += vectorization_width-1;
973 n_vectorized += vectorization_width;
977 std::vector<unsigned int> untouched;
978 untouched.reserve(no_faces - n_vectorized);
979 for (
unsigned int f=0; f<no_faces; ++f)
981 untouched.push_back(f);
983 for (
auto f : untouched)
985 macro_face.cells_interior[v] = faces_in[faces_type[type][f]].cells_interior[0];
986 macro_face.cells_exterior[v] = faces_in[faces_type[type][f]].cells_exterior[0];
988 if (v == vectorization_width)
990 new_faces.insert(macro_face);
994 if (v > 0 && v < vectorization_width)
997 if (hard_vectorization_boundary[partition+1] ||
998 partition == face_partition_data.size()-2)
1000 for ( ; v < vectorization_width; ++v)
1006 new_faces.insert(macro_face);
1011 std::vector<unsigned int> untreated(v);
1012 for (
unsigned int f=0; f<v; ++f)
1013 untreated[f] = faces_type[type][*(untouched.end()-1-f)];
1014 new_faces_type.push_back(untreated);
1020 for (
auto it = new_faces.begin(); it != new_faces.end(); ++it)
1021 faces_out.push_back(*it);
1022 face_partition_data[
partition+1] += new_faces.size();
1025 faces_type = std::move(new_faces_type);
1030 for (
unsigned int i=0; i<faces_type.size(); ++i)
1034 unsigned int nfaces = 0;
1035 for (
unsigned int i=face_partition_data[0]; i<face_partition_data.back(); ++i)
1036 for (
unsigned int v=0; v<vectorization_width; ++v)
1040 std::vector<std::pair<unsigned int,unsigned int>> in_faces, out_faces;
1041 for (
unsigned int i=0; i<faces_in.size(); ++i)
1042 in_faces.emplace_back(faces_in[i].cells_interior[0],
1043 faces_in[i].cells_exterior[0]);
1044 for (
unsigned int i=face_partition_data[0]; i<face_partition_data.back(); ++i)
1045 for (
unsigned int v=0; v<vectorization_width &&
1047 out_faces.emplace_back(faces_out[i].cells_interior[v],
1048 faces_out[i].cells_exterior[v]);
1049 std::sort(in_faces.begin(), in_faces.end());
1050 std::sort(out_faces.begin(), out_faces.end());
1052 for (
unsigned int i=0; i<in_faces.size(); ++i)
1060 #endif // ifndef DOXYGEN 1066 DEAL_II_NAMESPACE_CLOSE
static const unsigned int invalid_unsigned_int
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
#define AssertThrow(cond, exc)
unsigned int cells_interior[vectorization_width]
static ::ExceptionBase & ExcMessage(std::string arg1)
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)
#define Assert(cond, exc)
void initialize(const ::Triangulation< dim > &triangulation, const MFAddData &additional_data, std::vector< std::pair< unsigned int, unsigned int > > &cell_levels)
void generate_faces(const ::Triangulation< dim > &triangulation, const std::vector< std::pair< unsigned int, unsigned int > > &cell_levels, TaskInfo &task_info)
unsigned int subdomain_id
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcInternalError()