43 namespace TriangulationImplementation
52 template <
int dim,
int spacedim>
59 &cell) -> std::uint8_t {
60 if (cell->refine_flag_set())
62 if (cell->coarsen_flag_set())
70 const std::uint8_t &flag) ->
void {
71 cell->clear_coarsen_flag();
72 cell->clear_refine_flag();
74 cell->set_refine_flag();
76 cell->set_coarsen_flag();
79 GridTools::exchange_cell_data_to_ghosts<std::uint8_t>(tria,
90#ifdef DEAL_II_WITH_P4EST
94 template <
int dim,
int spacedim>
96 get_vertex_to_cell_mappings(
98 std::vector<unsigned int> &vertex_touch_count,
99 std::vector<std::list<
101 unsigned int>>> &vertex_to_cell)
103 vertex_touch_count.resize(triangulation.
n_vertices());
104 vertex_to_cell.resize(triangulation.
n_vertices());
106 for (
const auto &cell : triangulation.active_cell_iterators())
109 ++vertex_touch_count[cell->vertex_index(v)];
110 vertex_to_cell[cell->vertex_index(v)].emplace_back(cell, v);
116 template <
int dim,
int spacedim>
118 get_edge_to_cell_mappings(
120 std::vector<unsigned int> &edge_touch_count,
121 std::vector<std::list<
123 unsigned int>>> &edge_to_cell)
130 for (
const auto &cell : triangulation.active_cell_iterators())
131 for (unsigned
int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
133 ++edge_touch_count[cell->line(l)->index()];
134 edge_to_cell[cell->line(l)->index()].emplace_back(cell, l);
144 template <
int dim,
int spacedim>
146 set_vertex_and_cell_info(
148 const std::vector<unsigned int> &vertex_touch_count,
149 const std::vector<std::list<
151 unsigned int>>> &vertex_to_cell,
152 const std::vector<types::global_dof_index>
153 &coarse_cell_to_p4est_tree_permutation,
154 const bool set_vertex_info,
170 if (set_vertex_info ==
true)
171 for (
unsigned int v = 0; v < triangulation.
n_vertices(); ++v)
173 connectivity->vertices[3 * v] = triangulation.
get_vertices()[v][0];
174 connectivity->vertices[3 * v + 1] =
176 connectivity->vertices[3 * v + 2] =
177 (spacedim == 2 ? 0 : triangulation.
get_vertices()[v][2]);
187 endc = triangulation.
end();
188 for (; cell != endc; ++cell)
190 const unsigned int index =
191 coarse_cell_to_p4est_tree_permutation[cell->index()];
195 if (set_vertex_info ==
true)
198 v] = cell->vertex_index(v);
201 v] = cell->vertex_index(v);
207 if (cell->face(f)->at_boundary() == false)
210 coarse_cell_to_p4est_tree_permutation[cell->neighbor(f)->
index()];
214 coarse_cell_to_p4est_tree_permutation[cell->index()];
219 if (cell->face(f)->at_boundary() == false)
225 connectivity->tree_to_face
227 cell->neighbor_of_neighbor(f);
246 connectivity->tree_to_face[
index * 6 + f] =
247 cell->neighbor_of_neighbor(f);
249 unsigned int face_idx_list[2] = {
250 f, cell->neighbor_of_neighbor(f)};
252 cell_list[2] = {cell, cell->neighbor(f)};
253 unsigned int smaller_idx = 0;
255 if (f > cell->neighbor_of_neighbor(f))
258 unsigned int larger_idx = (smaller_idx + 1) % 2;
266 unsigned int g_idx = cell_list[smaller_idx]->vertex_index(
268 face_idx_list[smaller_idx],
270 cell_list[smaller_idx]->face_orientation(
271 face_idx_list[smaller_idx]),
272 cell_list[smaller_idx]->face_flip(
273 face_idx_list[smaller_idx]),
274 cell_list[smaller_idx]->face_rotation(
275 face_idx_list[smaller_idx])));
279 for (
unsigned int i = 0;
280 i < GeometryInfo<dim>::vertices_per_face;
284 cell_list[larger_idx]->vertex_index(
286 face_idx_list[larger_idx], i));
295 connectivity->tree_to_face[
index * 6 + f] += 6 * v;
309 connectivity->ctt_offset[0] = 0;
310 std::partial_sum(vertex_touch_count.begin(),
311 vertex_touch_count.end(),
312 &connectivity->ctt_offset[1]);
315 num_vtt = std::accumulate(vertex_touch_count.begin(),
316 vertex_touch_count.end(),
321 for (
unsigned int v = 0; v < triangulation.
n_vertices(); ++v)
323 Assert(vertex_to_cell[v].
size() == vertex_touch_count[v],
327 std::pair<typename Triangulation<dim, spacedim>::active_cell_iterator,
328 unsigned int>>::const_iterator p =
329 vertex_to_cell[v].begin();
330 for (
unsigned int c = 0; c < vertex_touch_count[v]; ++c, ++p)
332 connectivity->corner_to_tree[connectivity->ctt_offset[v] + c] =
333 coarse_cell_to_p4est_tree_permutation[p->first->index()];
334 connectivity->corner_to_corner[connectivity->ctt_offset[v] + c] =
342 template <
int dim,
int spacedim>
348 Assert(coarse_grid_cell < parallel_forest->connectivity->num_trees,
350 return ((coarse_grid_cell >= parallel_forest->first_local_tree) &&
351 (coarse_grid_cell <= parallel_forest->last_local_tree));
355 template <
int dim,
int spacedim>
357 delete_all_children_and_self(
360 if (cell->has_children())
361 for (
unsigned int c = 0; c < cell->n_children(); ++c)
362 delete_all_children_and_self<dim, spacedim>(cell->child(c));
364 cell->set_coarsen_flag();
369 template <
int dim,
int spacedim>
374 if (cell->has_children())
375 for (
unsigned int c = 0; c < cell->n_children(); ++c)
376 delete_all_children_and_self<dim, spacedim>(cell->child(c));
380 template <
int dim,
int spacedim>
382 determine_level_subdomain_id_recursively(
389 const std::vector<std::vector<bool>> &marked_vertices)
398 if (marked_vertices[dealii_cell->level()]
399 [dealii_cell->vertex_index(v)])
418 if (!used && dealii_cell->is_active() &&
419 dealii_cell->is_artificial() ==
false &&
420 dealii_cell->level() + 1 <
static_cast<int>(marked_vertices.size()))
424 if (marked_vertices[dealii_cell->level() + 1]
425 [dealii_cell->vertex_index(v)])
434 if (!used && dealii_cell->is_active() &&
435 dealii_cell->is_artificial() ==
false && dealii_cell->level() > 0)
439 if (marked_vertices[dealii_cell->level() - 1]
440 [dealii_cell->vertex_index(v)])
451 &forest, tree_index, &p4est_cell, my_subdomain);
452 Assert((owner != -2) && (owner != -1),
454 dealii_cell->set_level_subdomain_id(owner);
458 if (dealii_cell->has_children())
462 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
470 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
473 determine_level_subdomain_id_recursively<dim, spacedim>(
476 dealii_cell->child(c),
486 template <
int dim,
int spacedim>
488 match_tree_recursively(
496 if (sc_array_bsearch(
const_cast<sc_array_t *
>(&tree.quadrants),
502 delete_all_children<dim, spacedim>(dealii_cell);
503 if (dealii_cell->is_active())
504 dealii_cell->set_subdomain_id(my_subdomain);
513 if (dealii_cell->is_active())
514 dealii_cell->set_refine_flag();
519 for (
unsigned int c = 0;
520 c < GeometryInfo<dim>::max_children_per_cell;
527 for (
unsigned int c = 0;
528 c < GeometryInfo<dim>::max_children_per_cell;
533 &p4est_child[c]) ==
false)
539 delete_all_children<dim, spacedim>(dealii_cell->child(c));
540 dealii_cell->child(c)->recursively_set_subdomain_id(
547 match_tree_recursively<dim, spacedim>(tree,
548 dealii_cell->child(c),
558 template <
int dim,
int spacedim>
561 const ::Triangulation<dim, spacedim> *tria,
562 unsigned int dealii_index,
566 const int l = ghost_quadrant.level;
568 for (
int i = 0; i <
l; ++i)
573 if (cell->is_active())
575 cell->clear_coarsen_flag();
576 cell->set_refine_flag();
583 dealii_index = cell->child_index(child_id);
589 if (cell->has_children())
590 delete_all_children<dim, spacedim>(cell);
593 cell->clear_coarsen_flag();
594 cell->set_subdomain_id(ghost_owner);
599 class PartitionSearch
607 PartitionSearch(
const PartitionSearch<dim> &other) =
delete;
609 PartitionSearch<dim> &
610 operator=(
const PartitionSearch<dim> &other) =
delete;
666 quad_length_on_level);
669 initialize_mapping();
672 map_real_to_unit_cell(
const Point<dim> &p)
const;
675 is_in_this_quadrant(
const Point<dim> &p)
const;
678 std::vector<Point<dim>> cell_vertices;
686 bool are_vertices_initialized;
688 bool is_reference_mapping_initialized;
694 QuadrantData quadrant_data;
701 PartitionSearch<dim>::local_quadrant_fn(
714 PartitionSearch<dim> *this_object =
715 reinterpret_cast<PartitionSearch<dim> *
>(forest->user_pointer);
719 quad_length_on_level =
721 (dim == 2 ? P4EST_MAXLEVEL : P8EST_MAXLEVEL)) -
725 this_object->quadrant_data.set_cell_vertices(forest,
728 quad_length_on_level);
731 this_object->quadrant_data.initialize_mapping();
741 PartitionSearch<dim>::local_point_fn(
754 PartitionSearch<dim> *this_object =
755 reinterpret_cast<PartitionSearch<dim> *
>(forest->user_pointer);
758 double *this_point_dptr =
static_cast<double *
>(
point);
761 (dim == 2 ?
Point<dim>(this_point_dptr[0], this_point_dptr[1]) :
762 Point<dim>(this_point_dptr[0],
764 this_point_dptr[2]));
767 const bool is_in_this_quadrant =
768 this_object->quadrant_data.is_in_this_quadrant(this_point);
772 if (!is_in_this_quadrant)
781 if (rank_begin < rank_end)
789 this_point_dptr[dim] =
static_cast<double>(rank_begin);
799 PartitionSearch<dim>::QuadrantData::is_in_this_quadrant(
802 const Point<dim> p_ref = map_real_to_unit_cell(p);
811 PartitionSearch<dim>::QuadrantData::map_real_to_unit_cell(
814 Assert(is_reference_mapping_initialized,
816 "Cell vertices and mapping coefficients must be fully "
817 "initialized before transforming a point to the unit cell."));
823 for (
unsigned int alpha = 0;
824 alpha < GeometryInfo<dim>::vertices_per_cell;
830 p_out += (quadrant_mapping_matrix(alpha, 0) +
831 quadrant_mapping_matrix(alpha, 1) * p(0) +
832 quadrant_mapping_matrix(alpha, 2) * p(1) +
833 quadrant_mapping_matrix(alpha, 3) * p(0) * p(1)) *
839 for (
unsigned int alpha = 0;
840 alpha < GeometryInfo<dim>::vertices_per_cell;
846 p_out += (quadrant_mapping_matrix(alpha, 0) +
847 quadrant_mapping_matrix(alpha, 1) * p(0) +
848 quadrant_mapping_matrix(alpha, 2) * p(1) +
849 quadrant_mapping_matrix(alpha, 3) * p(2) +
850 quadrant_mapping_matrix(alpha, 4) * p(0) * p(1) +
851 quadrant_mapping_matrix(alpha, 5) * p(1) * p(2) +
852 quadrant_mapping_matrix(alpha, 6) * p(0) * p(2) +
853 quadrant_mapping_matrix(alpha, 7) * p(0) * p(1) * p(2)) *
863 PartitionSearch<dim>::QuadrantData::QuadrantData()
865 , quadrant_mapping_matrix(
GeometryInfo<dim>::vertices_per_cell,
867 , are_vertices_initialized(false)
868 , is_reference_mapping_initialized(false)
875 PartitionSearch<dim>::QuadrantData::initialize_mapping()
878 are_vertices_initialized,
880 "Cell vertices must be initialized before the cell mapping can be filled."));
887 for (
unsigned int alpha = 0;
888 alpha < GeometryInfo<dim>::vertices_per_cell;
892 point_matrix(0, alpha) = 1;
893 point_matrix(1, alpha) = cell_vertices[alpha](0);
894 point_matrix(2, alpha) = cell_vertices[alpha](1);
895 point_matrix(3, alpha) =
896 cell_vertices[alpha](0) * cell_vertices[alpha](1);
903 quadrant_mapping_matrix.invert(point_matrix);
907 for (
unsigned int alpha = 0;
908 alpha < GeometryInfo<dim>::vertices_per_cell;
912 point_matrix(0, alpha) = 1;
913 point_matrix(1, alpha) = cell_vertices[alpha](0);
914 point_matrix(2, alpha) = cell_vertices[alpha](1);
915 point_matrix(3, alpha) = cell_vertices[alpha](2);
916 point_matrix(4, alpha) =
917 cell_vertices[alpha](0) * cell_vertices[alpha](1);
918 point_matrix(5, alpha) =
919 cell_vertices[alpha](1) * cell_vertices[alpha](2);
920 point_matrix(6, alpha) =
921 cell_vertices[alpha](0) * cell_vertices[alpha](2);
922 point_matrix(7, alpha) = cell_vertices[alpha](0) *
923 cell_vertices[alpha](1) *
924 cell_vertices[alpha](2);
931 quadrant_mapping_matrix.invert(point_matrix);
934 is_reference_mapping_initialized =
true;
941 PartitionSearch<2>::QuadrantData::set_cell_vertices(
946 quad_length_on_level)
948 constexpr unsigned int dim = 2;
952 double corner_point[dim + 1] = {0};
955 const auto copy_vertex = [&](
unsigned int vertex_index) ->
void {
957 for (
unsigned int d = 0;
d < dim; ++
d)
959 cell_vertices[vertex_index](
d) = corner_point[d];
969 unsigned int vertex_index = 0;
971 forest->connectivity, which_tree, quadrant->x, quadrant->y, corner_point);
974 copy_vertex(vertex_index);
981 forest->connectivity,
983 quadrant->x + quad_length_on_level,
988 copy_vertex(vertex_index);
995 forest->connectivity,
998 quadrant->y + quad_length_on_level,
1002 copy_vertex(vertex_index);
1009 forest->connectivity,
1011 quadrant->x + quad_length_on_level,
1012 quadrant->y + quad_length_on_level,
1016 copy_vertex(vertex_index);
1018 are_vertices_initialized =
true;
1025 PartitionSearch<3>::QuadrantData::set_cell_vertices(
1030 quad_length_on_level)
1032 constexpr unsigned int dim = 3;
1034 double corner_point[dim] = {0};
1037 auto copy_vertex = [&](
unsigned int vertex_index) ->
void {
1039 for (
unsigned int d = 0;
d < dim; ++
d)
1041 cell_vertices[vertex_index](
d) = corner_point[d];
1043 corner_point[
d] = 0;
1051 unsigned int vertex_index = 0;
1053 forest->connectivity,
1061 copy_vertex(vertex_index);
1069 forest->connectivity,
1071 quadrant->x + quad_length_on_level,
1077 copy_vertex(vertex_index);
1084 forest->connectivity,
1087 quadrant->y + quad_length_on_level,
1092 copy_vertex(vertex_index);
1099 forest->connectivity,
1101 quadrant->x + quad_length_on_level,
1102 quadrant->y + quad_length_on_level,
1107 copy_vertex(vertex_index);
1114 forest->connectivity,
1118 quadrant->z + quad_length_on_level,
1122 copy_vertex(vertex_index);
1129 forest->connectivity,
1131 quadrant->x + quad_length_on_level,
1133 quadrant->z + quad_length_on_level,
1137 copy_vertex(vertex_index);
1144 forest->connectivity,
1147 quadrant->y + quad_length_on_level,
1148 quadrant->z + quad_length_on_level,
1152 copy_vertex(vertex_index);
1159 forest->connectivity,
1161 quadrant->x + quad_length_on_level,
1162 quadrant->y + quad_length_on_level,
1163 quadrant->z + quad_length_on_level,
1167 copy_vertex(vertex_index);
1170 are_vertices_initialized =
true;
1180 template <
int dim,
int spacedim>
1181 class RefineAndCoarsenList
1185 const std::vector<types::global_dof_index>
1186 &p4est_tree_to_coarse_cell_permutation,
1214 pointers_are_at_end()
const;
1217 std::vector<typename internal::p4est::types<dim>::quadrant> refine_list;
1218 typename std::vector<typename internal::p4est::types<dim>::quadrant>::
1219 const_iterator current_refine_pointer;
1221 std::vector<typename internal::p4est::types<dim>::quadrant> coarsen_list;
1222 typename std::vector<typename internal::p4est::types<dim>::quadrant>::
1223 const_iterator current_coarsen_pointer;
1234 template <
int dim,
int spacedim>
1236 RefineAndCoarsenList<dim, spacedim>::pointers_are_at_end()
const
1238 return ((current_refine_pointer == refine_list.end()) &&
1239 (current_coarsen_pointer == coarsen_list.end()));
1244 template <
int dim,
int spacedim>
1245 RefineAndCoarsenList<dim, spacedim>::RefineAndCoarsenList(
1247 const std::vector<types::global_dof_index>
1248 &p4est_tree_to_coarse_cell_permutation,
1252 unsigned int n_refine_flags = 0, n_coarsen_flags = 0;
1253 for (
const auto &cell : triangulation.active_cell_iterators())
1256 if (cell->subdomain_id() != my_subdomain)
1259 if (cell->refine_flag_set())
1261 else if (cell->coarsen_flag_set())
1265 refine_list.reserve(n_refine_flags);
1266 coarsen_list.reserve(n_coarsen_flags);
1276 for (
unsigned int c = 0; c < triangulation.
n_cells(0); ++c)
1278 unsigned int coarse_cell_index =
1279 p4est_tree_to_coarse_cell_permutation[c];
1282 &triangulation, 0, coarse_cell_index);
1288 p4est_cell.p.which_tree = c;
1289 build_lists(cell, p4est_cell, my_subdomain);
1297 for (
unsigned int i = 1; i < refine_list.size(); ++i)
1298 Assert(refine_list[i].p.which_tree >= refine_list[i - 1].p.which_tree,
1300 for (
unsigned int i = 1; i < coarsen_list.size(); ++i)
1301 Assert(coarsen_list[i].p.which_tree >= coarsen_list[i - 1].p.which_tree,
1304 current_refine_pointer = refine_list.begin();
1305 current_coarsen_pointer = coarsen_list.begin();
1310 template <
int dim,
int spacedim>
1312 RefineAndCoarsenList<dim, spacedim>::build_lists(
1317 if (cell->is_active())
1319 if (cell->subdomain_id() == my_subdomain)
1321 if (cell->refine_flag_set())
1322 refine_list.push_back(p4est_cell);
1323 else if (cell->coarsen_flag_set())
1324 coarsen_list.push_back(p4est_cell);
1331 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
1336 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
1339 p4est_child[c].p.which_tree = p4est_cell.p.which_tree;
1340 build_lists(cell->child(c), p4est_child[c], my_subdomain);
1346 template <
int dim,
int spacedim>
1348 RefineAndCoarsenList<dim, spacedim>::refine_callback(
1353 RefineAndCoarsenList<dim, spacedim> *this_object =
1354 reinterpret_cast<RefineAndCoarsenList<dim, spacedim> *
>(
1355 forest->user_pointer);
1359 if (this_object->current_refine_pointer == this_object->refine_list.end())
1362 Assert(coarse_cell_index <=
1363 this_object->current_refine_pointer->p.which_tree,
1368 if (coarse_cell_index < this_object->current_refine_pointer->p.which_tree)
1372 Assert(coarse_cell_index <=
1373 this_object->current_refine_pointer->p.which_tree,
1379 quadrant, &*this_object->current_refine_pointer) <= 0,
1384 quadrant, &*this_object->current_refine_pointer))
1386 ++this_object->current_refine_pointer;
1396 template <
int dim,
int spacedim>
1398 RefineAndCoarsenList<dim, spacedim>::coarsen_callback(
1403 RefineAndCoarsenList<dim, spacedim> *this_object =
1404 reinterpret_cast<RefineAndCoarsenList<dim, spacedim> *
>(
1405 forest->user_pointer);
1409 if (this_object->current_coarsen_pointer == this_object->coarsen_list.end())
1412 Assert(coarse_cell_index <=
1413 this_object->current_coarsen_pointer->p.which_tree,
1418 if (coarse_cell_index < this_object->current_coarsen_pointer->p.which_tree)
1422 Assert(coarse_cell_index <=
1423 this_object->current_coarsen_pointer->p.which_tree,
1429 children[0], &*this_object->current_coarsen_pointer) <= 0,
1435 children[0], &*this_object->current_coarsen_pointer))
1438 ++this_object->current_coarsen_pointer;
1442 for (
unsigned int c = 1; c < GeometryInfo<dim>::max_children_per_cell;
1446 children[c], &*this_object->current_coarsen_pointer),
1448 ++this_object->current_coarsen_pointer;
1466 template <
int dim,
int spacedim>
1467 class PartitionWeights
1475 explicit PartitionWeights(
const std::vector<unsigned int> &cell_weights);
1490 std::vector<unsigned int> cell_weights_list;
1491 std::vector<unsigned int>::const_iterator current_pointer;
1495 template <
int dim,
int spacedim>
1496 PartitionWeights<dim, spacedim>::PartitionWeights(
1497 const std::vector<unsigned int> &cell_weights)
1498 : cell_weights_list(cell_weights)
1502 current_pointer = cell_weights_list.begin();
1506 template <
int dim,
int spacedim>
1508 PartitionWeights<dim, spacedim>::cell_weight(
1517 PartitionWeights<dim, spacedim> *this_object =
1518 reinterpret_cast<PartitionWeights<dim, spacedim> *
>(forest->user_pointer);
1520 Assert(this_object->current_pointer >=
1521 this_object->cell_weights_list.begin(),
1523 Assert(this_object->current_pointer < this_object->cell_weights_list.end(),
1529 const unsigned int weight = *this_object->current_pointer;
1530 ++this_object->current_pointer;
1532 Assert(weight <
static_cast<unsigned int>(std::numeric_limits<int>::max()),
1533 ExcMessage(
"p4est uses 'signed int' to represent the partition "
1534 "weights for cells. The weight provided here exceeds "
1535 "the maximum value represented as a 'signed int'."));
1536 return static_cast<int>(weight);
1539 template <
int dim,
int spacedim>
1540 using cell_relation_t =
typename std::pair<
1541 typename ::Triangulation<dim, spacedim>::cell_iterator,
1553 template <
int dim,
int spacedim>
1555 add_single_cell_relation(
1556 std::vector<cell_relation_t<dim, spacedim>> &cell_rel,
1557 const typename ::internal::p4est::types<dim>::tree &tree,
1558 const unsigned int idx,
1562 const unsigned int local_quadrant_index = tree.quadrants_offset + idx;
1568 cell_rel[local_quadrant_index] = std::make_pair(dealii_cell, status);
1582 template <
int dim,
int spacedim>
1584 update_cell_relations_recursively(
1585 std::vector<cell_relation_t<dim, spacedim>> &cell_rel,
1586 const typename ::internal::p4est::types<dim>::tree &tree,
1588 const typename ::internal::p4est::types<dim>::quadrant &p4est_cell)
1591 const int idx = sc_array_bsearch(
1592 const_cast<sc_array_t *
>(&tree.quadrants),
1597 const_cast<typename ::internal::p4est::types<dim>::tree *
>(
1599 &p4est_cell) ==
false))
1604 const bool p4est_has_children = (idx == -1);
1605 if (p4est_has_children && dealii_cell->has_children())
1608 typename ::internal::p4est::types<dim>::quadrant
1611 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
1616 &p4est_cell, p4est_child);
1618 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
1621 update_cell_relations_recursively<dim, spacedim>(
1622 cell_rel, tree, dealii_cell->child(c), p4est_child[c]);
1625 else if (!p4est_has_children && !dealii_cell->has_children())
1629 add_single_cell_relation<dim, spacedim>(
1632 else if (p4est_has_children)
1640 typename ::internal::p4est::types<dim>::quadrant
1642 for (
unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
1647 &p4est_cell, p4est_child);
1655 for (
unsigned int i = 0; i < GeometryInfo<dim>::max_children_per_cell;
1658 child_idx = sc_array_bsearch(
1659 const_cast<sc_array_t *
>(&tree.quadrants),
1666 add_single_cell_relation<dim, spacedim>(
1667 cell_rel, tree, child_idx, dealii_cell, cell_status);
1675 add_single_cell_relation<dim, spacedim>(
1689 namespace distributed
1692 template <
int dim,
int spacedim>
1704 (settings & construct_multigrid_hierarchy) ?
1708 Triangulation<dim, spacedim>::limit_level_difference_at_vertices) :
1711 , settings(settings)
1712 , triangulation_has_content(false)
1713 , connectivity(
nullptr)
1714 , parallel_forest(
nullptr)
1716 parallel_ghost =
nullptr;
1721 template <
int dim,
int spacedim>
1743 template <
int dim,
int spacedim>
1746 const
std::vector<
Point<spacedim>> &vertices,
1753 vertices, cells, subcelldata);
1756 const typename ::Triangulation<dim, spacedim>::DistortedCellList
1765 this->all_reference_cells_are_hyper_cube(),
1767 "The class parallel::distributed::Triangulation only supports meshes "
1768 "consisting only of hypercube-like cells."));
1773 triangulation_has_content =
true;
1775 setup_coarse_cell_to_p4est_tree_permutation();
1777 copy_new_triangulation_to_p4est(std::integral_constant<int, dim>());
1781 copy_local_forest_to_triangulation();
1790 this->update_periodic_face_map();
1791 this->update_number_cache();
1796 template <
int dim,
int spacedim>
1807 template <
int dim,
int spacedim>
1811 triangulation_has_content =
false;
1813 if (parallel_ghost !=
nullptr)
1817 parallel_ghost =
nullptr;
1820 if (parallel_forest !=
nullptr)
1823 parallel_forest =
nullptr;
1826 if (connectivity !=
nullptr)
1830 connectivity =
nullptr;
1833 coarse_cell_to_p4est_tree_permutation.resize(0);
1834 p4est_tree_to_coarse_cell_permutation.resize(0);
1838 this->update_number_cache();
1843 template <
int dim,
int spacedim>
1854 template <
int dim,
int spacedim>
1865 template <
int dim,
int spacedim>
1871 *previous_global_first_quadrant)
1873 Assert(this->data_serializer.sizes_fixed_cumulative.size() > 0,
1877 this->data_serializer.dest_data_fixed.resize(
1878 parallel_forest->local_num_quadrants *
1879 this->data_serializer.sizes_fixed_cumulative.back());
1882 typename ::internal::p4est::types<dim>::transfer_context
1886 parallel_forest->global_first_quadrant,
1887 previous_global_first_quadrant,
1888 parallel_forest->mpicomm,
1890 this->data_serializer.dest_data_fixed.data(),
1891 this->data_serializer.src_data_fixed.data(),
1892 this->data_serializer.sizes_fixed_cumulative.back());
1894 if (this->data_serializer.variable_size_data_stored)
1897 this->data_serializer.dest_sizes_variable.resize(
1898 parallel_forest->local_num_quadrants);
1903 parallel_forest->global_first_quadrant,
1904 previous_global_first_quadrant,
1905 parallel_forest->mpicomm,
1907 this->data_serializer.dest_sizes_variable.data(),
1908 this->data_serializer.src_sizes_variable.data(),
1909 sizeof(
unsigned int));
1915 this->data_serializer.src_data_fixed.clear();
1916 this->data_serializer.src_data_fixed.shrink_to_fit();
1918 if (this->data_serializer.variable_size_data_stored)
1921 this->data_serializer.dest_data_variable.resize(
1922 std::accumulate(this->data_serializer.dest_sizes_variable.begin(),
1923 this->data_serializer.dest_sizes_variable.end(),
1924 std::vector<int>::size_type(0)));
1928 parallel_forest->global_first_quadrant,
1929 previous_global_first_quadrant,
1930 parallel_forest->mpicomm,
1932 this->data_serializer.dest_data_variable.data(),
1933 this->data_serializer.dest_sizes_variable.data(),
1934 this->data_serializer.src_data_variable.data(),
1935 this->data_serializer.src_sizes_variable.data());
1938 this->data_serializer.src_sizes_variable.clear();
1939 this->data_serializer.src_sizes_variable.shrink_to_fit();
1940 this->data_serializer.src_data_variable.clear();
1941 this->data_serializer.src_data_variable.shrink_to_fit();
1947 template <
int dim,
int spacedim>
1950 spacedim>::setup_coarse_cell_to_p4est_tree_permutation()
1955 coarse_cell_to_p4est_tree_permutation.resize(this->n_cells(0));
1957 cell_connectivity, coarse_cell_to_p4est_tree_permutation);
1959 p4est_tree_to_coarse_cell_permutation =
1965 template <
int dim,
int spacedim>
1968 const
std::
string &file_basename)
const
1970 Assert(parallel_forest !=
nullptr,
1971 ExcMessage(
"Can't produce output when no forest is created yet."));
1975 "To use this function the triangulation's flag "
1976 "Settings::communicate_vertices_to_p4est must be set."));
1979 parallel_forest,
nullptr, file_basename.c_str());
1984 template <
int dim,
int spacedim>
1987 const
std::
string &file_basename)
const
1990 this->cell_attached_data.n_attached_deserialize == 0,
1992 "Not all SolutionTransfer objects have been deserialized after the last call to load()."));
1993 Assert(this->n_cells() > 0,
1994 ExcMessage(
"Can not save() an empty Triangulation."));
2000 this->signals.pre_distributed_save();
2002 if (this->my_subdomain == 0)
2004 std::string fname = file_basename +
".info";
2005 std::ofstream f(fname);
2006 f <<
"version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_coarse_cells"
2010 << this->cell_attached_data.pack_callbacks_fixed.size() <<
" "
2011 << this->cell_attached_data.pack_callbacks_variable.size() <<
" "
2012 << this->n_cells(0) << std::endl;
2016 for ([[maybe_unused]]
const auto &cell_rel : this->local_cell_relations)
2018 Assert((cell_rel.second ==
2024 this->save_attached_data(parallel_forest->global_first_quadrant[myrank],
2025 parallel_forest->global_num_quadrants,
2033 this->signals.post_distributed_save();
2038 template <
int dim,
int spacedim>
2043 this->n_cells() > 0,
2045 "load() only works if the Triangulation already contains a coarse mesh!"));
2047 this->n_levels() == 1,
2049 "Triangulation may only contain coarse cells when calling load()."));
2055 this->signals.pre_distributed_load();
2057 if (parallel_ghost !=
nullptr)
2061 parallel_ghost =
nullptr;
2064 parallel_forest =
nullptr;
2067 connectivity =
nullptr;
2069 unsigned int version, numcpus, attached_count_fixed,
2070 attached_count_variable, n_coarse_cells;
2072 std::string fname = std::string(file_basename) +
".info";
2073 std::ifstream f(fname);
2075 std::string firstline;
2076 getline(f, firstline);
2077 f >> version >> numcpus >> attached_count_fixed >>
2078 attached_count_variable >> n_coarse_cells;
2082 ExcMessage(
"Incompatible version found in .info file."));
2083 Assert(this->n_cells(0) == n_coarse_cells,
2084 ExcMessage(
"Number of coarse cells differ!"));
2088 this->cell_attached_data.n_attached_data_sets = 0;
2089 this->cell_attached_data.n_attached_deserialize =
2090 attached_count_fixed + attached_count_variable;
2093 file_basename.c_str(),
2094 this->mpi_communicator,
2112 copy_local_forest_to_triangulation();
2122 this->load_attached_data(parallel_forest->global_first_quadrant[myrank],
2123 parallel_forest->global_num_quadrants,
2124 parallel_forest->local_num_quadrants,
2126 attached_count_fixed,
2127 attached_count_variable);
2130 this->signals.post_distributed_load();
2132 this->update_periodic_face_map();
2133 this->update_number_cache();
2138 template <
int dim,
int spacedim>
2141 const typename ::
internal::p4est::
types<dim>::forest *forest)
2143 Assert(this->n_cells() > 0,
2145 "load() only works if the Triangulation already contains "
2147 Assert(this->n_cells() == forest->trees->elem_count,
2149 "Coarse mesh of the Triangulation does not match the one "
2150 "of the provided forest!"));
2153 if (parallel_ghost !=
nullptr)
2157 parallel_ghost =
nullptr;
2160 parallel_forest =
nullptr;
2166 typename ::internal::p4est::types<dim>::forest *temp =
2167 const_cast<typename ::internal::p4est::types<dim>::forest *
>(
2171 parallel_forest->connectivity = connectivity;
2172 parallel_forest->user_pointer =
this;
2176 copy_local_forest_to_triangulation();
2185 this->update_periodic_face_map();
2186 this->update_number_cache();
2191 template <
int dim,
int spacedim>
2195 Assert(parallel_forest !=
nullptr,
2197 "Can't produce a check sum when no forest is created yet."));
2202# if !DEAL_II_P4EST_VERSION_GTE(2, 8, 6, 0)
2218 template <
int dim,
int spacedim>
2220 const typename ::internal::p4est::types<dim>::forest
2223 Assert(parallel_forest !=
nullptr,
2224 ExcMessage(
"The forest has not been allocated yet."));
2225 return parallel_forest;
2230 template <
int dim,
int spacedim>
2232 typename ::internal::p4est::types<dim>::tree
2234 const int dealii_coarse_cell_index)
const
2236 const unsigned int tree_index =
2237 coarse_cell_to_p4est_tree_permutation[dealii_coarse_cell_index];
2238 typename ::internal::p4est::types<dim>::tree *tree =
2239 static_cast<typename ::internal::p4est::types<dim>::tree *
>(
2240 sc_array_index(parallel_forest->trees, tree_index));
2254 std::integral_constant<int, 2>)
2256 const unsigned int dim = 2, spacedim = 2;
2264 std::vector<unsigned int> vertex_touch_count;
2266 std::list<std::pair<Triangulation<dim, spacedim>::active_cell_iterator,
2269 get_vertex_to_cell_mappings(*
this, vertex_touch_count, vertex_to_cell);
2270 const ::internal::p4est::types<2>::locidx num_vtt =
2271 std::accumulate(vertex_touch_count.begin(),
2272 vertex_touch_count.end(),
2278 const bool set_vertex_info = this->are_vertices_communicated_to_p4est();
2281 (set_vertex_info ==
true ? this->n_vertices() : 0),
2286 set_vertex_and_cell_info(*
this,
2289 coarse_cell_to_p4est_tree_permutation,
2293 Assert(p4est_connectivity_is_valid(connectivity) == 1,
2298 this->mpi_communicator,
2315 std::integral_constant<int, 2>)
2317 const unsigned int dim = 2, spacedim = 3;
2325 std::vector<unsigned int> vertex_touch_count;
2327 std::list<std::pair<Triangulation<dim, spacedim>::active_cell_iterator,
2330 get_vertex_to_cell_mappings(*
this, vertex_touch_count, vertex_to_cell);
2331 const ::internal::p4est::types<2>::locidx num_vtt =
2332 std::accumulate(vertex_touch_count.begin(),
2333 vertex_touch_count.end(),
2339 const bool set_vertex_info = this->are_vertices_communicated_to_p4est();
2342 (set_vertex_info ==
true ? this->n_vertices() : 0),
2347 set_vertex_and_cell_info(*
this,
2350 coarse_cell_to_p4est_tree_permutation,
2354 Assert(p4est_connectivity_is_valid(connectivity) == 1,
2359 this->mpi_communicator,
2374 std::integral_constant<int, 3>)
2376 const int dim = 3, spacedim = 3;
2384 std::vector<unsigned int> vertex_touch_count;
2385 std::vector<std::list<
2386 std::pair<Triangulation<3>::active_cell_iterator,
unsigned int>>>
2388 get_vertex_to_cell_mappings(*
this, vertex_touch_count, vertex_to_cell);
2389 const ::internal::p4est::types<2>::locidx num_vtt =
2390 std::accumulate(vertex_touch_count.begin(),
2391 vertex_touch_count.end(),
2394 std::vector<unsigned int> edge_touch_count;
2395 std::vector<std::list<
2396 std::pair<Triangulation<3>::active_cell_iterator,
unsigned int>>>
2398 get_edge_to_cell_mappings(*
this, edge_touch_count, edge_to_cell);
2399 const ::internal::p4est::types<2>::locidx num_ett =
2400 std::accumulate(edge_touch_count.begin(), edge_touch_count.end(), 0u);
2403 const bool set_vertex_info = this->are_vertices_communicated_to_p4est();
2406 (set_vertex_info ==
true ? this->n_vertices() : 0),
2408 this->n_active_lines(),
2413 set_vertex_and_cell_info(*
this,
2416 coarse_cell_to_p4est_tree_permutation,
2445 const unsigned int deal_to_p4est_line_index[12] = {
2446 4, 5, 0, 1, 6, 7, 2, 3, 8, 9, 10, 11};
2448 for (
const auto &cell : this->active_cell_iterators())
2450 const unsigned int index =
2451 coarse_cell_to_p4est_tree_permutation[cell->index()];
2452 for (
unsigned int e = 0;
e < cell->n_lines(); ++
e)
2454 deal_to_p4est_line_index[e]] =
2455 cell->line(e)->index();
2460 connectivity->ett_offset[0] = 0;
2461 std::partial_sum(edge_touch_count.begin(),
2462 edge_touch_count.end(),
2463 &connectivity->ett_offset[1]);
2465 Assert(connectivity->ett_offset[this->n_active_lines()] == num_ett,
2468 for (
unsigned int v = 0; v < this->n_active_lines(); ++v)
2470 Assert(edge_to_cell[v].
size() == edge_touch_count[v],
2474 std::pair<Triangulation<dim, spacedim>::active_cell_iterator,
2476 edge_to_cell[v].begin();
2477 for (
unsigned int c = 0; c < edge_touch_count[v]; ++c, ++p)
2479 connectivity->edge_to_tree[connectivity->ett_offset[v] + c] =
2480 coarse_cell_to_p4est_tree_permutation[p->first->index()];
2481 connectivity->edge_to_edge[connectivity->ett_offset[v] + c] =
2482 deal_to_p4est_line_index[p->second];
2486 Assert(p8est_connectivity_is_valid(connectivity) == 1,
2491 this->mpi_communicator,
2508 template <
int dim,
int spacedim>
2510 enforce_mesh_balance_over_periodic_boundaries(
2516 std::vector<bool> flags_before[2];
2520 std::vector<unsigned int> topological_vertex_numbering(
2522 for (
unsigned int i = 0; i < topological_vertex_numbering.size(); ++i)
2523 topological_vertex_numbering[i] = i;
2541 using cell_iterator =
2543 for (
const auto &it : tria.get_periodic_face_map())
2545 const cell_iterator &cell_1 = it.first.first;
2546 const unsigned int face_no_1 = it.first.second;
2547 const cell_iterator &cell_2 = it.second.first.first;
2548 const unsigned int face_no_2 = it.second.first.second;
2549 const auto combined_orientation = it.second.second;
2551 if (cell_1->level() == cell_2->level())
2553 for (
const unsigned int v :
2558 const unsigned int vface1 =
2559 cell_1->reference_cell().standard_to_real_face_vertex(
2560 v, face_no_1, combined_orientation);
2561 const unsigned int vi1 =
2562 topological_vertex_numbering[cell_1->face(face_no_1)
2563 ->vertex_index(vface1)];
2564 const unsigned int vi2 =
2565 topological_vertex_numbering[cell_2->face(face_no_2)
2567 const unsigned int min_index =
std::min(vi1, vi2);
2568 topological_vertex_numbering[cell_1->face(face_no_1)
2569 ->vertex_index(vface1)] =
2570 topological_vertex_numbering[cell_2->face(face_no_2)
2571 ->vertex_index(v)] =
2580 for (
unsigned int i = 0; i < topological_vertex_numbering.size();
2583 const unsigned int j = topological_vertex_numbering[i];
2584 Assert(j == i || topological_vertex_numbering[j] == j,
2586 "Got inconclusive constraints with chain: " +
2587 std::to_string(i) +
" vs " + std::to_string(j) +
2588 " which should be equal to " +
2589 std::to_string(topological_vertex_numbering[j])));
2596 bool continue_iterating =
true;
2597 std::vector<int> vertex_level(tria.
n_vertices());
2598 while (continue_iterating)
2602 std::fill(vertex_level.begin(), vertex_level.end(), 0);
2606 for (; cell != endc; ++cell)
2608 if (cell->refine_flag_set())
2609 for (
const unsigned int vertex :
2611 vertex_level[topological_vertex_numbering
2612 [cell->vertex_index(vertex)]] =
2613 std::
max(vertex_level[topological_vertex_numbering
2614 [cell->vertex_index(vertex)]],
2616 else if (!cell->coarsen_flag_set())
2617 for (
const unsigned int vertex :
2619 vertex_level[topological_vertex_numbering
2620 [cell->vertex_index(vertex)]] =
2621 std::
max(vertex_level[topological_vertex_numbering
2622 [cell->vertex_index(vertex)]],
2633 for (
const unsigned int vertex :
2635 vertex_level[topological_vertex_numbering
2636 [cell->vertex_index(vertex)]] =
2637 std::
max(vertex_level[topological_vertex_numbering
2638 [cell->vertex_index(vertex)]],
2643 continue_iterating =
false;
2654 for (cell = tria.
last_active(); cell != endc; --cell)
2655 if (cell->refine_flag_set() ==
false)
2657 for (
const unsigned int vertex :
2659 if (vertex_level[topological_vertex_numbering
2660 [cell->vertex_index(vertex)]] >=
2664 cell->clear_coarsen_flag();
2669 if (vertex_level[topological_vertex_numbering
2670 [cell->vertex_index(vertex)]] >
2673 cell->set_refine_flag();
2674 continue_iterating =
true;
2676 for (
const unsigned int v :
2678 vertex_level[topological_vertex_numbering
2679 [cell->vertex_index(v)]] =
2681 vertex_level[topological_vertex_numbering
2682 [cell->vertex_index(v)]],
2693 for (
const auto &cell : tria.cell_iterators())
2696 if (cell->is_active())
2699 const unsigned int n_children = cell->n_children();
2700 unsigned int flagged_children = 0;
2701 for (
unsigned int child = 0; child < n_children; ++child)
2702 if (cell->child(child)->is_active() &&
2703 cell->child(child)->coarsen_flag_set())
2708 if (flagged_children < n_children)
2709 for (
unsigned int child = 0; child < n_children; ++child)
2710 if (cell->child(child)->is_active())
2711 cell->child(child)->clear_coarsen_flag();
2714 std::vector<bool> flags_after[2];
2717 return ((flags_before[0] != flags_after[0]) ||
2718 (flags_before[1] != flags_after[1]));
2724 template <
int dim,
int spacedim>
2728 const bool match_periodic_levels =
2730 match_refinement_across_periodic_boundaries;
2731 const bool has_periodic_faces = !this->get_periodic_face_map().empty();
2733 if (!match_periodic_levels || !has_periodic_faces)
2744 const auto get_locally_owned_flags = [
this]() {
2745 std::vector<std::uint8_t> flags;
2746 for (
const auto &cell : this->active_cell_iterators())
2747 if (cell->is_locally_owned())
2750 static_cast<std::uint8_t
>(cell->refine_flag_set()));
2751 flags.push_back(cell->coarsen_flag_set() ? 1 : 0);
2756 const std::vector<std::uint8_t> flags_before = get_locally_owned_flags();
2757 bool flags_changed_globally =
false;
2758 unsigned int n_iterations = 0;
2763 "The distributed refinement and coarsening flags "
2764 "did not converge after 10 iterations."));
2771 const std::vector<std::uint8_t> flags_before_pass =
2772 get_locally_owned_flags();
2778 const bool flags_changed_locally =
2779 flags_before_pass != get_locally_owned_flags();
2781 flags_changed_globally =
2783 this->get_mpi_communicator());
2787 while (flags_changed_globally);
2795 get_locally_owned_flags(),
2796 this->get_mpi_communicator());
2801 template <
int dim,
int spacedim>
2822 if (settings & construct_multigrid_hierarchy)
2825 spacedim>::limit_level_difference_at_vertices;
2829 bool mesh_changed =
false;
2837 if (settings & mesh_reconstruction_after_repartitioning)
2838 while (this->n_levels() > 1)
2845 for (
const auto &cell :
2846 this->active_cell_iterators_on_level(this->n_levels() - 1))
2848 cell->set_coarsen_flag();
2866 if (parallel_ghost !=
nullptr)
2870 parallel_ghost =
nullptr;
2874 (dim == 2 ? typename ::internal::p4est::types<dim>::balance_type(
2875 P4EST_CONNECT_CORNER) :
2876 typename ::internal::p4est::types<dim>::balance_type(
2877 P8EST_CONNECT_CORNER)));
2884 for (
const auto &cell : this->cell_iterators_on_level(0))
2889 for (
const auto &cell : this->cell_iterators_on_level(0))
2894 if (tree_exists_locally<dim, spacedim>(
2896 coarse_cell_to_p4est_tree_permutation[cell->index()]) ==
2899 delete_all_children<dim, spacedim>(cell);
2900 if (cell->is_active())
2909 typename ::internal::p4est::types<dim>::quadrant
2911 typename ::internal::p4est::types<dim>::tree *tree =
2912 init_tree(cell->index());
2914 ::internal::p4est::init_coarse_quadrant<dim>(
2917 match_tree_recursively<dim, spacedim>(*tree,
2921 this->my_subdomain);
2928 typename ::internal::p4est::types<dim>::quadrant *quadr;
2930 typename ::internal::p4est::types<dim>::topidx ghost_tree = 0;
2932 for (
unsigned int g_idx = 0;
2933 g_idx < parallel_ghost->ghosts.elem_count;
2936 while (g_idx >=
static_cast<unsigned int>(
2937 parallel_ghost->proc_offsets[ghost_owner + 1]))
2939 while (g_idx >=
static_cast<unsigned int>(
2940 parallel_ghost->tree_offsets[ghost_tree + 1]))
2943 quadr =
static_cast<
2944 typename ::internal::p4est::types<dim>::quadrant *
>(
2945 sc_array_index(¶llel_ghost->ghosts, g_idx));
2947 unsigned int coarse_cell_index =
2948 p4est_tree_to_coarse_cell_permutation[ghost_tree];
2950 match_quadrant<dim, spacedim>(
this,
2965 bool mesh_changed =
true;
2966 unsigned int loop_counter = 0;
2973 this->update_periodic_face_map();
2976 enforce_mesh_balance_over_periodic_boundaries(*
this);
2988 "parallel::distributed::Triangulation::copy_local_forest_to_triangulation() "
2989 "for periodic boundaries detected. Aborting."));
2991 while (mesh_changed);
2996 std::any_of(this->begin_active(),
2999 return cell.refine_flag_set() ||
3000 cell.coarsen_flag_set();
3018 while (mesh_changed);
3023 unsigned int num_ghosts = 0;
3025 for (
const auto &cell : this->active_cell_iterators())
3027 if (cell->subdomain_id() != this->my_subdomain &&
3032 Assert(num_ghosts == parallel_ghost->ghosts.elem_count,
3043 if (settings & construct_multigrid_hierarchy)
3049 for (
unsigned int lvl = this->n_levels(); lvl > 0;)
3052 for (
const auto &cell : this->cell_iterators_on_level(lvl))
3054 if ((cell->is_active() &&
3055 cell->subdomain_id() ==
3056 this->locally_owned_subdomain()) ||
3057 (cell->has_children() &&
3058 cell->child(0)->level_subdomain_id() ==
3059 this->locally_owned_subdomain()))
3060 cell->set_level_subdomain_id(
3061 this->locally_owned_subdomain());
3065 cell->set_level_subdomain_id(
3073 std::vector<std::vector<bool>> marked_vertices(this->n_levels());
3074 for (
unsigned int lvl = 0; lvl < this->n_levels(); ++lvl)
3075 marked_vertices[lvl] = mark_locally_active_vertices_on_level(lvl);
3077 for (
const auto &cell : this->cell_iterators_on_level(0))
3079 typename ::internal::p4est::types<dim>::quadrant
3081 const unsigned int tree_index =
3082 coarse_cell_to_p4est_tree_permutation[cell->index()];
3083 typename ::internal::p4est::types<dim>::tree *tree =
3084 init_tree(cell->index());
3086 ::internal::p4est::init_coarse_quadrant<dim>(
3089 determine_level_subdomain_id_recursively<dim, spacedim>(
3100 for (
unsigned int lvl = this->n_levels(); lvl > 0;)
3103 for (
const auto &cell : this->cell_iterators_on_level(lvl))
3105 if (cell->has_children())
3106 for (
unsigned int c = 0;
3107 c < GeometryInfo<dim>::max_children_per_cell;
3110 if (cell->child(c)->level_subdomain_id() ==
3111 this->locally_owned_subdomain())
3116 cell->child(0)->level_subdomain_id();
3120 cell->set_level_subdomain_id(mark);
3139 const unsigned int total_local_cells = this->n_active_cells();
3144 Assert(
static_cast<unsigned int>(
3145 parallel_forest->local_num_quadrants) ==
3151 Assert(
static_cast<unsigned int>(
3152 parallel_forest->local_num_quadrants) <=
3158 unsigned int n_owned = 0;
3159 for (
const auto &cell : this->active_cell_iterators())
3161 if (cell->subdomain_id() == this->my_subdomain)
3165 Assert(
static_cast<unsigned int>(
3166 parallel_forest->local_num_quadrants) == n_owned,
3171 this->smooth_grid = save_smooth;
3177 update_cell_relations();
3182 template <
int dim,
int spacedim>
3188 std::vector<Point<dim>> point{p};
3189 std::vector<types::subdomain_id> owner = find_point_owner_rank(point);
3196 template <
int dim,
int spacedim>
3199 find_point_owner_rank(const
std::vector<
Point<dim>> &points)
3202 AssertThrow(this->are_vertices_communicated_to_p4est(),
3204 "Vertices need to be communicated to p4est to use this "
3205 "function. This must explicitly be turned on in the "
3206 "settings of the triangulation's constructor."));
3209 for (
const auto &manifold_id : this->get_manifold_ids())
3214 "This function can only be used if the triangulation "
3215 "has no other manifold than a Cartesian (flat) manifold attached."));
3219 PartitionSearch<dim> partition_search;
3225 parallel_forest->user_pointer = &partition_search;
3231 sc_array_t *point_sc_array;
3235 sc_array_new_count(
sizeof(
double[dim + 1]), points.size());
3238 for (
size_t i = 0; i < points.size(); ++i)
3243 double *this_sc_point =
3244 static_cast<double *
>(sc_array_index_ssize_t(point_sc_array, i));
3246 for (
unsigned int d = 0; d < dim; ++d)
3248 this_sc_point[d] = p(d);
3250 this_sc_point[dim] = -1.0;
3256 static_cast<int>(
false),
3257 &PartitionSearch<dim>::local_quadrant_fn,
3258 &PartitionSearch<dim>::local_point_fn,
3262 std::vector<types::subdomain_id> owner_rank(
3266 for (
size_t i = 0; i < points.size(); ++i)
3269 double *this_sc_point =
3270 static_cast<double *
>(sc_array_index_ssize_t(point_sc_array, i));
3271 Assert(this_sc_point[dim] >= 0. || this_sc_point[dim] == -1.,
3273 if (this_sc_point[dim] < 0.)
3281 parallel_forest->user_pointer =
this;
3284 sc_array_destroy_null(&point_sc_array);
3291 template <
int dim,
int spacedim>
3298 for (
const auto &cell : this->active_cell_iterators())
3299 if (cell->is_locally_owned() && cell->refine_flag_set())
3300 Assert(cell->refine_flag_set() ==
3303 "This class does not support anisotropic refinement"));
3308 if (this->n_levels() ==
3312 cell = this->begin_active(
3320 !(cell->refine_flag_set()),
3322 "Fatal Error: maximum refinement level of p4est reached."));
3326 this->prepare_coarsening_and_refinement();
3329 this->signals.pre_distributed_refinement();
3334 for (
const auto &cell : this->active_cell_iterators())
3335 if (cell->is_ghost() || cell->is_artificial())
3337 cell->clear_refine_flag();
3338 cell->clear_coarsen_flag();
3344 RefineAndCoarsenList<dim, spacedim> refine_and_coarsen_list(
3345 *
this, p4est_tree_to_coarse_cell_permutation, this->my_subdomain);
3352 parallel_forest->user_pointer = &refine_and_coarsen_list;
3354 if (parallel_ghost !=
nullptr)
3358 parallel_ghost =
nullptr;
3363 &RefineAndCoarsenList<dim, spacedim>::refine_callback,
3368 &RefineAndCoarsenList<dim, spacedim>::coarsen_callback,
3375 parallel_forest->user_pointer =
this;
3381 (dim == 2 ? typename ::internal::p4est::types<dim>::balance_type(
3382 P4EST_CONNECT_FULL) :
3383 typename ::internal::p4est::types<dim>::balance_type(
3384 P8EST_CONNECT_FULL)),
3389 update_cell_relations();
3393 this->signals.post_p4est_refinement();
3397 std::vector<typename ::internal::p4est::types<dim>::gloidx>
3398 previous_global_first_quadrant;
3400 if (this->cell_attached_data.n_attached_data_sets > 0)
3402 previous_global_first_quadrant.resize(parallel_forest->mpisize + 1);
3403 std::memcpy(previous_global_first_quadrant.data(),
3404 parallel_forest->global_first_quadrant,
3406 typename ::internal::p4est::types<dim>::gloidx) *
3407 (parallel_forest->mpisize + 1));
3410 if (!(settings & no_automatic_repartitioning))
3414 if (this->signals.weight.empty())
3422 const std::vector<unsigned int> cell_weights = get_cell_weights();
3428 this->mpi_communicator) > 0,
3430 "The global sum of weights over all active cells "
3431 "is zero. Please verify how you generate weights."));
3433 PartitionWeights<dim, spacedim> partition_weights(cell_weights);
3438 parallel_forest->user_pointer = &partition_weights;
3444 &PartitionWeights<dim, spacedim>::cell_weight);
3448 parallel_forest, 0,
nullptr,
nullptr);
3450 parallel_forest->user_pointer =
this;
3455 if (this->cell_attached_data.n_attached_data_sets > 0)
3457 this->data_serializer.pack_data(
3458 this->local_cell_relations,
3459 this->cell_attached_data.pack_callbacks_fixed,
3460 this->cell_attached_data.pack_callbacks_variable,
3461 this->get_mpi_communicator());
3467 for (
const auto &cell : this->active_cell_iterators())
3469 cell->clear_refine_flag();
3470 cell->clear_coarsen_flag();
3475 copy_local_forest_to_triangulation();
3485 if (this->cell_attached_data.n_attached_data_sets > 0)
3487 this->execute_transfer(parallel_forest,
3488 previous_global_first_quadrant.data());
3491 this->data_serializer.unpack_cell_status(this->local_cell_relations);
3513 if (settings & construct_multigrid_hierarchy)
3515 for (
unsigned int lvl = 0; lvl < this->n_global_levels(); ++lvl)
3517 std::vector<bool> active_verts =
3518 this->mark_locally_active_vertices_on_level(lvl);
3520 const unsigned int maybe_coarser_lvl =
3521 (lvl > 0) ? (lvl - 1) : lvl;
3523 cell = this->
begin(maybe_coarser_lvl),
3524 endc = this->
end(lvl);
3525 for (; cell != endc; ++cell)
3526 if (cell->level() ==
static_cast<int>(lvl) ||
3529 const bool is_level_artificial =
3530 (cell->level_subdomain_id() ==
3532 bool need_to_know =
false;
3533 for (
const unsigned int vertex :
3535 if (active_verts[cell->vertex_index(vertex)])
3537 need_to_know =
true;
3542 !need_to_know || !is_level_artificial,
3544 "Internal error: the owner of cell" +
3545 cell->id().to_string() +
3546 " is unknown even though it is needed for geometric multigrid."));
3552 this->update_periodic_face_map();
3553 this->update_number_cache();
3556 match_refinement_across_periodic_boundaries)
3558 unsigned int n_mismatched_periodic_faces = 0;
3559 for (
const auto &cell : this->active_cell_iterators())
3560 if (cell->is_locally_owned())
3561 for (
const unsigned int face : cell->face_indices())
3562 if (cell->has_periodic_neighbor(face) &&
3563 cell->level() != cell->periodic_neighbor(face)->level())
3564 ++n_mismatched_periodic_faces;
3568 this->get_mpi_communicator()) == 0,
3570 "p4est produced periodic neighbors at different levels despite the"
3571 "match_refinement_across_periodic_boundaries smoothing flag."));
3575 this->signals.post_distributed_refinement();
3580 template <
int dim,
int spacedim>
3586 for (
const auto &cell : this->active_cell_iterators())
3587 if (cell->is_locally_owned())
3589 !cell->refine_flag_set() && !cell->coarsen_flag_set(),
3591 "Error: There shouldn't be any cells flagged for coarsening/refinement when calling repartition()."));
3595 this->signals.pre_distributed_repartition();
3599 std::vector<typename ::internal::p4est::types<dim>::gloidx>
3600 previous_global_first_quadrant;
3602 if (this->cell_attached_data.n_attached_data_sets > 0)
3604 previous_global_first_quadrant.resize(parallel_forest->mpisize + 1);
3605 std::memcpy(previous_global_first_quadrant.data(),
3606 parallel_forest->global_first_quadrant,
3608 typename ::internal::p4est::types<dim>::gloidx) *
3609 (parallel_forest->mpisize + 1));
3612 if (this->signals.weight.empty())
3624 const std::vector<unsigned int> cell_weights = get_cell_weights();
3630 this->mpi_communicator) > 0,
3632 "The global sum of weights over all active cells "
3633 "is zero. Please verify how you generate weights."));
3635 PartitionWeights<dim, spacedim> partition_weights(cell_weights);
3640 parallel_forest->user_pointer = &partition_weights;
3646 &PartitionWeights<dim, spacedim>::cell_weight);
3649 parallel_forest->user_pointer =
this;
3653 if (this->cell_attached_data.n_attached_data_sets > 0)
3655 this->data_serializer.pack_data(
3656 this->local_cell_relations,
3657 this->cell_attached_data.pack_callbacks_fixed,
3658 this->cell_attached_data.pack_callbacks_variable,
3659 this->get_mpi_communicator());
3664 copy_local_forest_to_triangulation();
3674 if (this->cell_attached_data.n_attached_data_sets > 0)
3676 this->execute_transfer(parallel_forest,
3677 previous_global_first_quadrant.data());
3680 this->update_periodic_face_map();
3683 this->update_number_cache();
3686 this->signals.post_distributed_repartition();
3691 template <
int dim,
int spacedim>
3693 const std::vector<types::global_dof_index>
3697 return p4est_tree_to_coarse_cell_permutation;
3702 template <
int dim,
int spacedim>
3704 const std::vector<types::global_dof_index>
3708 return coarse_cell_to_p4est_tree_permutation;
3713 template <
int dim,
int spacedim>
3716 mark_locally_active_vertices_on_level(const
int level)
const
3720 std::vector<bool> marked_vertices(this->n_vertices(),
false);
3721 for (
const auto &cell : this->cell_iterators_on_level(
level))
3722 if (cell->level_subdomain_id() == this->locally_owned_subdomain())
3724 marked_vertices[cell->vertex_index(v)] =
true;
3741 for (
unsigned int repetition = 0; repetition < dim; ++repetition)
3742 for (
const auto &it : this->get_periodic_face_map())
3745 const unsigned int face_no_1 = it.first.second;
3747 const unsigned int face_no_2 = it.second.first.second;
3748 const auto combined_orientation = it.second.second;
3749 const auto [orientation, rotation, flip] =
3752 if (cell_1->level() ==
level && cell_2->level() ==
level)
3754 for (
unsigned int v = 0;
3760 const unsigned int vface0 =
3762 v, orientation, flip, rotation);
3763 if (marked_vertices[cell_1->face(face_no_1)->vertex_index(
3765 marked_vertices[cell_2->face(face_no_2)->vertex_index(
3767 marked_vertices[cell_1->face(face_no_1)->vertex_index(
3769 marked_vertices[cell_2->face(face_no_2)->vertex_index(
3775 return marked_vertices;
3780 template <
int dim,
int spacedim>
3783 coarse_cell_id_to_coarse_cell_index(
3784 const
types::coarse_cell_id coarse_cell_id)
const
3786 return p4est_tree_to_coarse_cell_permutation[coarse_cell_id];
3791 template <
int dim,
int spacedim>
3795 const unsigned int coarse_cell_index)
const
3797 return coarse_cell_to_p4est_tree_permutation[coarse_cell_index];
3802 template <
int dim,
int spacedim>
3806 &periodicity_vector)
3808 Assert(triangulation_has_content ==
true,
3810 Assert(this->n_levels() == 1,
3811 ExcMessage(
"The triangulation is refined!"));
3818 const auto reference_cell = ReferenceCells::get_hypercube<dim>();
3820 for (
const auto &face_pair : periodicity_vector)
3824 const unsigned int face_left = face_pair.face_idx[0];
3825 const unsigned int face_right = face_pair.face_idx[1];
3828 const unsigned int tree_left =
3829 coarse_cell_to_p4est_tree_permutation[first_cell->index()];
3830 const unsigned int tree_right =
3831 coarse_cell_to_p4est_tree_permutation[second_cell->index()];
3839 unsigned int p4est_orientation = 0;
3843 p4est_orientation = face_pair.orientation ==
3850 const unsigned int face_idx_list[] = {face_left, face_right};
3851 const cell_iterator cell_list[] = {first_cell, second_cell};
3852 unsigned int lower_idx, higher_idx;
3854 if (face_left <= face_right)
3859 face_reference_cell.get_inverse_combined_orientation(
3860 face_pair.orientation);
3866 orientation = face_pair.orientation;
3871 unsigned int first_p4est_idx_on_cell =
3872 p8est_face_corners[face_idx_list[lower_idx]][0];
3873 unsigned int first_dealii_idx_on_face =
3875 for (
unsigned int i = 0; i < GeometryInfo<dim>::vertices_per_face;
3878 const unsigned int first_dealii_idx_on_cell =
3880 face_idx_list[lower_idx],
3882 cell_list[lower_idx]->face_orientation(
3883 face_idx_list[lower_idx]),
3884 cell_list[lower_idx]->face_flip(face_idx_list[lower_idx]),
3885 cell_list[lower_idx]->face_rotation(
3886 face_idx_list[lower_idx]));
3887 if (first_p4est_idx_on_cell == first_dealii_idx_on_cell)
3889 first_dealii_idx_on_face = i;
3897 const unsigned int second_dealii_idx_on_face =
3898 reference_cell.standard_to_real_face_vertex(
3899 first_dealii_idx_on_face,
3900 face_idx_list[lower_idx],
3902 const unsigned int second_dealii_idx_on_cell =
3903 reference_cell.face_to_cell_vertices(
3904 face_idx_list[higher_idx],
3905 second_dealii_idx_on_face,
3906 cell_list[higher_idx]->combined_face_orientation(
3907 face_idx_list[higher_idx]));
3909 const unsigned int second_p4est_idx_on_face =
3910 p8est_corner_face_corners[second_dealii_idx_on_cell]
3911 [face_idx_list[higher_idx]];
3912 p4est_orientation = second_p4est_idx_on_face;
3932 this->mpi_communicator,
3943 copy_local_forest_to_triangulation();
3954 this->update_number_cache();
3959 template <
int dim,
int spacedim>
3970 this->cell_attached_data.n_attached_data_sets) +
3977 coarse_cell_to_p4est_tree_permutation) +
3979 p4est_tree_to_coarse_cell_permutation) +
3980 memory_consumption_p4est();
3987 template <
int dim,
int spacedim>
3991 return ::internal::p4est::functions<dim>::forest_memory_used(
3999 template <
int dim,
int spacedim>
4004 if (const ::parallel::distributed::Triangulation<dim, spacedim>
4005 *other_distributed =
4006 dynamic_cast<const ::parallel::distributed::
4007 Triangulation<dim, spacedim> *
>(&other_tria))
4008 copy_triangulation(other_tria, other_distributed->settings);
4010 copy_triangulation(other_tria, default_setting);
4015 template <
int dim,
int spacedim>
4023 const ::parallel::distributed::Triangulation<dim, spacedim> *
>(
4025 (other_tria.n_global_levels() == 1),
4036 const typename ::Triangulation<dim, spacedim>::DistortedCellList
4044 if (const ::parallel::distributed::Triangulation<dim, spacedim>
4045 *other_distributed =
4046 dynamic_cast<const ::parallel::distributed::
4047 Triangulation<dim, spacedim> *
>(&other_tria))
4050 this->settings = settings;
4052 triangulation_has_content =
4053 other_distributed->triangulation_has_content;
4054 coarse_cell_to_p4est_tree_permutation =
4055 other_distributed->coarse_cell_to_p4est_tree_permutation;
4056 p4est_tree_to_coarse_cell_permutation =
4057 other_distributed->p4est_tree_to_coarse_cell_permutation;
4060 typename ::internal::p4est::types<dim>::connectivity
4061 *temp_connectivity =
const_cast<
4062 typename ::internal::p4est::types<dim>::connectivity *
>(
4063 other_distributed->connectivity);
4065 ::internal::p4est::copy_connectivity<dim>(temp_connectivity);
4068 typename ::internal::p4est::types<dim>::forest *temp_forest =
4069 const_cast<typename ::internal::p4est::types<dim>::forest *
>(
4070 other_distributed->parallel_forest);
4074 parallel_forest->connectivity = connectivity;
4075 parallel_forest->user_pointer =
this;
4079 triangulation_has_content =
true;
4080 setup_coarse_cell_to_p4est_tree_permutation();
4081 copy_new_triangulation_to_p4est(std::integral_constant<int, dim>());
4086 copy_local_forest_to_triangulation();
4095 this->update_periodic_face_map();
4096 this->update_number_cache();
4101 template <
int dim,
int spacedim>
4106 this->local_cell_relations.resize(parallel_forest->local_num_quadrants);
4107 this->local_cell_relations.shrink_to_fit();
4110 for (
const auto &cell : this->cell_iterators_on_level(0))
4113 if (tree_exists_locally<dim, spacedim>(
4115 coarse_cell_to_p4est_tree_permutation[cell->index()]) ==
false)
4119 typename ::internal::p4est::types<dim>::quadrant
4121 ::internal::p4est::init_coarse_quadrant<dim>(p4est_coarse_cell);
4124 typename ::internal::p4est::types<dim>::tree *tree =
4125 init_tree(cell->index());
4127 update_cell_relations_recursively<dim, spacedim>(
4128 this->local_cell_relations, *tree, cell, p4est_coarse_cell);
4134 template <
int dim,
int spacedim>
4141 Assert(this->local_cell_relations.size() ==
4142 static_cast<unsigned int>(parallel_forest->local_num_quadrants),
4147 std::vector<unsigned int> weights;
4148 weights.reserve(this->local_cell_relations.size());
4156 for (
const auto &[cell_it, cell_status] : this->local_cell_relations)
4158 weights.push_back(this->signals.weight(cell_it, cell_status));
4166 template <
int spacedim>
4182 template <
int spacedim>
4191 template <
int spacedim>
4193 const std::vector<types::global_dof_index>
4197 return p4est_tree_to_coarse_cell_permutation;
4202 template <
int spacedim>
4204 std::map<
unsigned int,
4207 const unsigned int )
const
4211 return std::map<unsigned int, std::set<::types::subdomain_id>>();
4216 template <
int spacedim>
4219 mark_locally_active_vertices_on_level(const
unsigned int)
const
4222 return std::vector<bool>();
4227 template <
int spacedim>
4230 coarse_cell_id_to_coarse_cell_index(const
types::coarse_cell_id)
const
4238 template <
int spacedim>
4242 const unsigned int)
const
4250 template <
int spacedim>
4259 template <
int spacedim>
4268 template <
int spacedim>
4278 template <
int spacedim>
4288 template <
int spacedim>
4305 namespace distributed
4307 template <
int dim,
int spacedim>
4315#ifdef DEAL_II_WITH_P4EST
4323 for (
const auto &[cell, status] :
4330 cell->clear_refine_flag();
4331 cell->clear_coarsen_flag();
4336 cell->clear_coarsen_flag();
4337 cell->set_refine_flag();
4342 for (
const auto &child : cell->child_iterators())
4344 child->clear_refine_flag();
4345 child->set_coarsen_flag();
4364 template <
int dim,
int spacedim>
4367#ifdef DEAL_II_WITH_P4EST
4368 if (distributed_tria)
4371 distributed_tria->load_coarsen_flags(saved_coarsen_flags);
4372 distributed_tria->load_refine_flags(saved_refine_flags);
4376 (void)distributed_tria;
4385#include "distributed/tria.inst"
* * for(const auto &cell :triangulation.active_cell_iterators())
* * const_iterator()=default
@ children_will_be_coarsened
virtual void add_periodicity(const std::vector< GridTools::PeriodicFacePair< cell_iterator > > &)
active_cell_iterator last_active() const
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
const std::vector< Point< spacedim > > & get_vertices() const
unsigned int n_active_lines() const
unsigned int n_levels() const
cell_iterator end() const
virtual types::coarse_cell_id coarse_cell_index_to_coarse_cell_id(const unsigned int coarse_cell_index) const
virtual void execute_coarsening_and_refinement()
unsigned int n_cells() const
virtual bool prepare_coarsening_and_refinement()
const std::vector< bool > & get_used_vertices() const
void save_refine_flags(std::ostream &out) const
unsigned int n_vertices() const
const std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, types::geometric_orientation > > & get_periodic_face_map() const
void save_coarsen_flags(std::ostream &out) const
active_cell_iterator begin_active(const unsigned int level=0) const
virtual std::size_t memory_consumption() const override
virtual void clear() override
virtual void copy_triangulation(const ::Triangulation< dim, spacedim > &old_tria) override
~TemporarilyMatchRefineFlags()
const ObserverPointer< ::parallel::distributed::Triangulation< dim, spacedim > > distributed_tria
std::vector< bool > saved_refine_flags
std::vector< bool > saved_coarsen_flags
virtual void clear() override
#define DEAL_II_NAMESPACE_OPEN
constexpr bool running_in_debug_mode()
#define DEAL_II_CXX20_REQUIRES(condition)
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertNothrow(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
typename ::Triangulation< dim, spacedim >::cell_iterator cell_iterator
typename ::Triangulation< dim, spacedim >::active_cell_iterator active_cell_iterator
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
Point< spacedim > point(const gp_Pnt &p, const double tolerance=1e-10)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
* * if(update_pressure &update_flags) * compute_pressure(constitutive_request
* * * * std::vector< Number > ThermoPlasticMaterial< dim, ViscoplasticYieldLaw, Number >::get_state_parameters const
constexpr const ReferenceCell< dim > & get_hypercube()
T sum(const T &t, const MPI_Comm mpi_communicator)
T logical_or(const T &t, const MPI_Comm mpi_communicator)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
T broadcast(const MPI_Comm comm, const T &object_to_send, const unsigned int root_process=0)
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
bool tree_exists_locally(const typename types< dim >::forest *parallel_forest, const typename types< dim >::topidx coarse_grid_cell)
void exchange_refinement_flags(::parallel::distributed::Triangulation< dim, spacedim > &tria)
std::tuple< bool, bool, bool > split_face_orientation(const types::geometric_orientation combined_orientation)
constexpr unsigned int invalid_unsigned_int
constexpr types::manifold_id flat_manifold_id
constexpr types::subdomain_id artificial_subdomain_id
constexpr types::subdomain_id invalid_subdomain_id
constexpr types::geometric_orientation default_geometric_orientation
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
std::uint8_t geometric_orientation
static unsigned int standard_to_real_face_vertex(const unsigned int vertex, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static unsigned int face_to_cell_vertices(const unsigned int face, const unsigned int vertex, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static std_cxx20::ranges::iota_view< unsigned int, unsigned int > vertex_indices()
static bool is_inside_unit_cell(const Point< dim > &p)
static Point< dim > unit_cell_vertex(const unsigned int vertex)