33template <
int structdim>
37 , manifold_id(
numbers::flat_manifold_id)
42template <
int structdim>
49 for (
unsigned int i = 0; i <
vertices.size(); ++i)
89 template <
int dim,
int spacedim>
90 struct DescriptionTemp
96 template <
class Archive>
98 serialize(Archive &ar,
const unsigned int )
111 const std::vector<unsigned int> & relevant_processes,
112 const std::vector<DescriptionTemp<dim, spacedim>> &description_temp,
114 const bool vertices_have_unique_ids)
116 const auto create_request = [&](
const unsigned int other_rank) {
117 const auto ptr = std::find(relevant_processes.begin(),
118 relevant_processes.end(),
123 const auto other_rank_index =
124 std::distance(relevant_processes.begin(), ptr);
126 return description_temp[other_rank_index];
129 const auto process_request =
130 [&](
const unsigned int,
131 const DescriptionTemp<dim, spacedim> &request) {
132 this->
merge(request, vertices_have_unique_ids);
136 DescriptionTemp<dim, spacedim>>(relevant_processes,
148 merge(
const DescriptionTemp<dim, spacedim> &other,
149 const bool vertices_have_unique_ids)
152 std::max(other.cell_infos.size(), this->cell_infos.size()));
154 if (vertices_have_unique_ids ==
false)
157 const auto comp = [](
const auto &a,
const auto &b) {
158 const double tolerance = 1e-10;
160 for (
unsigned int i = 0; i < spacedim; ++i)
161 if (
std::abs(a[i] - b[i]) > tolerance)
168 std::map<Point<spacedim>,
unsigned int,
decltype(comp)>
169 map_point_to_local_vertex_index(comp);
174 map_point_to_local_vertex_index[coarse_cell_vertices[i]
178 std::map<unsigned int, unsigned int>
179 map_old_to_new_local_vertex_index;
183 for (
const auto &p : other.coarse_cell_vertices)
184 if (map_point_to_local_vertex_index.find(p.second) ==
185 map_point_to_local_vertex_index.end())
188 map_point_to_local_vertex_index[p.second] =
189 map_old_to_new_local_vertex_index[p.first] = counter++;
192 map_old_to_new_local_vertex_index[p.first] =
193 map_point_to_local_vertex_index[p.second];
196 auto other_coarse_cells_copy = other.coarse_cells;
198 for (
auto &cell : other_coarse_cells_copy)
199 for (
auto &v : cell.vertices)
200 v = map_old_to_new_local_vertex_index[v];
203 other_coarse_cells_copy.begin(),
204 other_coarse_cells_copy.end());
209 other.coarse_cells.begin(),
210 other.coarse_cells.end());
213 other.coarse_cell_vertices.begin(),
214 other.coarse_cell_vertices.end());
219 other.coarse_cell_index_to_coarse_cell_id.begin(),
220 other.coarse_cell_index_to_coarse_cell_id.end());
222 for (
unsigned int i = 0; i < this->
cell_infos.size(); ++i)
223 this->cell_infos[i].
insert(this->cell_infos[i].
end(),
224 other.cell_infos[i].begin(),
225 other.cell_infos[i].end());
241 for (
unsigned int i = 0; i < this->
coarse_cells.size(); ++i)
242 temp.emplace_back(this->coarse_cell_index_to_coarse_cell_id[i],
243 this->coarse_cells[i],
246 std::sort(temp.begin(),
248 [](
const auto &a,
const auto &b) {
249 return std::get<0>(a) < std::get<0>(b);
251 temp.erase(std::unique(temp.begin(),
253 [](
const auto &a,
const auto &b) {
254 return std::get<0>(a) == std::get<0>(b);
257 std::sort(temp.begin(),
259 [](
const auto &a,
const auto &b) {
260 return std::get<2>(a) < std::get<2>(b);
266 for (
unsigned int i = 0; i < temp.size(); ++i)
269 std::get<0>(temp[i]);
277 this->coarse_cell_vertices.end(),
278 [](
const auto &a,
const auto &b) {
279 return a.first < b.first;
283 this->coarse_cell_vertices.end(),
284 [](
const auto &a,
const auto &b) {
285 if (a.first == b.first)
287 Assert(a.second.distance(b.second) < 10e-8,
297 for (
unsigned int i = 0; i < this->
cell_infos.size(); ++i)
299 if (this->cell_infos[i].size() == 0)
302 std::sort(this->cell_infos[i].
begin(),
303 this->cell_infos[i].
end(),
304 [](
const auto &a,
const auto &b) {
308 std::vector<CellData<dim>> temp;
309 temp.push_back(this->cell_infos[i][0]);
311 for (
unsigned int j = 1; j < this->
cell_infos[i].size(); ++j)
312 if (temp.back().id == cell_infos[i][j].id)
314 temp.back().subdomain_id =
316 this->cell_infos[i][j].subdomain_id);
317 temp.back().level_subdomain_id =
318 std::min(temp.back().level_subdomain_id,
319 this->cell_infos[i][j].level_subdomain_id);
323 temp.push_back(this->cell_infos[i][j]);
335 Description<dim, spacedim>
341 Description<dim, spacedim> description;
344 description.comm =
comm;
349 description.smoothing = mesh_smoothing;
351 std::map<unsigned int, unsigned int> map;
355 description.coarse_cell_vertices.push_back(
362 for (
auto &cell : description.coarse_cells)
363 for (
unsigned int v = 0; v < cell.vertices.size(); ++v)
364 cell.vertices[v] = map[cell.vertices[v]];
366 description.coarse_cell_index_to_coarse_cell_id =
367 this->coarse_cell_index_to_coarse_cell_id;
368 description.cell_infos = this->cell_infos;
375 std::vector<std::pair<unsigned int, Point<spacedim>>>
386 template <
int dim,
int spacedim>
388 set_user_flag_and_of_its_parents(
391 cell->set_user_flag();
392 if (cell->level() != 0)
393 set_user_flag_and_of_its_parents(cell->parent());
401 template <
int dim,
int spacedim>
402 class CreateDescriptionFromTriangulationHelper
405 CreateDescriptionFromTriangulationHelper(
406 const ::Triangulation<dim, spacedim> &tria,
408 const typename ::Triangulation<dim, spacedim>::cell_iterator
409 &)> & subdomain_id_function,
411 const typename ::Triangulation<dim, spacedim>::cell_iterator
412 &)> & level_subdomain_id_function,
429 spacedim>::limit_level_difference_at_vertices),
431 "Source triangulation has to be set up with "
432 "limit_level_difference_at_vertices if the construction of the "
433 "multigrid hierarchy is requested!"));
436 tria, coinciding_vertex_groups, vertex_to_coinciding_vertex_group);
439 template <
typename T>
441 create_description_for_rank(
const unsigned int my_rank)
const
445 set_additional_data(construction_data);
450 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells =
451 [
this](
const auto & cell,
452 std::vector<bool> &vertices_owned_by_locally_owned_cells) {
454 for (
const auto v : cell->vertex_indices())
456 vertices_owned_by_locally_owned_cells[cell->vertex_index(
458 const auto coinciding_vertex_group =
460 cell->vertex_index(v));
461 if (coinciding_vertex_group !=
464 coinciding_vertex_group->second))
465 vertices_owned_by_locally_owned_cells[co_vertex] =
true;
470 std::vector<bool> old_user_flags;
485 std::vector<bool> vertices_owned_by_locally_owned_cells_on_level(
488 if (construct_multigrid &&
490 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
491 cell, vertices_owned_by_locally_owned_cells_on_level);
495 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
496 cell, vertices_owned_by_locally_owned_cells_on_level);
501 const auto is_locally_relevant_on_level = [&](
const auto &cell) {
502 for (
const auto v : cell->vertex_indices())
503 if (vertices_owned_by_locally_owned_cells_on_level
504 [cell->vertex_index(v)])
511 if (is_locally_relevant_on_level(cell))
512 set_user_flag_and_of_its_parents(cell);
523 if (!cell->user_flag_set())
528 cell_data.material_id = cell->material_id();
529 cell_data.manifold_id = cell->manifold_id();
530 for (
const auto v : cell->vertex_indices())
531 cell_data.vertices[v] = cell->vertex_index(v);
532 construction_data.coarse_cells.push_back(cell_data);
535 for (
const auto v : cell->vertex_indices())
536 vertices_locally_relevant[cell->vertex_index(v)] =
true;
539 construction_data.coarse_cell_index_to_coarse_cell_id.push_back(
540 cell->id().get_coarse_cell_id());
543 add_vertices(construction_data, vertices_locally_relevant);
548 construction_data.cell_infos.resize(
552 std::vector<bool> vertices_owned_by_locally_owned_active_cells(
556 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
557 cell, vertices_owned_by_locally_owned_active_cells);
561 const auto is_locally_relevant_on_active_level =
562 [&](
const auto &cell) {
563 if (cell->is_active())
564 for (
const auto v : cell->vertex_indices())
565 if (vertices_owned_by_locally_owned_active_cells
566 [cell->vertex_index(v)])
571 for (
unsigned int level = 0;
576 std::vector<bool> vertices_owned_by_locally_owned_cells_on_level(
579 if ((construct_multigrid &&
581 (cell->is_active() &&
583 add_vertices_of_cell_to_vertices_owned_by_locally_owned_cells(
584 cell, vertices_owned_by_locally_owned_cells_on_level);
588 const auto is_locally_relevant_on_level = [&](
const auto &cell) {
589 for (
const auto v : cell->vertex_indices())
590 if (vertices_owned_by_locally_owned_cells_on_level
591 [cell->vertex_index(v)])
596 auto &level_cell_infos = construction_data.cell_infos[
level];
600 if (!(cell->user_flag_set()))
606 cell_info.id = cell->id().template to_binary<dim>();
609 for (
const auto f : cell->face_indices())
612 cell->face(f)->boundary_id();
614 cell_info.boundary_ids.emplace_back(f, boundary_ind);
624 for (
const auto line : cell->line_indices())
625 cell_info.manifold_line_ids[line] =
630 for (
const auto f : cell->face_indices())
631 cell_info.manifold_quad_ids[f] =
637 cell_info.level_subdomain_id =
640 if (is_locally_relevant_on_active_level(cell))
644 cell_info.level_subdomain_id =
647 else if (is_locally_relevant_on_level(cell))
649 cell_info.level_subdomain_id =
657 level_cell_infos.emplace_back(cell_info);
662 .load_user_flags(old_user_flags);
664 return construction_data;
669 set_additional_data(Description<dim, spacedim> &construction_data)
const
671 construction_data.comm =
comm;
673 construction_data.settings =
settings;
677 set_additional_data(DescriptionTemp<dim, spacedim> &)
const
683 add_vertices(Description<dim, spacedim> &construction_data,
684 const std::vector<bool> &vertices_locally_relevant)
const
686 std::vector<unsigned int> vertices_locally_relevant_indices(
687 vertices_locally_relevant.size());
690 unsigned int vertex_counter = 0;
691 for (
unsigned int i = 0; i < vertices_locally_relevant.size(); ++i)
692 if (vertices_locally_relevant[i])
694 construction_data.coarse_cell_vertices.push_back(
696 vertices_locally_relevant_indices[i] = vertex_counter++;
700 for (
auto &cell : construction_data.coarse_cells)
701 for (
unsigned int v = 0; v < cell.vertices.size(); ++v)
703 vertices_locally_relevant_indices[cell.vertices[v]];
707 add_vertices(DescriptionTemp<dim, spacedim> &construction_data,
708 const std::vector<bool> &vertices_locally_relevant)
const
710 for (
unsigned int i = 0; i < vertices_locally_relevant.size(); ++i)
711 if (vertices_locally_relevant[i])
712 construction_data.coarse_cell_vertices.emplace_back(
717 const ::Triangulation<dim, spacedim> &
tria;
719 const typename ::Triangulation<dim, spacedim>::cell_iterator &)>
722 const typename ::Triangulation<dim, spacedim>::cell_iterator &)>
729 std::map<unsigned int, std::vector<unsigned int>>
737 template <
int dim,
int spacedim>
738 Description<dim, spacedim>
740 const ::Triangulation<dim, spacedim> &
tria,
743 const unsigned int my_rank_in)
745 if (
const auto tria_pdt =
dynamic_cast<
748 ExcMessage(
"MPI communicators do not match."));
752 unsigned int my_rank = my_rank_in;
755 ExcMessage(
"Rank has to be smaller than available processes."));
757 if (
auto tria_pdt =
dynamic_cast<
763 "For creation from a parallel::distributed::Triangulation, "
764 "my_rank has to equal global rank."));
768 else if (
auto tria_serial =
769 dynamic_cast<const ::Triangulation<dim, spacedim> *
>(
778 ExcMessage(
"This type of triangulation is not supported!"));
782 return cell->subdomain_id();
786 return cell->level_subdomain_id();
789 return CreateDescriptionFromTriangulationHelper<dim, spacedim>(
795 .template create_description_for_rank<Description<dim, spacedim>>(
801 template <
int dim,
int spacedim>
805 & serial_grid_generator,
808 const unsigned int)> &serial_grid_partitioner,
810 const int group_size,
814#ifndef DEAL_II_WITH_MPI
815 (void)serial_grid_generator;
816 (void)serial_grid_partitioner;
824 const unsigned int my_rank =
826 const unsigned int group_root = (my_rank / group_size) * group_size;
832 if (my_rank == group_root)
839 typename ::Triangulation<dim, spacedim>::MeshSmoothing
>(
842 spacedim>::limit_level_difference_at_vertices) :
844 serial_grid_generator(
tria);
847 serial_grid_partitioner(
tria,
comm, group_size);
854 const unsigned int end_group =
862 for (
unsigned int other_rank = group_root + 1; other_rank < end_group;
866 const auto construction_data =
872 std::vector<char> buffer;
876 const auto ierr = MPI_Send(buffer.data(),
898 auto ierr = MPI_Probe(group_root, mpi_tag,
comm, &status);
902 MPI_Get_count(&status, MPI_CHAR, &len);
904 std::vector<char> buf(len);
905 ierr = MPI_Recv(buf.data(),
916 auto construction_data =
917 ::Utilities::template unpack<Description<dim, spacedim>>(
922 construction_data.comm =
comm;
924 return construction_data;
931 template <
int dim,
int spacedim>
939 (partition.size() > 0) &&
948 "Source triangulation has to be set up with "
949 "limit_level_difference_at_vertices if the construction of the "
950 "multigrid hierarchy is requested!"));
952 std::vector<LinearAlgebra::distributed::Vector<double>> partitions_mg;
956 const auto tria_parallel =
962 partition.update_ghost_values();
967 partitions_mg[l].reinit(
968 tria_parallel->global_level_cell_index_partitioner(l).lock());
974 if (cell->is_locally_owned_on_level() ==
false)
977 if (cell->is_active())
978 partitions_mg[
level][cell->global_level_cell_index()] =
979 partition[cell->global_active_cell_index()];
981 partitions_mg[
level][cell->global_level_cell_index()] =
982 partitions_mg[
level + 1]
983 [cell->child(0)->global_level_cell_index()];
986 partitions_mg[
level].update_ghost_values();
998 template <
int dim,
int spacedim>
1007#ifdef DEAL_II_WITH_MPI
1012 if (partition.size() == 0)
1020 partition.update_ghost_values();
1022 for (
const auto &partition : partitions_mg)
1023 partition.update_ghost_values();
1026 const std::vector<unsigned int> relevant_processes = [&]() {
1027 std::set<unsigned int> relevant_processes;
1029 for (
unsigned int i = 0; i < partition.local_size(); ++i)
1030 relevant_processes.insert(
1031 static_cast<unsigned int>(partition.local_element(i)));
1033 for (
const auto &partition : partitions_mg)
1034 for (
unsigned int i = 0; i < partition.local_size(); ++i)
1035 relevant_processes.insert(
1036 static_cast<unsigned int>(partition.local_element(i)));
1038 return std::vector<unsigned int>(relevant_processes.begin(),
1039 relevant_processes.end());
1052 if ((cell->is_active() && (cell->is_artificial() ==
false)))
1053 return static_cast<unsigned int>(
1054 partition[cell->global_active_cell_index()]);
1062 return static_cast<unsigned int>(
1063 partitions_mg[cell->level()][cell->global_level_cell_index()]);
1068 CreateDescriptionFromTriangulationHelper<dim, spacedim> helper(
1077 std::vector<DescriptionTemp<dim, spacedim>> descriptions_per_rank;
1078 descriptions_per_rank.reserve(relevant_processes.size());
1080 for (
const auto rank : relevant_processes)
1081 descriptions_per_rank.emplace_back(
1082 helper.template create_description_for_rank<
1083 DescriptionTemp<dim, spacedim>>(rank));
1087 DescriptionTemp<dim, spacedim> description_merged;
1088 description_merged.collect(
1090 descriptions_per_rank,
1091 partition.get_mpi_communicator(),
1097 description_merged.reduce();
1100 return description_merged.convert(partition.get_mpi_communicator(),
1111#include "tria_description.inst"
virtual MPI_Comm get_communicator() const
virtual const MeshSmoothing & get_mesh_smoothing() const
void save_user_flags(std::ostream &out) const
const std::vector< Point< spacedim > > & get_vertices() const
virtual unsigned int n_global_levels() const
Triangulation< dim, spacedim > & get_triangulation()
unsigned int n_vertices() const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
IteratorRange< active_cell_iterator > active_cell_iterators() const
IteratorRange< cell_iterator > cell_iterators_on_level(const unsigned int level) const
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
void collect_coinciding_vertices(const Triangulation< dim, spacedim > &tria, std::map< unsigned int, std::vector< unsigned int > > &coinciding_vertex_groups, std::map< unsigned int, unsigned int > &vertex_to_coinciding_vertex_group)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
Description< dim, spacedim > create_description_from_triangulation_in_groups(const std::function< void(::Triangulation< dim, spacedim > &)> &serial_grid_generator, const std::function< void(::Triangulation< dim, spacedim > &, const MPI_Comm &, const unsigned int)> &serial_grid_partitioner, const MPI_Comm &comm, const int group_size=1, const typename Triangulation< dim, spacedim >::MeshSmoothing smoothing=::Triangulation< dim, spacedim >::none, const TriangulationDescription::Settings setting=TriangulationDescription::Settings::default_setting)
Description< dim, spacedim > create_description_from_triangulation(const ::Triangulation< dim, spacedim > &tria, const MPI_Comm &comm, const TriangulationDescription::Settings settings=TriangulationDescription::Settings::default_setting, const unsigned int my_rank_in=numbers::invalid_unsigned_int)
@ construct_multigrid_hierarchy
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
std::vector< unsigned int > selector(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm &comm)
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
T reduce(const T &local_value, const MPI_Comm &comm, const std::function< T(const T &, const T &)> &combiner, const unsigned int root_process=0)
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
constexpr TableIndices< 2 > merge(const TableIndices< 2 > &previous_indices, const unsigned int new_index, const unsigned int position)
const types::boundary_id internal_face_boundary_id
const types::subdomain_id artificial_subdomain_id
static const unsigned int invalid_unsigned_int
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
global_cell_index coarse_cell_id
unsigned int subdomain_id
std::vector< unsigned int > vertices
bool operator==(const CellData< structdim > &other) const
types::manifold_id manifold_id
types::material_id material_id
types::boundary_id boundary_id
CellData(const unsigned int n_vertices=ReferenceCells::get_hypercube< structdim >().n_vertices())
std::vector< CellData< 2 > > boundary_quads
bool check_consistency(const unsigned int dim) const
std::vector< CellData< 1 > > boundary_lines
std::vector< std::pair< unsigned int, Point< spacedim > > > coarse_cell_vertices
const TriangulationDescription::Settings settings
const bool construct_multigrid
std::map< unsigned int, unsigned int > vertex_to_coinciding_vertex_group
const std::function< types::subdomain_id(const typename ::Triangulation< dim, spacedim >::cell_iterator &)> subdomain_id_function
const std::function< types::subdomain_id(const typename ::Triangulation< dim, spacedim >::cell_iterator &)> level_subdomain_id_function
std::vector< types::coarse_cell_id > coarse_cell_index_to_coarse_cell_id
std::vector< std::vector< CellData< dim > > > cell_infos
std::map< unsigned int, std::vector< unsigned int > > coinciding_vertex_groups
const ::Triangulation< dim, spacedim > & tria
std::vector<::CellData< dim > > coarse_cells