166 if (vertices_have_unique_ids ==
false)
169 std::map<Point<spacedim>,
172 map_point_to_local_vertex_index(
182 std::map<unsigned int, unsigned int>
183 map_old_to_new_local_vertex_index;
187 for (
const auto &p : other.coarse_cell_vertices)
188 if (map_point_to_local_vertex_index.find(p.second) ==
189 map_point_to_local_vertex_index.end())
192 map_point_to_local_vertex_index[p.second] =
193 map_old_to_new_local_vertex_index[p.first] = counter++;
196 map_old_to_new_local_vertex_index[p.first] =
197 map_point_to_local_vertex_index[p.second];
200 auto other_coarse_cells_copy = other.coarse_cells;
202 for (
auto &cell : other_coarse_cells_copy)
203 for (
auto &v : cell.vertices)
204 v = map_old_to_new_local_vertex_index[v];
207 other_coarse_cells_copy.begin(),
208 other_coarse_cells_copy.end());
213 other.coarse_cells.begin(),
214 other.coarse_cells.end());
217 other.coarse_cell_vertices.begin(),
218 other.coarse_cell_vertices.end());
223 other.coarse_cell_index_to_coarse_cell_id.begin(),
224 other.coarse_cell_index_to_coarse_cell_id.end());
226 for (
unsigned int i = 0; i < this->
cell_infos.size(); ++i)
227 this->cell_infos[i].
insert(this->cell_infos[i].
end(),
228 other.cell_infos[i].begin(),
229 other.cell_infos[i].end());
245 for (
unsigned int i = 0; i < this->
coarse_cells.size(); ++i)
246 temp.emplace_back(this->coarse_cell_index_to_coarse_cell_id[i],
247 this->coarse_cells[i],
250 std::sort(temp.begin(),
252 [](
const auto &a,
const auto &b) {
253 return std::get<0>(a) < std::get<0>(b);
255 temp.erase(std::unique(temp.begin(),
257 [](
const auto &a,
const auto &b) {
258 return std::get<0>(a) == std::get<0>(b);
261 std::sort(temp.begin(),
263 [](
const auto &a,
const auto &b) {
264 return std::get<2>(a) < std::get<2>(b);
270 for (
unsigned int i = 0; i < temp.size(); ++i)
273 std::get<0>(temp[i]);
281 this->coarse_cell_vertices.end(),
284 return a.first < b.first;
289 this->coarse_cell_vertices.end(),
292 if (a.first == b.first)
294 Assert(a.second.distance(b.second) <=
296 std::max(a.second.norm(), b.second.norm()),
298 "In the process of merging the vertices of "
299 "the coarse meshes used on different processes, "
300 "there were two processes that used the same "
301 "vertex index for points that are not the same. "
302 "This suggests that you are using different "
303 "coarse meshes on different processes. This "
304 "should not happen."));
313 for (
unsigned int i = 0; i < this->
cell_infos.size(); ++i)
315 if (this->cell_infos[i].empty())
318 std::sort(this->cell_infos[i].
begin(),
319 this->cell_infos[i].
end(),
320 [](
const auto &a,
const auto &b) {
324 std::vector<CellData<dim>> temp;
325 temp.push_back(this->cell_infos[i][0]);
327 for (
unsigned int j = 1; j < this->
cell_infos[i].size(); ++j)
328 if (temp.back().id == cell_infos[i][j].id)
330 temp.back().subdomain_id =
332 this->cell_infos[i][j].subdomain_id);
333 temp.back().level_subdomain_id =
334 std::min(temp.back().level_subdomain_id,
335 this->cell_infos[i][j].level_subdomain_id);
339 temp.push_back(this->cell_infos[i][j]);
351 Description<dim, spacedim>
357 Description<dim, spacedim> description;
360 description.comm =
comm;
362 description.settings = settings;
365 description.smoothing = mesh_smoothing;
367 std::map<unsigned int, unsigned int> map;
371 description.coarse_cell_vertices.push_back(
379 for (unsigned
int v = 0; v < cell.vertices.size(); ++v)
380 cell.
vertices[v] = map[cell.vertices[v]];
382 description.coarse_cell_index_to_coarse_cell_id =
391 std::vector<std::pair<unsigned int, Point<spacedim>>>
402 template <
int dim,
int spacedim>
404 mark_cell_and_its_parents(
406 std::vector<std::vector<bool>> &cell_marked)
408 cell_marked[cell->level()][cell->index()] =
true;
409 if (cell->level() != 0)
410 mark_cell_and_its_parents(cell->parent(), cell_marked);
418 template <
typename DescriptionType,
int dim,
int spacedim>
420 create_description_for_rank(
421 const ::Triangulation<dim, spacedim> &tria,
423 const typename ::Triangulation<dim, spacedim>::cell_iterator &)>
424 &subdomain_id_function,
426 const typename ::Triangulation<dim, spacedim>::cell_iterator &)>
427 &level_subdomain_id_function,
428 const std::map<
unsigned int, std::vector<unsigned int>>
429 &coinciding_vertex_groups,
430 const std::map<unsigned int, unsigned int>
431 &vertex_to_coinciding_vertex_group,
437 std::is_same_v<DescriptionType, Description<dim, spacedim>> ||
438 std::is_same_v<DescriptionType, DescriptionTemp<dim, spacedim>>,
439 "Wrong template type.");
443 (tria.get_mesh_smoothing() &
444 Triangulation<dim, spacedim>::limit_level_difference_at_vertices),
446 "Source triangulation has to be set up with "
447 "limit_level_difference_at_vertices if the construction of the "
448 "multigrid hierarchy is requested!"));
450 const bool construct_multigrid =
454 DescriptionType construction_data;
455 if constexpr (std::is_same_v<DescriptionType,
456 Description<dim, spacedim>>)
458 construction_data.comm =
comm;
459 construction_data.smoothing = tria.get_mesh_smoothing();
460 construction_data.settings = settings;
469 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells =
470 [&coinciding_vertex_groups, &vertex_to_coinciding_vertex_group](
471 const typename ::Triangulation<dim, spacedim>::cell_iterator
473 std::vector<bool> &vertices_on_locally_owned_cells) {
479 const auto coinciding_vertex_group =
480 vertex_to_coinciding_vertex_group.find(global_vertex_index);
481 if (coinciding_vertex_group !=
482 vertex_to_coinciding_vertex_group.end())
483 for (
const auto &co_vertex : coinciding_vertex_groups.at(
484 coinciding_vertex_group->
second))
485 vertices_on_locally_owned_cells[co_vertex] = true;
489 const auto add_vertices =
490 [&tria](
const std::vector<bool> &vertices_locally_relevant,
491 DescriptionType &construction_data) {
492 if constexpr (std::is_same_v<DescriptionType,
493 Description<dim, spacedim>>)
495 std::vector<unsigned int> vertices_locally_relevant_indices(
496 vertices_locally_relevant.size());
499 unsigned int vertex_counter = 0;
500 for (
unsigned int i = 0; i < vertices_locally_relevant.size();
502 if (vertices_locally_relevant[i])
504 construction_data.coarse_cell_vertices.push_back(
505 tria.get_vertices()[i]);
506 vertices_locally_relevant_indices[i] = vertex_counter++;
511 for (unsigned
int v = 0; v < cell.vertices.size(); ++v)
513 vertices_locally_relevant_indices[cell.vertices[v]];
517 for (
unsigned int i = 0; i < vertices_locally_relevant.size();
519 if (vertices_locally_relevant[i])
520 construction_data.coarse_cell_vertices.emplace_back(
521 i, tria.get_vertices()[i]);
528 std::vector<std::vector<bool>> cell_marked(tria.n_levels());
529 for (
unsigned int l = 0;
l < tria.n_levels(); ++
l)
530 cell_marked[l].resize(tria.n_raw_cells(l));
532 for (
int level = tria.get_triangulation().n_global_levels() - 1;
538 std::vector<bool> vertices_owned_by_locally_owned_cells_on_level(
540 for (
const auto &cell : tria.cell_iterators_on_level(
level))
541 if (construct_multigrid &&
542 (level_subdomain_id_function(cell) ==
my_rank))
543 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
544 cell, vertices_owned_by_locally_owned_cells_on_level);
546 for (
const auto &cell : tria.active_cell_iterators())
547 if (subdomain_id_function(cell) ==
my_rank)
548 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
549 cell, vertices_owned_by_locally_owned_cells_on_level);
554 const auto is_locally_relevant_on_level = [&](
const auto &cell) {
556 if (vertices_owned_by_locally_owned_cells_on_level
557 [cell->vertex_index(v)])
563 for (
const auto &cell : tria.cell_iterators_on_level(
level))
564 if (is_locally_relevant_on_level(cell))
565 mark_cell_and_its_parents(cell, cell_marked);
570 std::vector<bool> vertices_locally_relevant(tria.n_vertices(),
false);
573 for (
const auto &cell : tria.cell_iterators_on_level(0))
575 if (!cell_marked[cell->level()][cell->index()])
580 cell_data.material_id = cell->material_id();
581 cell_data.manifold_id = cell->manifold_id();
583 cell_data.vertices[v] = cell->vertex_index(v);
584 construction_data.coarse_cells.push_back(cell_data);
588 vertices_locally_relevant[cell->vertex_index(v)] = true;
591 construction_data.coarse_cell_index_to_coarse_cell_id.push_back(
592 cell->id().get_coarse_cell_id());
595 add_vertices(vertices_locally_relevant, construction_data);
600 construction_data.cell_infos.resize(
601 tria.get_triangulation().n_global_levels());
604 std::vector<bool> vertices_owned_by_locally_owned_active_cells(
606 for (
const auto &cell : tria.active_cell_iterators())
607 if (subdomain_id_function(cell) ==
my_rank)
608 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
609 cell, vertices_owned_by_locally_owned_active_cells);
613 const auto is_locally_relevant_on_active_level = [&](
const auto &cell) {
614 if (cell->is_active())
616 if (vertices_owned_by_locally_owned_active_cells
617 [cell->vertex_index(v)])
622 for (
unsigned int level = 0;
623 level < tria.get_triangulation().n_global_levels();
627 std::vector<bool> vertices_owned_by_locally_owned_cells_on_level(
629 for (
const auto &cell : tria.cell_iterators_on_level(
level))
630 if ((construct_multigrid &&
631 (level_subdomain_id_function(cell) ==
my_rank)) ||
632 (cell->is_active() && subdomain_id_function(cell) ==
my_rank))
633 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
634 cell, vertices_owned_by_locally_owned_cells_on_level);
638 const auto is_locally_relevant_on_level = [&](
const auto &cell) {
640 if (vertices_owned_by_locally_owned_cells_on_level
641 [cell->vertex_index(v)])
646 auto &level_cell_infos = construction_data.cell_infos[
level];
647 for (
const auto &cell : tria.cell_iterators_on_level(
level))
650 if (!cell_marked[cell->level()][cell->index()])
656 cell_info.id = cell->id().template to_binary<dim>();
659 for (
const auto f : cell->face_indices())
662 cell->face(f)->boundary_id();
664 cell_info.boundary_ids.emplace_back(f, boundary_ind);
674 for (
const auto line : cell->line_indices())
675 cell_info.manifold_line_ids[line] =
680 for (
const auto f : cell->face_indices())
681 cell_info.manifold_quad_ids[f] =
689 if (is_locally_relevant_on_active_level(cell))
691 cell_info.subdomain_id = subdomain_id_function(cell);
693 cell_info.level_subdomain_id =
694 level_subdomain_id_function(cell);
696 else if (is_locally_relevant_on_level(cell))
698 cell_info.level_subdomain_id =
699 level_subdomain_id_function(cell);
706 level_cell_infos.emplace_back(cell_info);
710 return construction_data;
715 template <
int dim,
int spacedim>
716 Description<dim, spacedim>
718 const ::Triangulation<dim, spacedim> &tria,
721 const unsigned int my_rank_in)
723 if (
const auto ptria =
728 ExcMessage(
"MPI communicators do not match."));
732 "For creation from a parallel::Triangulation, "
733 "my_rank has to equal the rank of the current process "
734 "in the given communicator."));
745 const unsigned int n_mpi_processes =
747 for (
const auto &cell : tria.active_cell_iterators())
748 Assert(cell->subdomain_id() < n_mpi_processes,
749 ExcMessage(
"You can't have a cell with subdomain_id of " +
750 std::to_string(cell->subdomain_id()) +
751 " when splitting the triangulation using an MPI "
752 " communicator with only " +
753 std::to_string(n_mpi_processes) +
" processes."));
764 const auto subdomain_id_function = [](
const auto &cell) {
765 return cell->subdomain_id();
768 const auto level_subdomain_id_function = [](
const auto &cell) {
769 return cell->level_subdomain_id();
772 std::map<unsigned int, std::vector<unsigned int>>
773 coinciding_vertex_groups;
774 std::map<unsigned int, unsigned int> vertex_to_coinciding_vertex_group;
776 coinciding_vertex_groups,
777 vertex_to_coinciding_vertex_group);
779 return create_description_for_rank<Description<dim, spacedim>>(
781 subdomain_id_function,
782 level_subdomain_id_function,
783 coinciding_vertex_groups,
784 vertex_to_coinciding_vertex_group,
792 template <
int dim,
int spacedim>
796 &serial_grid_generator,
799 const unsigned int)> &serial_grid_partitioner,
801 const int group_size,
805#ifndef DEAL_II_WITH_MPI
806 (void)serial_grid_generator;
807 (void)serial_grid_partitioner;
817 const unsigned int group_root = (
my_rank / group_size) * group_size;
830 typename ::Triangulation<dim, spacedim>::MeshSmoothing
>(
833 spacedim>::limit_level_difference_at_vertices) :
835 serial_grid_generator(tria);
838 serial_grid_partitioner(tria,
comm, group_size);
845 const unsigned int end_group =
853 for (
unsigned int other_rank = group_root + 1; other_rank < end_group;
857 const auto construction_data =
863 std::vector<char> buffer;
867 const auto ierr = MPI_Send(buffer.data(),
889 auto ierr = MPI_Probe(group_root, mpi_tag,
comm, &status);
893 MPI_Get_count(&status, MPI_CHAR, &len);
895 std::vector<char> buf(len);
896 ierr = MPI_Recv(buf.data(),
907 auto construction_data =
908 ::Utilities::template unpack<Description<dim, spacedim>>(
913 construction_data.comm =
comm;
915 return construction_data;
922 template <
int dim,
int spacedim>
929 const bool construct_multigrid =
930 (partition.size() > 0) &&
935 construct_multigrid ==
false ||
939 "Source triangulation has to be set up with "
940 "limit_level_difference_at_vertices if the construction of the "
941 "multigrid hierarchy is requested!"));
943 std::vector<LinearAlgebra::distributed::Vector<double>> partitions_mg;
950 if (construct_multigrid)
952 const auto tria_parallel =
960 partitions_mg[l].reinit(
961 tria_parallel->global_level_cell_index_partitioner(l).lock());
971 partition.update_ghost_values();
976 if (cell->is_locally_owned_on_level())
978 if (cell->is_active())
979 partitions_mg[
level][cell->global_level_cell_index()] =
980 partition[cell->global_active_cell_index()];
982 partitions_mg[
level][cell->global_level_cell_index()] =
983 partitions_mg[
level + 1]
985 ->global_level_cell_index()];
993 partitions_mg[
level].update_ghost_values();
1006 template <
int dim,
int spacedim>
1015#ifdef DEAL_II_WITH_MPI
1020 if (partition.size() == 0)
1029 partition.update_ghost_values();
1030 for (
const auto &partition : partitions_mg)
1031 partition.update_ghost_values();
1041 const std::vector<unsigned int> future_owners_of_locally_owned_cells =
1042 [&partition, &partitions_mg]() {
1043 std::set<unsigned int> relevant_process_set;
1045 const unsigned int n_mpi_ranks =
1047 partition.get_mpi_communicator());
1050 for (
unsigned int i = 0; i < partition.locally_owned_size(); ++i)
1052 Assert(
static_cast<unsigned int>(partition.local_element(i)) ==
1053 partition.local_element(i),
1055 "The elements of a partition vector must be integers."));
1057 partition.local_element(i) < n_mpi_ranks,
1059 "The elements of a partition vector must be between zero "
1060 "and the number of processes in the communicator "
1061 "to be used for partitioning the triangulation."));
1062 relevant_process_set.insert(
1063 static_cast<unsigned int>(partition.local_element(i)));
1066 for (
const auto &partition : partitions_mg)
1067 for (
unsigned int i = 0; i < partition.locally_owned_size(); ++i)
1070 static_cast<unsigned int>(partition.local_element(i)) ==
1071 partition.local_element(i),
1073 "The elements of a partition vector must be integers."));
1075 partition.local_element(i) < n_mpi_ranks,
1077 "The elements of a partition vector must be between zero "
1078 "and the number of processes in the communicator "
1079 "to be used for partitioning the triangulation."));
1080 relevant_process_set.insert(
1081 static_cast<unsigned int>(partition.local_element(i)));
1084 return std::vector<unsigned int>(relevant_process_set.begin(),
1085 relevant_process_set.end());
1088 const bool construct_multigrid = (partitions_mg.size() > 0);
1091 (construct_multigrid ?
1101 const auto cell_to_future_owner =
1103 if ((cell->is_active() && (cell->is_artificial() ==
false)))
1105 partition[cell->global_active_cell_index()]);
1110 const auto mg_cell_to_future_owner =
1111 [&construct_multigrid,
1113 if (construct_multigrid && (cell->is_artificial_on_level() ==
false))
1115 partitions_mg[cell->level()][cell->global_level_cell_index()]);
1124 std::vector<DescriptionTemp<dim, spacedim>> descriptions_per_rank;
1125 descriptions_per_rank.reserve(
1126 future_owners_of_locally_owned_cells.size());
1128 std::map<unsigned int, std::vector<unsigned int>>
1129 coinciding_vertex_groups;
1130 std::map<unsigned int, unsigned int> vertex_to_coinciding_vertex_group;
1132 coinciding_vertex_groups,
1133 vertex_to_coinciding_vertex_group);
1135 for (
const auto rank : future_owners_of_locally_owned_cells)
1136 descriptions_per_rank.emplace_back(
1137 create_description_for_rank<DescriptionTemp<dim, spacedim>>(
1139 cell_to_future_owner,
1140 mg_cell_to_future_owner,
1141 coinciding_vertex_groups,
1142 vertex_to_coinciding_vertex_group,
1149 DescriptionTemp<dim, spacedim> description_merged;
1150 description_merged.collect(
1151 future_owners_of_locally_owned_cells,
1152 descriptions_per_rank,
1153 partition.get_mpi_communicator(),
1159 description_merged.reduce();
1162 return description_merged.convert(partition.get_mpi_communicator(),
1173#include "tria_description.inst"