160 merge(
const DescriptionTemp<dim, spacedim> &other,
161 const bool vertices_have_unique_ids)
163 this->cell_infos.resize(
164 std::max(other.cell_infos.size(), this->cell_infos.size()));
166 if (vertices_have_unique_ids ==
false)
169 std::map<Point<spacedim>,
172 map_point_to_local_vertex_index(
176 for (
unsigned int i = 0; i < this->coarse_cell_vertices.size();
178 map_point_to_local_vertex_index[coarse_cell_vertices[i]
182 std::map<unsigned int, unsigned int>
183 map_old_to_new_local_vertex_index;
186 unsigned int counter = coarse_cell_vertices.size();
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())
191 this->coarse_cell_vertices.emplace_back(counter, p.second);
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];
206 this->coarse_cells.insert(this->coarse_cells.end(),
207 other_coarse_cells_copy.begin(),
208 other_coarse_cells_copy.end());
212 this->coarse_cells.insert(this->coarse_cells.end(),
213 other.coarse_cells.begin(),
214 other.coarse_cells.end());
215 this->coarse_cell_vertices.insert(
216 this->coarse_cell_vertices.end(),
217 other.coarse_cell_vertices.begin(),
218 other.coarse_cell_vertices.end());
221 this->coarse_cell_index_to_coarse_cell_id.insert(
222 this->coarse_cell_index_to_coarse_cell_id.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 temp.reserve(this->coarse_cells.size());
246 for (
unsigned int i = 0; i < this->coarse_cells.size(); ++i)
247 temp.emplace_back(this->coarse_cell_index_to_coarse_cell_id[i],
248 this->coarse_cells[i],
251 std::sort(temp.begin(),
253 [](
const auto &a,
const auto &b) {
254 return std::get<0>(a) < std::get<0>(b);
256 temp.erase(std::unique(temp.begin(),
258 [](
const auto &a,
const auto &b) {
259 return std::get<0>(a) == std::get<0>(b);
262 std::sort(temp.begin(),
264 [](
const auto &a,
const auto &b) {
265 return std::get<2>(a) < std::get<2>(b);
268 this->coarse_cell_index_to_coarse_cell_id.resize(temp.size());
269 this->coarse_cells.resize(temp.size());
271 for (
unsigned int i = 0; i < temp.size(); ++i)
273 this->coarse_cell_index_to_coarse_cell_id[i] =
274 std::get<0>(temp[i]);
275 this->coarse_cells[i] = std::get<1>(temp[i]);
281 std::sort(this->coarse_cell_vertices.begin(),
282 this->coarse_cell_vertices.end(),
283 [](
const std::pair<
unsigned int, Point<spacedim>> &a,
284 const std::pair<
unsigned int, Point<spacedim>> &b) {
285 return a.first < b.first;
287 this->coarse_cell_vertices.erase(
289 this->coarse_cell_vertices.begin(),
290 this->coarse_cell_vertices.end(),
291 [](
const std::pair<
unsigned int, Point<spacedim>> &a,
292 const std::pair<
unsigned int, Point<spacedim>> &b) {
293 if (a.first == b.first)
295 Assert(a.second.distance(b.second) <=
297 std::max(a.second.norm(), b.second.norm()),
299 "In the process of merging the vertices of "
300 "the coarse meshes used on different processes, "
301 "there were two processes that used the same "
302 "vertex index for points that are not the same. "
303 "This suggests that you are using different "
304 "coarse meshes on different processes. This "
305 "should not happen."));
310 this->coarse_cell_vertices.end());
314 for (
unsigned int i = 0; i < this->cell_infos.size(); ++i)
316 if (this->cell_infos[i].empty())
319 std::sort(this->cell_infos[i].
begin(),
320 this->cell_infos[i].
end(),
321 [](
const auto &a,
const auto &b) {
325 std::vector<CellData<dim>> temp;
326 temp.push_back(this->cell_infos[i][0]);
328 for (
unsigned int j = 1; j < this->cell_infos[i].size(); ++j)
329 if (temp.back().id == cell_infos[i][j].id)
331 temp.back().subdomain_id =
333 this->cell_infos[i][j].subdomain_id);
334 temp.back().level_subdomain_id =
335 std::min(temp.back().level_subdomain_id,
336 this->cell_infos[i][j].level_subdomain_id);
340 temp.push_back(this->cell_infos[i][j]);
343 this->cell_infos[i] = temp;
352 Description<dim, spacedim>
353 convert(
const MPI_Comm
comm,
358 Description<dim, spacedim> description;
361 description.comm =
comm;
363 description.settings = settings;
366 description.smoothing = mesh_smoothing;
368 std::map<unsigned int, unsigned int> map;
370 for (
unsigned int i = 0; i < this->coarse_cell_vertices.size(); ++i)
372 description.coarse_cell_vertices.push_back(
373 this->coarse_cell_vertices[i].second);
374 map[this->coarse_cell_vertices[i].first] = i;
377 description.coarse_cells = this->coarse_cells;
379 for (
auto &cell : description.coarse_cells)
380 for (
unsigned int v = 0; v < cell.vertices.size(); ++v)
381 cell.
vertices[v] = map[cell.vertices[v]];
383 description.coarse_cell_index_to_coarse_cell_id =
384 this->coarse_cell_index_to_coarse_cell_id;
385 description.cell_infos = this->cell_infos;
390 std::vector<::CellData<dim>> coarse_cells;
392 std::vector<std::pair<unsigned int, Point<spacedim>>>
393 coarse_cell_vertices;
395 std::vector<types::coarse_cell_id> coarse_cell_index_to_coarse_cell_id;
397 std::vector<std::vector<CellData<dim>>> cell_infos;
403 template <
int dim,
int spacedim>
405 mark_cell_and_its_parents(
406 const TriaIterator<CellAccessor<dim, spacedim>> &cell,
407 std::vector<std::vector<bool>> &cell_marked)
409 cell_marked[cell->level()][cell->index()] =
true;
410 if (cell->level() != 0)
411 mark_cell_and_its_parents(cell->parent(), cell_marked);
419 template <
typename DescriptionType,
int dim,
int spacedim>
421 create_description_for_rank(
422 const ::Triangulation<dim, spacedim> &tria,
424 const typename ::Triangulation<dim, spacedim>::cell_iterator &)>
425 &subdomain_id_function,
427 const typename ::Triangulation<dim, spacedim>::cell_iterator &)>
428 &level_subdomain_id_function,
429 const std::map<
unsigned int, std::vector<unsigned int>>
430 &coinciding_vertex_groups,
431 const std::map<unsigned int, unsigned int>
432 &vertex_to_coinciding_vertex_group,
434 const unsigned int my_rank,
438 std::is_same_v<DescriptionType, Description<dim, spacedim>> ||
439 std::is_same_v<DescriptionType, DescriptionTemp<dim, spacedim>>,
440 "Wrong template type.");
444 (tria.get_mesh_smoothing() &
447 "Source triangulation has to be set up with "
448 "limit_level_difference_at_vertices if the construction of the "
449 "multigrid hierarchy is requested!"));
451 const bool construct_multigrid =
452 ((settings & TriangulationDescription::Settings::
453 construct_multigrid_hierarchy) != 0u);
455 DescriptionType construction_data;
456 if constexpr (std::is_same_v<DescriptionType,
457 Description<dim, spacedim>>)
459 construction_data.comm =
comm;
460 construction_data.smoothing = tria.get_mesh_smoothing();
461 construction_data.settings = settings;
470 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells =
471 [&coinciding_vertex_groups, &vertex_to_coinciding_vertex_group](
472 const typename ::Triangulation<dim, spacedim>::cell_iterator
474 std::vector<bool> &vertices_on_locally_owned_cells) {
475 for (
const unsigned int v : cell->vertex_indices())
480 const auto coinciding_vertex_group =
481 vertex_to_coinciding_vertex_group.find(global_vertex_index);
482 if (coinciding_vertex_group !=
483 vertex_to_coinciding_vertex_group.end())
484 for (
const auto &co_vertex : coinciding_vertex_groups.at(
485 coinciding_vertex_group->second))
486 vertices_on_locally_owned_cells[co_vertex] =
true;
490 const auto add_vertices =
491 [&tria](
const std::vector<bool> &vertices_locally_relevant,
492 DescriptionType &construction_data) {
493 if constexpr (std::is_same_v<DescriptionType,
494 Description<dim, spacedim>>)
496 std::vector<unsigned int> vertices_locally_relevant_indices(
497 vertices_locally_relevant.size());
500 unsigned int vertex_counter = 0;
501 for (
unsigned int i = 0; i < vertices_locally_relevant.size();
503 if (vertices_locally_relevant[i])
505 construction_data.coarse_cell_vertices.push_back(
506 tria.get_vertices()[i]);
507 vertices_locally_relevant_indices[i] = vertex_counter++;
511 for (
auto &cell : construction_data.coarse_cells)
512 for (
unsigned int v = 0; v < cell.vertices.size(); ++v)
514 vertices_locally_relevant_indices[cell.vertices[v]];
518 for (
unsigned int i = 0; i < vertices_locally_relevant.size();
520 if (vertices_locally_relevant[i])
521 construction_data.coarse_cell_vertices.emplace_back(
522 i, tria.get_vertices()[i]);
529 std::vector<std::vector<bool>> cell_marked(tria.n_levels());
530 for (
unsigned int l = 0;
l < tria.n_levels(); ++
l)
531 cell_marked[l].resize(tria.n_raw_cells(l));
533 for (
int level = tria.get_triangulation().n_global_levels() - 1;
539 std::vector<bool> vertices_owned_by_locally_owned_cells_on_level(
541 for (
const auto &cell : tria.cell_iterators_on_level(level))
542 if (construct_multigrid &&
543 (level_subdomain_id_function(cell) == my_rank))
544 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
545 cell, vertices_owned_by_locally_owned_cells_on_level);
547 for (
const auto &cell : tria.active_cell_iterators())
548 if (subdomain_id_function(cell) == my_rank)
549 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
550 cell, vertices_owned_by_locally_owned_cells_on_level);
555 const auto is_locally_relevant_on_level = [&](
const auto &cell) {
556 for (
const auto v : cell->vertex_indices())
557 if (vertices_owned_by_locally_owned_cells_on_level
558 [cell->vertex_index(v)])
564 for (
const auto &cell : tria.cell_iterators_on_level(level))
565 if (is_locally_relevant_on_level(cell))
566 mark_cell_and_its_parents(cell, cell_marked);
571 std::vector<bool> vertices_locally_relevant(tria.n_vertices(),
false);
574 for (
const auto &cell : tria.cell_iterators_on_level(0))
576 if (!cell_marked[cell->level()][cell->index()])
580 ::CellData<dim> cell_data(cell->n_vertices());
581 cell_data.material_id = cell->material_id();
582 cell_data.manifold_id = cell->manifold_id();
583 for (
const auto v : cell->vertex_indices())
584 cell_data.vertices[v] = cell->vertex_index(v);
585 construction_data.coarse_cells.push_back(cell_data);
588 for (
const auto v : cell->vertex_indices())
589 vertices_locally_relevant[cell->vertex_index(v)] =
true;
592 construction_data.coarse_cell_index_to_coarse_cell_id.push_back(
593 cell->id().get_coarse_cell_id());
596 add_vertices(vertices_locally_relevant, construction_data);
601 construction_data.cell_infos.resize(
602 tria.get_triangulation().n_global_levels());
605 std::vector<bool> vertices_owned_by_locally_owned_active_cells(
607 for (
const auto &cell : tria.active_cell_iterators())
608 if (subdomain_id_function(cell) == my_rank)
609 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
610 cell, vertices_owned_by_locally_owned_active_cells);
614 const auto is_locally_relevant_on_active_level = [&](
const auto &cell) {
615 if (cell->is_active())
616 for (
const auto v : cell->vertex_indices())
617 if (vertices_owned_by_locally_owned_active_cells
618 [cell->vertex_index(v)])
623 for (
unsigned int level = 0;
624 level < tria.get_triangulation().n_global_levels();
628 std::vector<bool> vertices_owned_by_locally_owned_cells_on_level(
630 for (
const auto &cell : tria.cell_iterators_on_level(level))
631 if ((construct_multigrid &&
632 (level_subdomain_id_function(cell) == my_rank)) ||
633 (cell->is_active() && subdomain_id_function(cell) == my_rank))
634 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
635 cell, vertices_owned_by_locally_owned_cells_on_level);
639 const auto is_locally_relevant_on_level = [&](
const auto &cell) {
640 for (
const auto v : cell->vertex_indices())
641 if (vertices_owned_by_locally_owned_cells_on_level
642 [cell->vertex_index(v)])
647 auto &level_cell_infos = construction_data.cell_infos[level];
648 for (
const auto &cell : tria.cell_iterators_on_level(level))
651 if (!cell_marked[cell->level()][cell->index()])
654 CellData<dim> cell_info;
657 cell_info.id = cell->id().template to_binary<dim>();
660 for (
const auto f : cell->face_indices())
663 cell->face(f)->boundary_id();
665 cell_info.boundary_ids.emplace_back(f, boundary_ind);
675 for (
const auto line : cell->line_indices())
676 cell_info.manifold_line_ids[line] =
681 for (
const auto f : cell->face_indices())
682 cell_info.manifold_quad_ids[f] =
690 if (is_locally_relevant_on_active_level(cell))
692 cell_info.subdomain_id = subdomain_id_function(cell);
694 cell_info.level_subdomain_id =
695 level_subdomain_id_function(cell);
697 else if (is_locally_relevant_on_level(cell))
699 cell_info.level_subdomain_id =
700 level_subdomain_id_function(cell);
707 level_cell_infos.emplace_back(cell_info);
711 return construction_data;
716 template <
int dim,
int spacedim>
719 const ::Triangulation<dim, spacedim> &tria,
722 const unsigned int my_rank_in)
724 if (
const auto ptria =
729 ExcMessage(
"MPI communicators do not match."));
733 "For creation from a parallel::Triangulation, "
734 "my_rank has to equal the rank of the current process "
735 "in the given communicator."));
747 const unsigned int n_mpi_processes =
749 for (
const auto &cell : tria.active_cell_iterators())
750 Assert(cell->subdomain_id() < n_mpi_processes,
752 "You can't have a cell with subdomain_id of " +
753 std::to_string(cell->subdomain_id()) +
754 " when splitting the triangulation using an MPI "
755 " communicator with only " +
756 std::to_string(n_mpi_processes) +
" processes."));
762 const unsigned int my_rank =
767 const auto subdomain_id_function = [](
const auto &cell) {
768 return cell->subdomain_id();
771 const auto level_subdomain_id_function = [](
const auto &cell) {
772 return cell->level_subdomain_id();
775 std::map<unsigned int, std::vector<unsigned int>>
776 coinciding_vertex_groups;
777 std::map<unsigned int, unsigned int> vertex_to_coinciding_vertex_group;
779 coinciding_vertex_groups,
780 vertex_to_coinciding_vertex_group);
782 return create_description_for_rank<Description<dim, spacedim>>(
784 subdomain_id_function,
785 level_subdomain_id_function,
786 coinciding_vertex_groups,
787 vertex_to_coinciding_vertex_group,
795 template <
int dim,
int spacedim>
799 &serial_grid_generator,
802 const unsigned int)> &serial_grid_partitioner,
804 const int group_size,
808#ifndef DEAL_II_WITH_MPI
809 (void)serial_grid_generator;
810 (void)serial_grid_partitioner;
818 const unsigned int my_rank =
820 const unsigned int group_root = (my_rank / group_size) * group_size;
826 if (my_rank == group_root)
833 typename ::Triangulation<dim, spacedim>::MeshSmoothing
>(
836 spacedim>::limit_level_difference_at_vertices) :
838 serial_grid_generator(tria);
841 serial_grid_partitioner(tria,
comm, group_size);
848 const unsigned int end_group =
856 for (
unsigned int other_rank = group_root + 1; other_rank < end_group;
860 const auto construction_data =
866 std::vector<char> buffer;
870 const auto ierr = MPI_Send(buffer.data(),
892 auto ierr = MPI_Probe(group_root, mpi_tag,
comm, &status);
896 MPI_Get_count(&status, MPI_CHAR, &len);
898 std::vector<char> buf(len);
899 ierr = MPI_Recv(buf.data(),
910 auto construction_data =
911 ::Utilities::template unpack<Description<dim, spacedim>>(
916 construction_data.comm =
comm;
918 return construction_data;
925 template <
int dim,
int spacedim>
932 const bool construct_multigrid =
933 (partition.size() > 0) &&
938 construct_multigrid ==
false ||
942 "Source triangulation has to be set up with "
943 "limit_level_difference_at_vertices if the construction of the "
944 "multigrid hierarchy is requested!"));
946 std::vector<LinearAlgebra::distributed::Vector<double>> partitions_mg;
953 if (construct_multigrid)
955 const auto tria_parallel =
963 partitions_mg[l].reinit(
964 tria_parallel->global_level_cell_index_partitioner(l).lock());
974 partition.update_ghost_values();
979 if (cell->is_locally_owned_on_level())
981 if (cell->is_active())
982 partitions_mg[level][cell->global_level_cell_index()] =
983 partition[cell->global_active_cell_index()];
985 partitions_mg[level][cell->global_level_cell_index()] =
986 partitions_mg[level + 1]
988 ->global_level_cell_index()];
996 partitions_mg[level].update_ghost_values();
1009 template <
int dim,
int spacedim>
1018#ifdef DEAL_II_WITH_MPI
1023 if (partition.size() == 0)
1032 partition.update_ghost_values();
1033 for (
const auto &partition : partitions_mg)
1034 partition.update_ghost_values();
1044 const std::vector<unsigned int> future_owners_of_locally_owned_cells =
1045 [&partition, &partitions_mg]() {
1046 std::set<unsigned int> relevant_process_set;
1048 const unsigned int n_mpi_ranks =
1050 partition.get_mpi_communicator());
1052 for (
unsigned int i = 0; i < partition.locally_owned_size(); ++i)
1054 Assert(
static_cast<unsigned int>(partition.local_element(i)) ==
1055 partition.local_element(i),
1057 "The elements of a partition vector must be integers."));
1059 partition.local_element(i) < n_mpi_ranks,
1061 "The elements of a partition vector must be between zero "
1062 "and the number of processes in the communicator "
1063 "to be used for partitioning the triangulation."));
1064 relevant_process_set.insert(
1065 static_cast<unsigned int>(partition.local_element(i)));
1068 for (
const auto &partition : partitions_mg)
1069 for (
unsigned int i = 0; i < partition.locally_owned_size(); ++i)
1072 static_cast<unsigned int>(partition.local_element(i)) ==
1073 partition.local_element(i),
1075 "The elements of a partition vector must be integers."));
1077 partition.local_element(i) < n_mpi_ranks,
1079 "The elements of a partition vector must be between zero "
1080 "and the number of processes in the communicator "
1081 "to be used for partitioning the triangulation."));
1082 relevant_process_set.insert(
1083 static_cast<unsigned int>(partition.local_element(i)));
1086 return std::vector<unsigned int>(relevant_process_set.begin(),
1087 relevant_process_set.end());
1090 const bool construct_multigrid = (partitions_mg.size() > 0);
1093 (construct_multigrid ?
1095 settings_in | TriangulationDescription::Settings::
1096 construct_multigrid_hierarchy) :
1103 const auto cell_to_future_owner =
1105 if ((cell->is_active() && (cell->is_artificial() ==
false)))
1107 partition[cell->global_active_cell_index()]);
1112 const auto mg_cell_to_future_owner =
1113 [&construct_multigrid,
1115 if (construct_multigrid && (cell->is_artificial_on_level() ==
false))
1117 partitions_mg[cell->level()][cell->global_level_cell_index()]);
1126 std::vector<DescriptionTemp<dim, spacedim>> descriptions_per_rank;
1127 descriptions_per_rank.reserve(
1128 future_owners_of_locally_owned_cells.size());
1130 std::map<unsigned int, std::vector<unsigned int>>
1131 coinciding_vertex_groups;
1132 std::map<unsigned int, unsigned int> vertex_to_coinciding_vertex_group;
1134 coinciding_vertex_groups,
1135 vertex_to_coinciding_vertex_group);
1137 for (
const auto rank : future_owners_of_locally_owned_cells)
1138 descriptions_per_rank.emplace_back(
1139 create_description_for_rank<DescriptionTemp<dim, spacedim>>(
1141 cell_to_future_owner,
1142 mg_cell_to_future_owner,
1143 coinciding_vertex_groups,
1144 vertex_to_coinciding_vertex_group,
1151 DescriptionTemp<dim, spacedim> description_merged;
1152 description_merged.collect(
1153 future_owners_of_locally_owned_cells,
1154 descriptions_per_rank,
1155 partition.get_mpi_communicator(),
1161 description_merged.reduce();
1164 return description_merged.convert(partition.get_mpi_communicator(),
1175#include "grid/tria_description.inst"