17 #include <deal.II/base/mpi.templates.h>
57 #include <boost/random/mersenne_twister.hpp>
58 #include <boost/random/uniform_real_distribution.hpp>
67 #include <unordered_map>
74 template <
int dim,
int spacedim>
84 #if defined(DEAL_II_WITH_P4EST) && defined(DEBUG)
99 std::vector<bool> boundary_vertices(
vertices.size(),
false);
105 for (; cell != endc; ++cell)
107 if (cell->face(face)->at_boundary())
108 for (
unsigned int i = 0; i < GeometryInfo<dim>::vertices_per_face;
110 boundary_vertices[cell->face(face)->vertex_index(i)] =
true;
114 double max_distance_sqr = 0;
115 std::vector<bool>::const_iterator pi = boundary_vertices.begin();
116 const unsigned int N = boundary_vertices.size();
117 for (
unsigned int i = 0; i <
N; ++i, ++pi)
119 std::vector<bool>::const_iterator pj = pi + 1;
120 for (
unsigned int j = i + 1; j <
N; ++j, ++pj)
121 if ((*pi ==
true) && (*pj ==
true) &&
126 return std::sqrt(max_distance_sqr);
131 template <
int dim,
int spacedim>
137 unsigned int mapping_degree = 1;
140 mapping_degree = p->get_degree();
141 else if (
const auto *p =
143 mapping_degree = p->get_degree();
146 const QGauss<dim> quadrature_formula(mapping_degree + 1);
147 const unsigned int n_q_points = quadrature_formula.
size();
162 double local_volume = 0;
165 for (; cell != endc; ++cell)
166 if (cell->is_locally_owned())
169 for (
unsigned int q = 0; q < n_q_points; ++q)
170 local_volume += fe_values.JxW(q);
173 double global_volume = 0;
175 #ifdef DEAL_II_WITH_MPI
183 global_volume = local_volume;
185 return global_volume;
202 for (
const auto &cell :
triangulation.active_cell_iterators())
204 if (cell->is_locally_owned())
206 double aspect_ratio_cell = 0.0;
211 for (
unsigned int q = 0; q < quadrature.
size(); ++q)
222 aspect_ratio_cell = std::numeric_limits<double>::infinity();
227 for (
unsigned int i = 0; i < dim; i++)
228 for (
unsigned int j = 0; j < dim; j++)
229 J(i, j) = jacobian[i][j];
235 double const ar = max_sv / min_sv;
242 aspect_ratio_cell =
std::max(aspect_ratio_cell, ar);
247 aspect_ratio_vector(cell->active_cell_index()) = aspect_ratio_cell;
251 return aspect_ratio_vector;
272 template <
int dim,
int spacedim>
278 const auto predicate = [](
const iterator &) {
return true; };
281 tria, std::function<
bool(
const iterator &)>(predicate));
307 template <
int structdim>
331 "Two CellData objects with equal vertices must "
332 "have the same material/boundary ids and manifold "
357 template <
class FaceIteratorType>
362 for (
unsigned int vertex_n = 0;
363 vertex_n < GeometryInfo<dim>::vertices_per_face;
365 face_cell_data.
vertices[vertex_n] = face->vertex_index(vertex_n);
366 face_cell_data.boundary_id = face->boundary_id();
367 face_cell_data.manifold_id = face->manifold_id();
397 template <
class FaceIteratorType>
412 template <
int dim,
int spacedim>
414 tuple<std::vector<Point<spacedim>>, std::vector<CellData<dim>>,
SubCellData>
418 ExcMessage(
"The input triangulation must be non-empty."));
420 std::vector<Point<spacedim>>
vertices;
421 std::vector<CellData<dim>> cells;
423 unsigned int max_level_0_vertex_n = 0;
425 for (
const unsigned int cell_vertex_n :
427 max_level_0_vertex_n =
428 std::max(cell->vertex_index(cell_vertex_n), max_level_0_vertex_n);
429 vertices.resize(max_level_0_vertex_n + 1);
439 for (
const unsigned int cell_vertex_n :
444 vertices[cell->vertex_index(cell_vertex_n)] =
445 cell->vertex(cell_vertex_n);
447 cell->vertex_index(cell_vertex_n);
451 cells.push_back(cell_data);
462 for (
unsigned int line_n = 0;
463 line_n < GeometryInfo<dim>::lines_per_cell;
466 const auto line = cell->line(line_n);
468 for (
unsigned int vertex_n = 0;
469 vertex_n < GeometryInfo<2>::vertices_per_face;
472 line->vertex_index(vertex_n);
476 line_data.insert(line_cell_data);
484 std::vector<bool> used_vertices(
vertices.size());
486 for (
const unsigned int cell_vertex_n :
488 used_vertices[cell_data.vertices[cell_vertex_n]] =
true;
489 Assert(std::find(used_vertices.begin(), used_vertices.end(),
false) ==
491 ExcMessage(
"The level zero vertices should form a contiguous "
499 for (
const CellData<1> &face_line_data : line_data)
502 return std::tuple<std::vector<Point<spacedim>>,
503 std::vector<CellData<dim>>,
506 std::move(subcell_data));
511 template <
int dim,
int spacedim>
520 "Invalid SubCellData supplied according to ::check_consistency(). "
521 "This is caused by data containing objects for the wrong dimension."));
524 std::vector<bool> vertex_used(
vertices.size(),
false);
525 for (
unsigned int c = 0; c < cells.size(); ++c)
529 ExcMessage(
"Invalid vertex index encountered! cells[" +
533 " is invalid, because only " +
535 " vertices were supplied."));
536 vertex_used[cells[c].vertices[v]] =
true;
543 std::vector<unsigned int> new_vertex_numbers(
vertices.size(),
545 unsigned int next_free_number = 0;
546 for (
unsigned int i = 0; i <
vertices.size(); ++i)
547 if (vertex_used[i] ==
true)
549 new_vertex_numbers[i] = next_free_number;
554 for (
unsigned int c = 0; c < cells.size(); ++c)
556 cells[c].vertices[v] = new_vertex_numbers[cells[c].vertices[v]];
564 new_vertex_numbers.size(),
566 "Invalid vertex index in subcelldata.boundary_lines. "
567 "subcelldata.boundary_lines[" +
572 " is invalid, because only " +
574 " vertices were supplied."));
584 new_vertex_numbers.size(),
586 "Invalid vertex index in subcelldata.boundary_quads. "
587 "subcelldata.boundary_quads[" +
592 " is invalid, because only " +
594 " vertices were supplied."));
602 std::vector<Point<spacedim>> tmp;
603 tmp.reserve(std::count(vertex_used.begin(), vertex_used.end(),
true));
604 for (
unsigned int v = 0; v <
vertices.size(); ++v)
605 if (vertex_used[v] ==
true)
612 template <
int dim,
int spacedim>
617 std::vector<unsigned int> & considered_vertices,
623 std::vector<unsigned int> new_vertex_numbers(
vertices.size());
624 std::iota(new_vertex_numbers.begin(), new_vertex_numbers.end(), 0);
627 if (considered_vertices.size() == 0)
628 considered_vertices = new_vertex_numbers;
645 unsigned int longest_coordinate_direction = 0;
646 double longest_coordinate_length =
max[0] -
min[0];
647 for (
unsigned int d = 1;
d < spacedim; ++
d)
649 const double coordinate_length =
max[
d] -
min[
d];
650 if (longest_coordinate_length < coordinate_length)
652 longest_coordinate_length = coordinate_length;
653 longest_coordinate_direction =
d;
659 std::vector<std::pair<unsigned int, Point<spacedim>>> sorted_vertices;
660 sorted_vertices.reserve(
vertices.size());
661 for (
const unsigned int vertex_n : considered_vertices)
664 sorted_vertices.emplace_back(vertex_n,
vertices[vertex_n]);
666 std::sort(sorted_vertices.begin(),
667 sorted_vertices.end(),
670 return a.second[longest_coordinate_direction] <
671 b.second[longest_coordinate_direction];
676 for (
unsigned int d = 0;
d < spacedim; ++
d)
677 if (std::abs(a[
d] -
b[
d]) > tol)
684 auto range_start = sorted_vertices.begin();
685 while (range_start != sorted_vertices.end())
687 auto range_end = range_start + 1;
688 while (range_end != sorted_vertices.end() &&
689 std::abs(range_end->second[longest_coordinate_direction] -
690 range_start->second[longest_coordinate_direction]) <
696 std::sort(range_start,
700 return a.first <
b.first;
709 for (
auto reference = range_start; reference != range_end; ++reference)
712 for (
auto it = reference + 1; it != range_end; ++it)
714 if (within_tolerance(reference->second, it->second))
716 new_vertex_numbers[it->first] = reference->first;
722 range_start = range_end;
729 for (
auto &cell : cells)
730 for (
auto &vertex_index : cell.vertices)
731 vertex_index = new_vertex_numbers[vertex_index];
733 for (
auto &vertex_index : quad.vertices)
734 vertex_index = new_vertex_numbers[vertex_index];
736 for (
auto &vertex_index : line.vertices)
737 vertex_index = new_vertex_numbers[vertex_index];
747 template <
int spacedim>
779 std::cos(
angle) * p(1) - std::sin(
angle) * p(2),
780 std::sin(
angle) * p(1) + std::cos(
angle) * p(2)};
782 return {std::cos(
angle) * p(0) + std::sin(
angle) * p(2),
784 -std::sin(
angle) * p(0) + std::cos(
angle) * p(2)};
786 return {std::cos(
angle) * p(0) - std::sin(
angle) * p(1),
787 std::sin(
angle) * p(0) + std::cos(
angle) * p(1),
796 template <
int spacedim>
815 template <
int dim,
int spacedim>
827 const unsigned int axis,
835 template <
int dim,
int spacedim>
857 const unsigned int n_dofs = S.
n();
869 const auto constrained_rhs =
871 solver.
solve(SF, u, constrained_rhs, prec);
884 const bool solve_for_absolute_positions)
912 std::array<AffineConstraints<double>, dim> constraints;
913 typename std::map<unsigned int, Point<dim>>::const_iterator map_end =
923 const unsigned int vertex_index = cell->vertex_index(vertex_no);
924 const Point<dim> & vertex_point = cell->vertex(vertex_no);
926 const typename std::map<unsigned int, Point<dim>>::const_iterator
927 map_iter = new_points.find(vertex_index);
929 if (map_iter != map_end)
930 for (
unsigned int i = 0; i < dim; ++i)
932 constraints[i].add_line(cell->vertex_dof_index(vertex_no, 0));
933 constraints[i].set_inhomogeneity(
934 cell->vertex_dof_index(vertex_no, 0),
935 (solve_for_absolute_positions ?
936 map_iter->second(i) :
937 map_iter->second(i) - vertex_point[i]));
942 for (
unsigned int i = 0; i < dim; ++i)
943 constraints[i].close();
947 for (
unsigned int i = 0; i < dim; ++i)
952 for (
unsigned int i = 0; i < dim; ++i)
959 std::vector<bool> vertex_touched(
triangulation.n_vertices(),
false);
962 if (vertex_touched[cell->vertex_index(vertex_no)] ==
false)
967 cell->vertex_dof_index(vertex_no, 0);
968 for (
unsigned int i = 0; i < dim; ++i)
969 if (solve_for_absolute_positions)
970 v(i) = us[i](dof_index);
972 v(i) += us[i](dof_index);
974 vertex_touched[cell->vertex_index(vertex_no)] =
true;
978 template <
int dim,
int spacedim>
979 std::map<unsigned int, Point<spacedim>>
982 std::map<unsigned int, Point<spacedim>> vertex_map;
986 for (; cell != endc; ++cell)
992 if (face->at_boundary())
994 for (
unsigned j = 0; j < GeometryInfo<dim>::vertices_per_face;
998 const unsigned int vertex_index = face->vertex_index(j);
999 vertex_map[vertex_index] = vertex;
1011 template <
int dim,
int spacedim>
1015 const bool keep_boundary)
1032 double almost_infinite_length = 0;
1037 almost_infinite_length += cell->diameter();
1039 std::vector<double> minimal_length(
triangulation.n_vertices(),
1040 almost_infinite_length);
1043 std::vector<bool> at_boundary(keep_boundary ?
triangulation.n_vertices() :
1048 const bool is_parallel_shared =
1051 for (
const auto &cell :
triangulation.active_cell_iterators())
1052 if (is_parallel_shared || cell->is_locally_owned())
1056 for (
unsigned int i = 0; i < GeometryInfo<dim>::lines_per_cell;
1060 line = cell->line(i);
1062 if (keep_boundary && line->at_boundary())
1064 at_boundary[line->vertex_index(0)] =
true;
1065 at_boundary[line->vertex_index(1)] =
true;
1068 minimal_length[line->vertex_index(0)] =
1070 minimal_length[line->vertex_index(0)]);
1071 minimal_length[line->vertex_index(1)] =
1073 minimal_length[line->vertex_index(1)]);
1079 for (
unsigned int vertex = 0; vertex < 2; ++vertex)
1080 if (cell->at_boundary(vertex) ==
true)
1081 at_boundary[cell->vertex_index(vertex)] =
true;
1083 minimal_length[cell->vertex_index(0)] =
1085 minimal_length[cell->vertex_index(0)]);
1086 minimal_length[cell->vertex_index(1)] =
1088 minimal_length[cell->vertex_index(1)]);
1099 boost::random::mt19937 rng;
1100 boost::random::uniform_real_distribution<> uniform_distribution(-1, 1);
1105 *distributed_triangulation =
1109 const std::vector<bool> locally_owned_vertices =
1111 std::vector<bool> vertex_moved(
triangulation.n_vertices(),
false);
1114 for (
const auto &cell :
triangulation.active_cell_iterators())
1115 if (cell->is_locally_owned())
1117 for (
const unsigned int vertex_no :
1120 const unsigned global_vertex_no =
1121 cell->vertex_index(vertex_no);
1126 if ((keep_boundary && at_boundary[global_vertex_no]) ||
1127 vertex_moved[global_vertex_no] ||
1128 !locally_owned_vertices[global_vertex_no])
1133 for (
unsigned int d = 0;
d < spacedim; ++
d)
1134 shift_vector(
d) = uniform_distribution(rng);
1136 shift_vector *= factor * minimal_length[global_vertex_no] /
1137 std::sqrt(shift_vector.
square());
1140 cell->vertex(vertex_no) += shift_vector;
1141 vertex_moved[global_vertex_no] =
true;
1145 #ifdef DEAL_II_WITH_P4EST
1146 distributed_triangulation->communicate_locally_moved_vertices(
1147 locally_owned_vertices);
1149 (void)distributed_triangulation;
1161 std::vector<Point<spacedim>> new_vertex_locations(n_vertices);
1162 const std::vector<Point<spacedim>> &old_vertex_locations =
1165 for (
unsigned int vertex = 0; vertex < n_vertices; ++vertex)
1169 if (keep_boundary && at_boundary[vertex])
1170 new_vertex_locations[vertex] = old_vertex_locations[vertex];
1175 for (
unsigned int d = 0;
d < spacedim; ++
d)
1176 shift_vector(
d) = uniform_distribution(rng);
1178 shift_vector *= factor * minimal_length[vertex] /
1179 std::sqrt(shift_vector.
square());
1182 new_vertex_locations[vertex] =
1183 old_vertex_locations[vertex] + shift_vector;
1188 for (
const auto &cell :
triangulation.active_cell_iterators())
1189 for (
const unsigned int vertex_no :
1191 cell->vertex(vertex_no) =
1192 new_vertex_locations[cell->vertex_index(vertex_no)];
1208 for (; cell != endc; ++cell)
1209 if (!cell->is_artificial())
1211 if (cell->face(face)->has_children() &&
1212 !cell->face(face)->at_boundary())
1216 cell->face(face)->child(0)->vertex(1) =
1217 (cell->face(face)->vertex(0) +
1218 cell->face(face)->vertex(1)) /
1222 cell->face(face)->child(0)->vertex(1) =
1223 .5 * (cell->face(face)->vertex(0) +
1224 cell->face(face)->vertex(1));
1225 cell->face(face)->child(0)->vertex(2) =
1226 .5 * (cell->face(face)->vertex(0) +
1227 cell->face(face)->vertex(2));
1228 cell->face(face)->child(1)->vertex(3) =
1229 .5 * (cell->face(face)->vertex(1) +
1230 cell->face(face)->vertex(3));
1231 cell->face(face)->child(2)->vertex(3) =
1232 .5 * (cell->face(face)->vertex(2) +
1233 cell->face(face)->vertex(3));
1236 cell->face(face)->child(0)->vertex(3) =
1237 .25 * (cell->face(face)->vertex(0) +
1238 cell->face(face)->vertex(1) +
1239 cell->face(face)->vertex(2) +
1240 cell->face(face)->vertex(3));
1248 template <
int dim,
template <
int,
int>
class MeshType,
int spacedim>
1252 const std::vector<bool> & marked_vertices)
1261 marked_vertices.size() == 0,
1263 marked_vertices.size()));
1270 marked_vertices.size() == 0 ||
1271 std::equal(marked_vertices.begin(),
1272 marked_vertices.end(),
1274 [](
bool p,
bool q) { return !p || q; }),
1276 "marked_vertices should be a subset of used vertices in the triangulation "
1277 "but marked_vertices contains one or more vertices that are not used vertices!"));
1281 const std::vector<bool> &vertices_to_use = (marked_vertices.size() == 0) ?
1287 std::vector<bool>::const_iterator
first =
1288 std::find(vertices_to_use.begin(), vertices_to_use.end(),
true);
1293 unsigned int best_vertex = std::distance(vertices_to_use.begin(),
first);
1294 double best_dist = (p -
vertices[best_vertex]).norm_square();
1298 for (
unsigned int j = best_vertex + 1; j <
vertices.size(); j++)
1299 if (vertices_to_use[j])
1301 const double dist = (p -
vertices[j]).norm_square();
1302 if (dist < best_dist)
1314 template <
int dim,
template <
int,
int>
class MeshType,
int spacedim>
1317 const MeshType<dim, spacedim> &mesh,
1319 const std::vector<bool> & marked_vertices)
1332 marked_vertices.size() == 0,
1334 marked_vertices.size()));
1342 marked_vertices.size() == 0 ||
1343 std::equal(marked_vertices.begin(),
1344 marked_vertices.end(),
1346 [](
bool p,
bool q) { return !p || q; }),
1348 "marked_vertices should be a subset of used vertices in the triangulation "
1349 "but marked_vertices contains one or more vertices that are not used vertices!"));
1352 if (marked_vertices.size() != 0)
1355 if (marked_vertices[it->first] ==
false)
1370 template <
int dim,
template <
int,
int>
class MeshType,
int spacedim>
1372 std::vector<typename MeshType<dim, spacedim>::active_cell_iterator>
1375 typename ::internal::
1376 ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>
1379 const unsigned int vertex)
1385 Assert(mesh.get_triangulation().get_used_vertices()[vertex],
1392 ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>
1428 for (
const auto &cell : mesh.active_cell_iterators())
1431 if (cell->vertex_index(v) == vertex)
1436 adjacent_cells.insert(cell);
1443 for (
unsigned int vface = 0; vface < dim; vface++)
1445 const unsigned int face =
1448 if (!cell->at_boundary(face) &&
1449 cell->neighbor(face)->is_active())
1461 adjacent_cells.insert(cell->neighbor(face));
1472 for (
unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++
e)
1473 if (cell->line(
e)->has_children())
1477 if (cell->line(
e)->child(0)->vertex_index(1) == vertex)
1479 adjacent_cells.insert(cell);
1501 typename ::internal::
1502 ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>(
1503 adjacent_cells.begin(), adjacent_cells.end());
1508 template <
int dim,
int spacedim>
1509 std::vector<std::vector<Tensor<1, spacedim>>>
1517 const unsigned int n_vertices = vertex_to_cells.size();
1522 std::vector<std::vector<Tensor<1, spacedim>>> vertex_to_cell_centers(
1524 for (
unsigned int vertex = 0; vertex < n_vertices; ++vertex)
1527 const unsigned int n_neighbor_cells = vertex_to_cells[vertex].size();
1528 vertex_to_cell_centers[vertex].resize(n_neighbor_cells);
1530 typename std::set<typename Triangulation<dim, spacedim>::
1531 active_cell_iterator>::iterator it =
1532 vertex_to_cells[vertex].begin();
1533 for (
unsigned int cell = 0; cell < n_neighbor_cells; ++cell, ++it)
1535 vertex_to_cell_centers[vertex][cell] =
1536 (*it)->center() -
vertices[vertex];
1537 vertex_to_cell_centers[vertex][cell] /=
1538 vertex_to_cell_centers[vertex][cell].norm();
1541 return vertex_to_cell_centers;
1547 template <
int spacedim>
1550 const unsigned int a,
1551 const unsigned int b,
1555 const double scalar_product_a = center_directions[a] * point_direction;
1556 const double scalar_product_b = center_directions[
b] * point_direction;
1561 return (scalar_product_a > scalar_product_b);
1565 template <
int dim,
template <
int,
int>
class MeshType,
int spacedim>
1567 std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
Point<dim>>
1569 std::pair<typename ::internal::
1570 ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type,
1575 const MeshType<dim, spacedim> &mesh,
1578 std::set<
typename MeshType<dim, spacedim>::active_cell_iterator>>
1581 const typename MeshType<dim, spacedim>::active_cell_iterator &cell_hint,
1582 const std::vector<bool> & marked_vertices,
1585 std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
1590 std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
1592 cell_and_position_approx;
1594 bool found_cell =
false;
1595 bool approx_cell =
false;
1597 unsigned int closest_vertex_index = 0;
1599 auto current_cell = cell_hint;
1601 while (found_cell ==
false)
1607 const auto cell_vertices = mapping.
get_vertices(current_cell);
1608 const unsigned int closest_vertex =
1609 find_closest_vertex_of_cell<dim, spacedim>(current_cell,
1612 vertex_to_point = p - cell_vertices[closest_vertex];
1613 closest_vertex_index = current_cell->vertex_index(closest_vertex);
1617 if (!used_vertices_rtree.empty())
1620 using ValueType = std::pair<Point<spacedim>,
unsigned int>;
1621 std::function<
bool(
const ValueType &)> marked;
1622 if (marked_vertices.size() == mesh.n_vertices())
1623 marked = [&marked_vertices](
const ValueType &
value) ->
bool {
1624 return marked_vertices[
value.second];
1627 marked = [](
const ValueType &) ->
bool {
return true; };
1629 std::vector<std::pair<Point<spacedim>,
unsigned int>> res;
1630 used_vertices_rtree.query(
1631 boost::geometry::index::nearest(p, 1) &&
1632 boost::geometry::index::satisfies(marked),
1633 std::back_inserter(res));
1637 closest_vertex_index = res[0].second;
1641 closest_vertex_index =
1644 vertex_to_point = p - mesh.get_vertices()[closest_vertex_index];
1647 const double vertex_point_norm = vertex_to_point.
norm();
1648 if (vertex_point_norm > 0)
1649 vertex_to_point /= vertex_point_norm;
1651 const unsigned int n_neighbor_cells =
1652 vertex_to_cells[closest_vertex_index].size();
1655 std::vector<unsigned int> neighbor_permutation(n_neighbor_cells);
1657 for (
unsigned int i = 0; i < n_neighbor_cells; ++i)
1658 neighbor_permutation[i] = i;
1660 auto comp = [&](
const unsigned int a,
const unsigned int b) ->
bool {
1661 return internal::compare_point_association<spacedim>(
1665 vertex_to_cell_centers[closest_vertex_index]);
1668 std::sort(neighbor_permutation.begin(),
1669 neighbor_permutation.end(),
1675 double best_distance = 1
e-10;
1679 for (
unsigned int i = 0; i < n_neighbor_cells; ++i)
1683 auto cell = vertex_to_cells[closest_vertex_index].begin();
1689 cell_and_position.first = *cell;
1690 cell_and_position.second = p_unit;
1692 approx_cell =
false;
1700 if (dist < best_distance)
1702 best_distance = dist;
1703 cell_and_position_approx.first = *cell;
1704 cell_and_position_approx.second = p_unit;
1712 if (found_cell ==
true)
1713 return cell_and_position;
1714 else if (approx_cell ==
true)
1715 return cell_and_position_approx;
1735 current_cell =
typename MeshType<dim, spacedim>::active_cell_iterator();
1737 return cell_and_position;
1742 template <
int dim,
int spacedim>
1751 unsigned int closest_vertex = 0;
1753 for (
unsigned int v = 1; v < GeometryInfo<dim>::vertices_per_cell; ++v)
1756 if (vertex_distance < minimum_distance)
1759 minimum_distance = vertex_distance;
1762 return closest_vertex;
1769 namespace BoundingBoxPredicate
1771 template <
class MeshType>
1772 std::tuple<BoundingBox<MeshType::space_dimension>,
bool>
1774 const typename MeshType::cell_iterator &parent_cell,
1775 const std::function<
1776 bool(
const typename MeshType::active_cell_iterator &)> &predicate)
1778 bool has_predicate =
1780 std::vector<typename MeshType::active_cell_iterator> active_cells;
1781 if (parent_cell->is_active())
1782 active_cells = {parent_cell};
1786 active_cells = get_active_child_cells<MeshType>(parent_cell);
1788 const unsigned int spacedim = MeshType::space_dimension;
1792 while (i < active_cells.size() && !predicate(active_cells[i]))
1796 if (active_cells.size() == 0 || i == active_cells.size())
1799 return std::make_tuple(bbox, has_predicate);
1806 for (; i < active_cells.size(); ++i)
1807 if (predicate(active_cells[i]))
1808 for (
const unsigned int v :
1810 for (
unsigned int d = 0;
d < spacedim; ++
d)
1812 minp[
d] =
std::min(minp[
d], active_cells[i]->vertex(v)[
d]);
1813 maxp[
d] =
std::max(maxp[
d], active_cells[i]->vertex(v)[
d]);
1816 has_predicate =
true;
1818 return std::make_tuple(bbox, has_predicate);
1825 template <
class MeshType>
1826 std::vector<BoundingBox<MeshType::space_dimension>>
1828 const MeshType &mesh,
1829 const std::function<
bool(
const typename MeshType::active_cell_iterator &)>
1831 const unsigned int refinement_level,
1832 const bool allow_merge,
1833 const unsigned int max_boxes)
1840 refinement_level <= mesh.n_levels(),
1842 "Error: refinement level is higher then total levels in the triangulation!"));
1844 const unsigned int spacedim = MeshType::space_dimension;
1845 std::vector<BoundingBox<spacedim>> bounding_boxes;
1849 for (
unsigned int i = 0; i < refinement_level; ++i)
1850 for (
const typename MeshType::cell_iterator &cell :
1851 mesh.active_cell_iterators_on_level(i))
1853 bool has_predicate =
false;
1855 std::tie(bbox, has_predicate) =
1857 MeshType>(cell, predicate);
1859 bounding_boxes.push_back(bbox);
1863 for (
const typename MeshType::cell_iterator &cell :
1864 mesh.cell_iterators_on_level(refinement_level))
1866 bool has_predicate =
false;
1868 std::tie(bbox, has_predicate) =
1870 MeshType>(cell, predicate);
1872 bounding_boxes.push_back(bbox);
1877 return bounding_boxes;
1883 std::vector<unsigned int> merged_boxes_idx;
1884 bool found_neighbors =
true;
1889 while (found_neighbors)
1891 found_neighbors =
false;
1892 for (
unsigned int i = 0; i < bounding_boxes.size() - 1; ++i)
1894 if (std::find(merged_boxes_idx.begin(),
1895 merged_boxes_idx.end(),
1896 i) == merged_boxes_idx.end())
1897 for (
unsigned int j = i + 1; j < bounding_boxes.size(); ++j)
1898 if (std::find(merged_boxes_idx.begin(),
1899 merged_boxes_idx.end(),
1900 j) == merged_boxes_idx.end() &&
1901 bounding_boxes[i].get_neighbor_type(
1902 bounding_boxes[j]) ==
1905 bounding_boxes[i].merge_with(bounding_boxes[j]);
1906 merged_boxes_idx.push_back(j);
1907 found_neighbors =
true;
1913 std::vector<BoundingBox<spacedim>> merged_b_boxes;
1914 for (
unsigned int i = 0; i < bounding_boxes.size(); ++i)
1915 if (std::find(merged_boxes_idx.begin(), merged_boxes_idx.end(), i) ==
1916 merged_boxes_idx.end())
1917 merged_b_boxes.push_back(bounding_boxes[i]);
1922 if ((merged_b_boxes.size() > max_boxes) && (spacedim > 1))
1924 std::vector<double> volumes;
1925 for (
unsigned int i = 0; i < merged_b_boxes.size(); ++i)
1926 volumes.push_back(merged_b_boxes[i].volume());
1928 while (merged_b_boxes.size() > max_boxes)
1930 unsigned int min_idx =
1931 std::min_element(volumes.begin(), volumes.end()) -
1933 volumes.erase(volumes.begin() + min_idx);
1935 bool not_removed =
true;
1936 for (
unsigned int i = 0;
1937 i < merged_b_boxes.size() && not_removed;
1942 if (i != min_idx && (merged_b_boxes[i].get_neighbor_type(
1943 merged_b_boxes[min_idx]) ==
1945 merged_b_boxes[i].get_neighbor_type(
1946 merged_b_boxes[min_idx]) ==
1949 merged_b_boxes[i].merge_with(merged_b_boxes[min_idx]);
1950 merged_b_boxes.erase(merged_b_boxes.begin() + min_idx);
1951 not_removed =
false;
1954 ExcMessage(
"Error: couldn't merge bounding boxes!"));
1957 Assert(merged_b_boxes.size() <= max_boxes,
1959 "Error: couldn't reach target number of bounding boxes!"));
1960 return merged_b_boxes;
1966 template <
int spacedim>
1968 std::tuple<std::vector<std::vector<unsigned int>>,
1969 std::map<unsigned int, unsigned int>,
1970 std::map<unsigned int, std::vector<unsigned int>>>
1978 unsigned int n_procs = global_bboxes.size();
1979 std::vector<std::vector<unsigned int>> point_owners(n_procs);
1980 std::map<unsigned int, unsigned int> map_owners_found;
1981 std::map<unsigned int, std::vector<unsigned int>> map_owners_guessed;
1983 unsigned int n_points = points.size();
1984 for (
unsigned int pt = 0; pt < n_points; ++pt)
1987 std::vector<unsigned int> owners_found;
1989 for (
unsigned int rk = 0; rk < n_procs; ++rk)
1992 if (bbox.point_inside(points[pt]))
1994 point_owners[rk].emplace_back(pt);
1995 owners_found.emplace_back(rk);
1999 Assert(owners_found.size() > 0,
2000 ExcMessage(
"No owners found for the point " +
2002 if (owners_found.size() == 1)
2003 map_owners_found[pt] = owners_found[0];
2006 map_owners_guessed[pt] = owners_found;
2009 return std::make_tuple(std::move(point_owners),
2010 std::move(map_owners_found),
2011 std::move(map_owners_guessed));
2014 template <
int spacedim>
2016 std::tuple<std::map<unsigned int, std::vector<unsigned int>>,
2017 std::map<unsigned int, unsigned int>,
2018 std::map<unsigned int, std::vector<unsigned int>>>
2026 std::map<unsigned int, std::vector<unsigned int>> point_owners;
2027 std::map<unsigned int, unsigned int> map_owners_found;
2028 std::map<unsigned int, std::vector<unsigned int>> map_owners_guessed;
2029 std::vector<std::pair<BoundingBox<spacedim>,
unsigned int>> search_result;
2031 unsigned int n_points = points.size();
2032 for (
unsigned int pt_n = 0; pt_n < n_points; ++pt_n)
2034 search_result.clear();
2037 covering_rtree.query(boost::geometry::index::intersects(points[pt_n]),
2038 std::back_inserter(search_result));
2041 std::set<unsigned int> owners_found;
2043 for (
const auto &rank_bbox : search_result)
2047 const bool pt_inserted = owners_found.insert(pt_n).second;
2049 point_owners[rank_bbox.second].emplace_back(pt_n);
2051 Assert(owners_found.size() > 0,
2052 ExcMessage(
"No owners found for the point " +
2054 if (owners_found.size() == 1)
2055 map_owners_found[pt_n] = *owners_found.begin();
2060 std::back_inserter(map_owners_guessed[pt_n]));
2063 return std::make_tuple(std::move(point_owners),
2064 std::move(map_owners_found),
2065 std::move(map_owners_guessed));
2069 template <
int dim,
int spacedim>
2071 std::set<typename Triangulation<dim, spacedim>::active_cell_iterator>>
2075 std::set<typename Triangulation<dim, spacedim>::active_cell_iterator>>
2080 for (; cell != endc; ++cell)
2086 for (; cell != endc; ++cell)
2090 if ((cell->at_boundary(i) ==
false) &&
2091 (cell->neighbor(i)->is_active()))
2094 adjacent_cell = cell->neighbor(i);
2095 for (
unsigned int j = 0;
2096 j < GeometryInfo<dim>::vertices_per_face;
2106 for (
unsigned int i = 0; i < GeometryInfo<dim>::lines_per_cell; ++i)
2107 if (cell->line(i)->has_children())
2121 template <
int dim,
int spacedim>
2122 std::map<unsigned int, types::global_vertex_index>
2126 std::map<unsigned int, types::global_vertex_index>
2127 local_to_global_vertex_index;
2129 #ifndef DEAL_II_WITH_MPI
2136 ExcMessage(
"This function does not make any sense "
2137 "for parallel::distributed::Triangulation "
2138 "objects if you do not have MPI enabled."));
2142 using active_cell_iterator =
2144 const std::vector<std::set<active_cell_iterator>> vertex_to_cell =
2149 unsigned int max_cellid_size = 0;
2150 std::set<std::pair<types::subdomain_id, types::global_vertex_index>>
2152 std::map<types::subdomain_id, std::set<unsigned int>> vertices_to_recv;
2160 std::set<active_cell_iterator> missing_vert_cells;
2161 std::set<unsigned int> used_vertex_index;
2162 for (; cell != endc; ++cell)
2164 if (cell->is_locally_owned())
2169 typename std::set<active_cell_iterator>::iterator
2170 adjacent_cell = vertex_to_cell[cell->vertex_index(i)].begin(),
2171 end_adj_cell = vertex_to_cell[cell->vertex_index(i)].end();
2172 for (; adjacent_cell != end_adj_cell; ++adjacent_cell)
2173 lowest_subdomain_id =
2175 (*adjacent_cell)->subdomain_id());
2178 if (lowest_subdomain_id == cell->subdomain_id())
2182 if (used_vertex_index.find(cell->vertex_index(i)) ==
2183 used_vertex_index.end())
2186 local_to_global_vertex_index[cell->vertex_index(i)] =
2192 vertex_to_cell[cell->vertex_index(i)].begin();
2193 for (; adjacent_cell != end_adj_cell; ++adjacent_cell)
2194 if ((*adjacent_cell)->subdomain_id() !=
2195 cell->subdomain_id())
2199 tmp((*adjacent_cell)->subdomain_id(),
2200 cell->vertex_index(i));
2201 if (vertices_added.find(tmp) ==
2202 vertices_added.end())
2204 vertices_to_send[(*adjacent_cell)
2207 cell->vertex_index(i),
2208 cell->id().to_string());
2209 if (cell->id().to_string().size() >
2212 cell->id().to_string().size();
2213 vertices_added.insert(tmp);
2216 used_vertex_index.insert(cell->vertex_index(i));
2223 vertices_to_recv[lowest_subdomain_id].insert(
2224 cell->vertex_index(i));
2225 missing_vert_cells.insert(cell);
2232 if (cell->is_ghost())
2236 if (cell->at_boundary(i) ==
false)
2238 if (cell->neighbor(i)->is_active())
2241 spacedim>::active_cell_iterator
2242 adjacent_cell = cell->neighbor(i);
2243 if ((adjacent_cell->is_locally_owned()))
2246 adjacent_cell->subdomain_id();
2247 if (cell->subdomain_id() < adj_subdomain_id)
2248 for (
unsigned int j = 0;
2249 j < GeometryInfo<dim>::vertices_per_face;
2252 vertices_to_recv[cell->subdomain_id()].insert(
2253 cell->face(i)->vertex_index(j));
2254 missing_vert_cells.insert(cell);
2270 int ierr = MPI_Exscan(&next_index,
2278 std::map<unsigned int, types::global_vertex_index>::iterator
2279 global_index_it = local_to_global_vertex_index.begin(),
2280 global_index_end = local_to_global_vertex_index.end();
2281 for (; global_index_it != global_index_end; ++global_index_it)
2282 global_index_it->second +=
shift;
2296 std::vector<std::vector<types::global_vertex_index>> vertices_send_buffers(
2297 vertices_to_send.size());
2298 std::vector<MPI_Request> first_requests(vertices_to_send.size());
2302 std::string>>>::iterator
2303 vert_to_send_it = vertices_to_send.begin(),
2304 vert_to_send_end = vertices_to_send.end();
2305 for (
unsigned int i = 0; vert_to_send_it != vert_to_send_end;
2306 ++vert_to_send_it, ++i)
2308 int destination = vert_to_send_it->first;
2309 const unsigned int n_vertices = vert_to_send_it->second.size();
2310 const int buffer_size = 2 * n_vertices;
2311 vertices_send_buffers[i].resize(buffer_size);
2314 for (
unsigned int j = 0; j < n_vertices; ++j)
2316 vertices_send_buffers[i][2 * j] =
2317 std::get<0>(vert_to_send_it->second[j]);
2318 vertices_send_buffers[i][2 * j + 1] =
2319 local_to_global_vertex_index[std::get<1>(
2320 vert_to_send_it->second[j])];
2324 ierr = MPI_Isend(vertices_send_buffers[i].data(),
2330 &first_requests[i]);
2335 std::vector<std::vector<types::global_vertex_index>> vertices_recv_buffers(
2336 vertices_to_recv.size());
2337 typename std::map<types::subdomain_id, std::set<unsigned int>>::iterator
2338 vert_to_recv_it = vertices_to_recv.begin(),
2339 vert_to_recv_end = vertices_to_recv.end();
2340 for (
unsigned int i = 0; vert_to_recv_it != vert_to_recv_end;
2341 ++vert_to_recv_it, ++i)
2343 int source = vert_to_recv_it->first;
2344 const unsigned int n_vertices = vert_to_recv_it->second.size();
2345 const int buffer_size = 2 * n_vertices;
2346 vertices_recv_buffers[i].resize(buffer_size);
2349 ierr = MPI_Recv(vertices_recv_buffers[i].data(),
2361 std::vector<std::vector<char>> cellids_send_buffers(
2362 vertices_to_send.size());
2363 std::vector<MPI_Request> second_requests(vertices_to_send.size());
2364 vert_to_send_it = vertices_to_send.begin();
2365 for (
unsigned int i = 0; vert_to_send_it != vert_to_send_end;
2366 ++vert_to_send_it, ++i)
2368 int destination = vert_to_send_it->first;
2369 const unsigned int n_vertices = vert_to_send_it->second.size();
2370 const int buffer_size = max_cellid_size * n_vertices;
2371 cellids_send_buffers[i].resize(buffer_size);
2374 unsigned int pos = 0;
2375 for (
unsigned int j = 0; j < n_vertices; ++j)
2377 std::string cell_id = std::get<2>(vert_to_send_it->second[j]);
2378 for (
unsigned int k = 0; k < max_cellid_size; ++k, ++pos)
2380 if (k < cell_id.size())
2381 cellids_send_buffers[i][pos] = cell_id[k];
2385 cellids_send_buffers[i][pos] =
'-';
2390 ierr = MPI_Isend(cellids_send_buffers[i].data(),
2396 &second_requests[i]);
2401 std::vector<std::vector<char>> cellids_recv_buffers(
2402 vertices_to_recv.size());
2403 vert_to_recv_it = vertices_to_recv.begin();
2404 for (
unsigned int i = 0; vert_to_recv_it != vert_to_recv_end;
2405 ++vert_to_recv_it, ++i)
2407 int source = vert_to_recv_it->first;
2408 const unsigned int n_vertices = vert_to_recv_it->second.size();
2409 const int buffer_size = max_cellid_size * n_vertices;
2410 cellids_recv_buffers[i].resize(buffer_size);
2413 ierr = MPI_Recv(cellids_recv_buffers[i].data(),
2425 vert_to_recv_it = vertices_to_recv.begin();
2426 for (
unsigned int i = 0; vert_to_recv_it != vert_to_recv_end;
2427 ++i, ++vert_to_recv_it)
2429 for (
unsigned int j = 0; j < vert_to_recv_it->second.size(); ++j)
2431 const unsigned int local_pos_recv = vertices_recv_buffers[i][2 * j];
2433 vertices_recv_buffers[i][2 * j + 1];
2434 const std::string cellid_recv(
2435 &cellids_recv_buffers[i][max_cellid_size * j],
2436 &cellids_recv_buffers[i][max_cellid_size * j] + max_cellid_size);
2438 typename std::set<active_cell_iterator>::iterator
2439 cell_set_it = missing_vert_cells.begin(),
2440 end_cell_set = missing_vert_cells.end();
2441 for (; (found ==
false) && (cell_set_it != end_cell_set);
2444 typename std::set<active_cell_iterator>::iterator
2446 vertex_to_cell[(*cell_set_it)->vertex_index(i)].begin(),
2448 vertex_to_cell[(*cell_set_it)->vertex_index(i)].end();
2449 for (; candidate_cell != end_cell; ++candidate_cell)
2451 std::string current_cellid =
2452 (*candidate_cell)->id().to_string();
2453 current_cellid.resize(max_cellid_size,
'-');
2454 if (current_cellid.compare(cellid_recv) == 0)
2456 local_to_global_vertex_index
2457 [(*candidate_cell)->vertex_index(local_pos_recv)] =
2469 return local_to_global_vertex_index;
2474 template <
int dim,
int spacedim>
2488 std::map<std::pair<unsigned int, unsigned int>,
unsigned int> indexmap;
2489 for (
const auto &cell :
triangulation.active_cell_iterators())
2490 indexmap[std::pair<unsigned int, unsigned int>(cell->level(),
2492 cell->active_cell_index();
2501 for (
const auto &cell :
triangulation.active_cell_iterators())
2503 const unsigned int index = cell->active_cell_index();
2504 cell_connectivity.
add(index, index);
2506 if ((cell->at_boundary(f) ==
false) &&
2507 (cell->neighbor(f)->has_children() ==
false))
2509 const unsigned int other_index =
2511 .find(std::pair<unsigned int, unsigned int>(
2512 cell->neighbor(f)->level(), cell->neighbor(f)->index()))
2514 cell_connectivity.
add(index, other_index);
2515 cell_connectivity.
add(other_index, index);
2522 template <
int dim,
int spacedim>
2528 std::vector<std::vector<unsigned int>> vertex_to_cell(
2530 for (
const auto &cell :
triangulation.active_cell_iterators())
2533 vertex_to_cell[cell->vertex_index(v)].push_back(
2534 cell->active_cell_index());
2539 for (
const auto &cell :
triangulation.active_cell_iterators())
2542 for (
unsigned int n = 0;
2543 n < vertex_to_cell[cell->vertex_index(v)].size();
2545 cell_connectivity.
add(cell->active_cell_index(),
2546 vertex_to_cell[cell->vertex_index(v)][n]);
2551 template <
int dim,
int spacedim>
2555 const unsigned int level,
2558 std::vector<std::vector<unsigned int>> vertex_to_cell(
2566 vertex_to_cell[cell->vertex_index(v)].push_back(cell->index());
2577 for (
unsigned int n = 0;
2578 n < vertex_to_cell[cell->vertex_index(v)].size();
2580 cell_connectivity.
add(cell->index(),
2581 vertex_to_cell[cell->vertex_index(v)][n]);
2587 template <
int dim,
int spacedim>
2595 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
2596 "are already partitioned implicitly and can not be "
2597 "partitioned again explicitly."));
2599 std::vector<unsigned int> cell_weights;
2609 for (
const auto &cell :
triangulation.active_cell_iterators())
2610 if (cell->is_locally_owned())
2611 cell_weights[cell->active_cell_index()] =
2621 if (
const auto shared_tria =
2625 shared_tria->get_communicator(),
2638 template <
int dim,
int spacedim>
2641 const std::vector<unsigned int> &cell_weights,
2647 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
2648 "are already partitioned implicitly and can not be "
2649 "partitioned again explicitly."));
2653 if (n_partitions == 1)
2655 for (
const auto &cell :
triangulation.active_cell_iterators())
2656 cell->set_subdomain_id(0);
2670 sp_cell_connectivity.
copy_from(cell_connectivity);
2673 sp_cell_connectivity,
2680 template <
int dim,
int spacedim>
2689 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
2690 "are already partitioned implicitly and can not be "
2691 "partitioned again explicitly."));
2693 std::vector<unsigned int> cell_weights;
2703 for (
const auto &cell :
triangulation.active_cell_iterators())
2704 if (cell->is_locally_owned())
2705 cell_weights[cell->active_cell_index()] =
2715 if (
const auto shared_tria =
2719 shared_tria->get_communicator(),
2726 cell_connection_graph,
2733 template <
int dim,
int spacedim>
2736 const std::vector<unsigned int> &cell_weights,
2743 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
2744 "are already partitioned implicitly and can not be "
2745 "partitioned again explicitly."));
2748 ExcMessage(
"Connectivity graph has wrong size"));
2750 ExcMessage(
"Connectivity graph has wrong size"));
2756 if (n_partitions == 1)
2758 for (
const auto &cell :
triangulation.active_cell_iterators())
2759 cell->set_subdomain_id(0);
2767 std::vector<unsigned int> partition_indices(
triangulation.n_active_cells());
2775 for (
const auto &cell :
triangulation.active_cell_iterators())
2776 cell->set_subdomain_id(partition_indices[cell->active_cell_index()]);
2788 unsigned int & current_proc_idx,
2789 unsigned int & current_cell_idx,
2791 const unsigned int n_partitions)
2793 if (cell->is_active())
2795 while (current_cell_idx >=
2797 (current_proc_idx + 1) / n_partitions))
2799 cell->set_subdomain_id(current_proc_idx);
2804 for (
unsigned int n = 0; n < cell->n_children(); ++n)
2814 template <
int dim,
int spacedim>
2818 const bool group_siblings)
2822 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
2823 "are already partitioned implicitly and can not be "
2824 "partitioned again explicitly."));
2831 if (n_partitions == 1)
2833 for (
const auto &cell :
triangulation.active_cell_iterators())
2834 cell->set_subdomain_id(0);
2840 std::vector<types::global_dof_index> coarse_cell_to_p4est_tree_permutation;
2841 std::vector<types::global_dof_index> p4est_tree_to_coarse_cell_permutation;
2847 coarse_cell_to_p4est_tree_permutation.resize(
triangulation.n_cells(0));
2849 coarse_cell_to_p4est_tree_permutation);
2851 p4est_tree_to_coarse_cell_permutation =
2854 unsigned int current_proc_idx = 0;
2855 unsigned int current_cell_idx = 0;
2860 for (
unsigned int idx = 0; idx <
triangulation.n_cells(0); ++idx)
2862 const unsigned int coarse_cell_idx =
2863 p4est_tree_to_coarse_cell_permutation[idx];
2886 for (; cell != endc; ++cell)
2888 if (cell->is_active())
2890 bool all_children_active =
true;
2891 std::map<unsigned int, unsigned int> map_cpu_n_cells;
2892 for (
unsigned int n = 0; n < cell->n_children(); ++n)
2893 if (!cell->child(n)->is_active())
2895 all_children_active =
false;
2899 ++map_cpu_n_cells[cell->child(n)->subdomain_id()];
2901 if (!all_children_active)
2904 unsigned int new_owner = cell->child(0)->subdomain_id();
2905 for (std::map<unsigned int, unsigned int>::iterator it =
2906 map_cpu_n_cells.begin();
2907 it != map_cpu_n_cells.end();
2909 if (it->second > map_cpu_n_cells[new_owner])
2910 new_owner = it->first;
2912 for (
unsigned int n = 0; n < cell->n_children(); ++n)
2913 cell->child(n)->set_subdomain_id(new_owner);
2919 template <
int dim,
int spacedim>
2924 for (
int lvl = n_levels - 1; lvl >= 0; --lvl)
2929 for (; cell != endc; ++cell)
2931 if (cell->is_active())
2932 cell->set_level_subdomain_id(cell->subdomain_id());
2935 Assert(cell->child(0)->level_subdomain_id() !=
2938 cell->set_level_subdomain_id(
2939 cell->child(0)->level_subdomain_id());
2946 template <
int dim,
int spacedim>
2949 std::vector<types::subdomain_id> & subdomain)
2954 for (
const auto &cell :
triangulation.active_cell_iterators())
2955 subdomain[cell->active_cell_index()] = cell->subdomain_id();
2960 template <
int dim,
int spacedim>
2966 unsigned int count = 0;
2967 for (
const auto &cell :
triangulation.active_cell_iterators())
2968 if (cell->subdomain_id() == subdomain)
2976 template <
int dim,
int spacedim>
2981 std::vector<bool> locally_owned_vertices =
2991 for (
const auto &cell :
triangulation.active_cell_iterators())
2992 if (cell->is_artificial() ||
2993 (cell->is_ghost() &&
2994 (cell->subdomain_id() < tr->locally_owned_subdomain())))
2996 locally_owned_vertices[cell->vertex_index(v)] =
false;
2998 return locally_owned_vertices;
3005 template <
int dim,
int spacedim>
3031 template <
int dim,
int spacedim>
3037 for (
const auto &cell :
triangulation.active_cell_iterators())
3038 if (!cell->is_artificial())
3041 internal::diameter<dim, spacedim>(cell, mapping));
3043 double global_min_diameter = 0;
3045 #ifdef DEAL_II_WITH_MPI
3049 global_min_diameter =
3053 global_min_diameter = min_diameter;
3055 return global_min_diameter;
3060 template <
int dim,
int spacedim>
3065 double max_diameter = 0.;
3066 for (
const auto &cell :
triangulation.active_cell_iterators())
3067 if (!cell->is_artificial())
3071 double global_max_diameter = 0;
3073 #ifdef DEAL_II_WITH_MPI
3077 global_max_diameter =
3081 global_max_diameter = max_diameter;
3083 return global_max_diameter;
3090 namespace FixUpDistortedChildCells
3113 template <
typename Iterator,
int spacedim>
3118 const unsigned int structdim =
3119 Iterator::AccessorType::structure_dimension;
3120 Assert(spacedim == Iterator::AccessorType::dimension,
3126 Assert(object->refinement_case() ==
3134 Tensor<spacedim - structdim, spacedim>
3138 parent_vertices[i] =
object->vertex(i);
3141 parent_vertices, parent_alternating_forms);
3143 const Tensor<spacedim - structdim, spacedim>
3144 average_parent_alternating_form =
3145 std::accumulate(parent_alternating_forms,
3146 parent_alternating_forms +
3160 Tensor<spacedim - structdim, spacedim> child_alternating_forms
3164 for (
unsigned int c = 0; c <
object->n_children(); ++c)
3166 child_vertices[c][i] =
object->child(c)->vertex(i);
3174 for (
unsigned int c = 0; c <
object->n_children(); ++c)
3176 1] = object_mid_point;
3178 for (
unsigned int c = 0; c <
object->n_children(); ++c)
3180 child_vertices[c], child_alternating_forms[c]);
3192 double objective = 0;
3193 for (
unsigned int c = 0; c <
object->n_children(); ++c)
3196 (child_alternating_forms[c][i] -
3197 average_parent_alternating_form / std::pow(2., 1. * structdim))
3209 template <
typename Iterator>
3212 const unsigned int f,
3213 std::integral_constant<int, 1>)
3215 return object->vertex(f);
3225 template <
typename Iterator>
3228 const unsigned int f,
3229 std::integral_constant<int, 2>)
3231 return object->line(f)->center();
3241 template <
typename Iterator>
3244 const unsigned int f,
3245 std::integral_constant<int, 3>)
3247 return object->face(f)->center();
3274 template <
typename Iterator>
3278 const unsigned int structdim =
3279 Iterator::AccessorType::structure_dimension;
3281 double diameter =
object->diameter();
3283 for (
unsigned int e = f + 1;
3284 e < GeometryInfo<structdim>::faces_per_cell;
3290 std::integral_constant<int, structdim>())
3292 object,
e, std::integral_constant<int, structdim>())));
3303 template <
typename Iterator>
3307 const unsigned int structdim =
3308 Iterator::AccessorType::structure_dimension;
3309 const unsigned int spacedim = Iterator::AccessorType::space_dimension;
3316 Assert(object->refinement_case() ==
3326 unsigned int iteration = 0;
3331 double initial_delta = 0;
3338 const double step_length =
diameter / 4 / (iteration + 1);
3343 for (
unsigned int d = 0;
d < spacedim; ++
d)
3345 const double eps = step_length / 10;
3359 if (gradient.
norm() == 0)
3368 std::min(2 * current_value / (gradient * gradient),
3369 step_length / gradient.norm()) *
3374 const double previous_value = current_value;
3378 initial_delta = (previous_value - current_value);
3381 if ((iteration >= 1) &&
3382 ((previous_value - current_value < 0) ||
3383 (
std::fabs(previous_value - current_value) <
3384 0.001 * initial_delta)))
3389 while (iteration < 20);
3405 double old_min_product, new_min_product;
3410 parent_vertices[i] = object->vertex(i);
3412 Tensor<spacedim - structdim, spacedim>
3415 parent_vertices, parent_alternating_forms);
3421 for (
unsigned int c = 0; c <
object->n_children(); ++c)
3423 child_vertices[c][i] =
object->child(c)->vertex(i);
3425 Tensor<spacedim - structdim, spacedim> child_alternating_forms
3429 for (
unsigned int c = 0; c <
object->n_children(); ++c)
3431 child_vertices[c], child_alternating_forms[c]);
3434 child_alternating_forms[0][0] * parent_alternating_forms[0];
3435 for (
unsigned int c = 0; c <
object->n_children(); ++c)
3437 for (
const unsigned int j :
3439 old_min_product = std::min<double>(old_min_product,
3440 child_alternating_forms[c][i] *
3441 parent_alternating_forms[j]);
3449 for (
unsigned int c = 0; c <
object->n_children(); ++c)
3451 1] = object_mid_point;
3453 for (
unsigned int c = 0; c <
object->n_children(); ++c)
3455 child_vertices[c], child_alternating_forms[c]);
3458 child_alternating_forms[0][0] * parent_alternating_forms[0];
3459 for (
unsigned int c = 0; c <
object->n_children(); ++c)
3461 for (
const unsigned int j :
3463 new_min_product = std::min<double>(new_min_product,
3464 child_alternating_forms[c][i] *
3465 parent_alternating_forms[j]);
3473 if (new_min_product >= old_min_product)
3474 object->child(0)->vertex(
3481 return (
std::max(new_min_product, old_min_product) > 0);
3487 template <
int dim,
int spacedim>
3490 const typename ::Triangulation<dim, spacedim>::cell_iterator
3492 std::integral_constant<int, dim>,
3493 std::integral_constant<int, spacedim>)
3506 Assert(cell->face(f)->refinement_case() ==
3510 bool subface_is_more_refined =
false;
3511 for (
unsigned int g = 0;
3512 g < GeometryInfo<dim>::max_children_per_face;
3514 if (cell->face(f)->child(g)->has_children())
3516 subface_is_more_refined =
true;
3520 if (subface_is_more_refined ==
true)
3531 template <
int dim,
int spacedim>
3539 dim != 1 && spacedim != 1,
3540 "This function is only valid when dim != 1 or spacedim != 1.");
3544 for (
typename std::list<
3553 Assert(!cell->is_active(),
3555 "This function is only valid for a list of cells that "
3556 "have children (i.e., no cell in the list may be active)."));
3560 std::integral_constant<int, dim>(),
3561 std::integral_constant<int, spacedim>());
3568 return unfixable_subset;
3573 template <
int dim,
int spacedim>
3576 const bool reset_boundary_ids)
3579 std::vector<types::manifold_id> dst_manifold_ids(src_boundary_ids.size());
3580 auto m_it = dst_manifold_ids.begin();
3581 for (
const auto b : src_boundary_ids)
3586 const std::vector<types::boundary_id> reset_boundary_id =
3587 reset_boundary_ids ?
3588 std::vector<types::boundary_id>(src_boundary_ids.size(), 0) :
3598 template <
int dim,
int spacedim>
3601 const std::vector<types::boundary_id> &src_boundary_ids,
3602 const std::vector<types::manifold_id> &dst_manifold_ids,
3604 const std::vector<types::boundary_id> &reset_boundary_ids_)
3607 const auto reset_boundary_ids =
3608 reset_boundary_ids_.size() ? reset_boundary_ids_ : src_boundary_ids;
3618 if (cell->face(f)->at_boundary())
3619 for (
unsigned int e = 0; e < GeometryInfo<dim>::lines_per_face; ++
e)
3621 const auto bid = cell->face(f)->line(
e)->boundary_id();
3622 const unsigned int ind = std::find(src_boundary_ids.begin(),
3623 src_boundary_ids.end(),
3625 src_boundary_ids.begin();
3626 if (ind < src_boundary_ids.size())
3627 cell->face(f)->line(
e)->set_manifold_id(
3628 dst_manifold_ids[ind]);
3634 if (cell->face(f)->at_boundary())
3636 const auto bid = cell->face(f)->boundary_id();
3637 const unsigned int ind =
3638 std::find(src_boundary_ids.begin(), src_boundary_ids.end(), bid) -
3639 src_boundary_ids.begin();
3641 if (ind < src_boundary_ids.size())
3644 cell->face(f)->set_manifold_id(dst_manifold_ids[ind]);
3646 cell->face(f)->set_boundary_id(reset_boundary_ids[ind]);
3650 for (
unsigned int e = 0; e < GeometryInfo<dim>::lines_per_face;
3653 const auto bid = cell->face(f)->line(
e)->boundary_id();
3654 const unsigned int ind = std::find(src_boundary_ids.begin(),
3655 src_boundary_ids.end(),
3657 src_boundary_ids.begin();
3658 if (ind < src_boundary_ids.size())
3659 cell->face(f)->line(
e)->set_boundary_id(
3660 reset_boundary_ids[ind]);
3666 template <
int dim,
int spacedim>
3669 const bool compute_face_ids)
3675 for (; cell != endc; ++cell)
3677 cell->set_manifold_id(cell->material_id());
3678 if (compute_face_ids ==
true)
3682 if (cell->at_boundary(f) ==
false)
3683 cell->face(f)->set_manifold_id(
3685 cell->neighbor(f)->material_id()));
3687 cell->face(f)->set_manifold_id(cell->material_id());
3694 template <
int dim,
int spacedim>
3699 const std::set<types::manifold_id> &)> &disambiguation_function,
3700 bool overwrite_only_flat_manifold_ids)
3705 const unsigned int n_subobjects =
3709 std::vector<std::set<types::manifold_id>> manifold_ids(n_subobjects + 1);
3710 std::vector<unsigned int> backup;
3714 unsigned next_index = 1;
3718 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
3720 if (cell->line(
l)->user_index() == 0)
3723 manifold_ids[next_index].insert(cell->manifold_id());
3724 cell->line(
l)->set_user_index(next_index++);
3727 manifold_ids[cell->line(
l)->user_index()].insert(
3728 cell->manifold_id());
3731 for (
unsigned int l = 0; l < GeometryInfo<dim>::quads_per_cell; ++
l)
3733 if (cell->quad(
l)->user_index() == 0)
3736 manifold_ids[next_index].insert(cell->manifold_id());
3737 cell->quad(
l)->set_user_index(next_index++);
3740 manifold_ids[cell->quad(
l)->user_index()].insert(
3741 cell->manifold_id());
3747 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
3749 const auto id = cell->line(
l)->user_index();
3753 if (cell->line(
l)->manifold_id() ==
3755 overwrite_only_flat_manifold_ids ==
false)
3756 cell->line(
l)->set_manifold_id(
3757 disambiguation_function(manifold_ids[
id]));
3758 cell->line(
l)->set_user_index(0);
3762 for (
unsigned int l = 0; l < GeometryInfo<dim>::quads_per_cell; ++
l)
3764 const auto id = cell->quad(
l)->user_index();
3768 if (cell->quad(
l)->manifold_id() ==
3770 overwrite_only_flat_manifold_ids ==
false)
3771 cell->quad(
l)->set_manifold_id(
3772 disambiguation_function(manifold_ids[
id]));
3773 cell->quad(
l)->set_user_index(0);
3782 template <
int dim,
int spacedim>
3783 std::pair<unsigned int, double>
3787 double max_ratio = 1;
3788 unsigned int index = 0;
3790 for (
unsigned int i = 0; i < dim; ++i)
3791 for (
unsigned int j = i + 1; j < dim; ++j)
3793 unsigned int ax = i % dim;
3794 unsigned int next_ax = j % dim;
3797 cell->extent_in_direction(ax) / cell->extent_in_direction(next_ax);
3799 if (ratio > max_ratio)
3804 else if (1.0 / ratio > max_ratio)
3806 max_ratio = 1.0 / ratio;
3810 return std::make_pair(index, max_ratio);
3814 template <
int dim,
int spacedim>
3817 const bool isotropic,
3818 const unsigned int max_iterations)
3820 unsigned int iter = 0;
3821 bool continue_refinement =
true;
3823 while (continue_refinement && (iter < max_iterations))
3827 continue_refinement =
false;
3831 if (cell->at_boundary(j) ==
false &&
3832 cell->neighbor(j)->has_children())
3836 cell->set_refine_flag();
3837 continue_refinement =
true;
3840 continue_refinement |= cell->flag_for_face_refinement(j);
3847 template <
int dim,
int spacedim>
3850 const double max_ratio,
3851 const unsigned int max_iterations)
3853 unsigned int iter = 0;
3854 bool continue_refinement =
true;
3856 while (continue_refinement && (iter < max_iterations))
3859 continue_refinement =
false;
3862 std::pair<unsigned int, double> info =
3863 GridTools::get_longest_direction<dim, spacedim>(cell);
3864 if (info.second > max_ratio)
3866 cell->set_refine_flag(
3868 continue_refinement =
true;
3876 template <
int dim,
int spacedim>
3879 const double limit_angle_fraction)
3887 "have hanging nodes."));
3890 bool has_cells_with_more_than_dim_faces_on_boundary =
true;
3891 bool has_cells_with_dim_faces_on_boundary =
false;
3893 unsigned int refinement_cycles = 0;
3895 while (has_cells_with_more_than_dim_faces_on_boundary)
3897 has_cells_with_more_than_dim_faces_on_boundary =
false;
3901 unsigned int boundary_face_counter = 0;
3903 if (cell->face(f)->at_boundary())
3904 boundary_face_counter++;
3905 if (boundary_face_counter > dim)
3907 has_cells_with_more_than_dim_faces_on_boundary =
true;
3910 else if (boundary_face_counter == dim)
3911 has_cells_with_dim_faces_on_boundary =
true;
3913 if (has_cells_with_more_than_dim_faces_on_boundary)
3916 refinement_cycles++;
3920 if (has_cells_with_dim_faces_on_boundary)
3923 refinement_cycles++;
3927 while (refinement_cycles > 0)
3930 cell->set_coarsen_flag();
3932 refinement_cycles--;
3940 std::vector<bool> faces_to_remove(tria.
n_raw_faces(),
false);
3942 std::vector<CellData<dim>> cells_to_add;
3946 const unsigned int v0 = 0, v1 = 1, v2 = (dim > 1 ? 2 : 0),
3947 v3 = (dim > 1 ? 3 : 0);
3951 double angle_fraction = 0;
3957 p0[spacedim > 1 ? 1 : 0] = 1;
3961 if (cell->face(v0)->at_boundary() && cell->face(v3)->at_boundary())
3963 p0 = cell->vertex(v0) - cell->vertex(v2);
3964 p1 = cell->vertex(v3) - cell->vertex(v2);
3965 vertex_at_corner = v2;
3967 else if (cell->face(v3)->at_boundary() &&
3968 cell->face(v1)->at_boundary())
3970 p0 = cell->vertex(v2) - cell->vertex(v3);
3971 p1 = cell->vertex(v1) - cell->vertex(v3);
3972 vertex_at_corner = v3;
3974 else if (cell->face(1)->at_boundary() &&
3975 cell->face(2)->at_boundary())
3977 p0 = cell->vertex(v0) - cell->vertex(v1);
3978 p1 = cell->vertex(v3) - cell->vertex(v1);
3979 vertex_at_corner = v1;
3981 else if (cell->face(2)->at_boundary() &&
3982 cell->face(0)->at_boundary())
3984 p0 = cell->vertex(v2) - cell->vertex(v0);
3985 p1 = cell->vertex(v1) - cell->vertex(v0);
3986 vertex_at_corner = v0;
3997 if (angle_fraction > limit_angle_fraction)
3999 auto flags_removal = [&](
unsigned int f1,
4002 unsigned int n2) ->
void {
4003 cells_to_remove[cell->active_cell_index()] =
true;
4004 cells_to_remove[cell->neighbor(n1)->active_cell_index()] =
true;
4005 cells_to_remove[cell->neighbor(n2)->active_cell_index()] =
true;
4007 faces_to_remove[cell->face(f1)->index()] =
true;
4008 faces_to_remove[cell->face(f2)->index()] =
true;
4010 faces_to_remove[cell->neighbor(n1)->face(f1)->index()] =
true;
4011 faces_to_remove[cell->neighbor(n2)->face(f2)->index()] =
true;
4014 auto cell_creation = [&](
const unsigned int vv0,
4015 const unsigned int vv1,
4016 const unsigned int f0,
4017 const unsigned int f1,
4019 const unsigned int n0,
4020 const unsigned int v0n0,
4021 const unsigned int v1n0,
4023 const unsigned int n1,
4024 const unsigned int v0n1,
4025 const unsigned int v1n1) {
4029 c1.
vertices[v0] = cell->vertex_index(vv0);
4030 c1.
vertices[v1] = cell->vertex_index(vv1);
4031 c1.
vertices[v2] = cell->neighbor(n0)->vertex_index(v0n0);
4032 c1.
vertices[v3] = cell->neighbor(n0)->vertex_index(v1n0);
4037 c2.
vertices[v0] = cell->vertex_index(vv0);
4038 c2.
vertices[v1] = cell->neighbor(n1)->vertex_index(v0n1);
4039 c2.
vertices[v2] = cell->vertex_index(vv1);
4040 c2.
vertices[v3] = cell->neighbor(n1)->vertex_index(v1n1);
4045 l1.
vertices[0] = cell->vertex_index(vv0);
4046 l1.
vertices[1] = cell->neighbor(n0)->vertex_index(v0n0);
4052 l2.
vertices[0] = cell->vertex_index(vv0);
4053 l2.
vertices[1] = cell->neighbor(n1)->vertex_index(v0n1);
4059 cells_to_add.push_back(c1);
4060 cells_to_add.push_back(c2);
4065 switch (vertex_at_corner)
4068 flags_removal(0, 2, 3, 1);
4069 cell_creation(0, 3, 0, 2, 3, 2, 3, 1, 1, 3);
4072 flags_removal(1, 2, 3, 0);
4073 cell_creation(1, 2, 2, 1, 0, 0, 2, 3, 3, 2);
4076 flags_removal(3, 0, 1, 2);
4077 cell_creation(2, 1, 3, 0, 1, 3, 1, 2, 0, 1);
4080 flags_removal(3, 1, 0, 2);
4081 cell_creation(3, 0, 1, 3, 2, 1, 0, 0, 2, 0);
4094 if (cells_to_add.size() == 0)
4096 while (refinement_cycles > 0)
4099 cell->set_coarsen_flag();
4101 refinement_cycles--;
4109 if (cells_to_remove[cell->active_cell_index()] ==
false)
4113 c.
vertices[v] = cell->vertex_index(v);
4116 cells_to_add.push_back(c);
4124 for (; face != endf; ++face)
4125 if ((face->at_boundary() ||
4127 faces_to_remove[face->index()] ==
false)
4129 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_face; ++
l)
4135 line.
vertices[v] = face->vertex_index(v);
4142 line.
vertices[v] = face->line(
l)->vertex_index(v);
4152 quad.
vertices[v] = face->vertex_index(v);
4160 subcelldata_to_add);
4165 std::map<types::manifold_id, std::unique_ptr<Manifold<dim, spacedim>>>
4184 template <
int dim,
int spacedim>
4187 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
4188 std::vector<std::vector<Point<dim>>>,
4189 std::vector<std::vector<unsigned int>>>
4201 auto &cells = std::get<0>(cqmp);
4202 auto &qpoints = std::get<1>(cqmp);
4203 auto &maps = std::get<2>(cqmp);
4204 auto &missing_points = std::get<3>(cqmp);
4208 ExcPointNotFound<spacedim>(points[missing_points[0]]));
4210 (void)missing_points;
4212 return std::make_tuple(std::move(cells),
4219 template <
int dim,
int spacedim>
4222 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
4223 std::vector<std::vector<Point<dim>>>,
4224 std::vector<std::vector<unsigned int>>,
4225 std::vector<unsigned int>>
4236 const unsigned int np = points.size();
4238 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>
4240 std::vector<std::vector<Point<dim>>> qpoints_out;
4241 std::vector<std::vector<unsigned int>> maps_out;
4242 std::vector<unsigned int> missing_points_out;
4246 return std::make_tuple(std::move(cells_out),
4247 std::move(qpoints_out),
4248 std::move(maps_out),
4249 std::move(missing_points_out));
4255 std::pair<typename Triangulation<dim, spacedim>::active_cell_iterator,
4260 unsigned int points_checked = 0;
4272 catch (
const GridTools::ExcPointNotFound<dim> &)
4274 missing_points_out.emplace_back(0);
4283 std::pair<BoundingBox<spacedim>,
4288 int cell_candidate_idx = -1;
4292 bool use_try =
false;
4294 while (!found && points_checked < np)
4297 b_tree.query(boost::geometry::index::intersects(points[points_checked]),
4298 std::back_inserter(box_cell));
4301 cell_candidate_idx = -1;
4302 for (
unsigned int i = 0; i < box_cell.size(); ++i)
4305 if (!box_cell[i].
second->is_artificial())
4306 cell_candidate_idx = i;
4310 if (cell_candidate_idx != -1 &&
4311 (!box_cell[i].
second->is_locally_owned() ||
4312 box_cell[i].second->at_boundary()))
4316 if (cell_candidate_idx != -1)
4321 if (cell_candidate_idx != -1)
4329 points[points_checked],
4330 box_cell[cell_candidate_idx].
second);
4333 catch (
const GridTools::ExcPointNotFound<dim> &)
4335 missing_points_out.emplace_back(points_checked);
4342 points[points_checked],
4343 box_cell[cell_candidate_idx].
second);
4352 cache, points[points_checked]);
4357 cell_candidate_idx = box_cell.size();
4359 std::make_pair(my_pair.first->bounding_box(), my_pair.first));
4361 catch (
const GridTools::ExcPointNotFound<dim> &)
4363 missing_points_out.emplace_back(points_checked);
4374 cells_out.emplace_back(my_pair.first);
4375 qpoints_out.emplace_back(1, my_pair.second);
4376 maps_out.emplace_back(1, points_checked - 1);
4380 if (np == qpoints_out.size())
4381 return std::make_tuple(std::move(cells_out),
4382 std::move(qpoints_out),
4383 std::move(maps_out),
4384 std::move(missing_points_out));
4387 for (
unsigned int p = points_checked; p < np; ++p)
4390 if (cell_candidate_idx != -1)
4391 if (!box_cell[cell_candidate_idx].
first.point_inside(points[p]))
4393 cell_candidate_idx = -1;
4396 if (cell_candidate_idx == -1)
4400 b_tree.query(boost::geometry::index::intersects(points[p]),
4401 std::back_inserter(box_cell));
4404 cell_candidate_idx = -1;
4405 for (
unsigned int i = 0; i < box_cell.size(); ++i)
4408 if (!box_cell[i].
second->is_artificial())
4409 cell_candidate_idx = i;
4413 if (cell_candidate_idx != -1 &&
4414 (!box_cell[i].
second->is_locally_owned() ||
4415 box_cell[i].second->at_boundary()))
4419 if (cell_candidate_idx != -1)
4424 if (cell_candidate_idx == -1)
4435 cell_candidate_idx = box_cell.size();
4437 std::make_pair(my_pair.first->bounding_box(), my_pair.first));
4439 catch (
const GridTools::ExcPointNotFound<dim> &)
4441 missing_points_out.emplace_back(p);
4453 cache, points[p], box_cell[cell_candidate_idx].
second);
4455 catch (
const GridTools::ExcPointNotFound<dim> &)
4457 missing_points_out.push_back(p);
4464 cache, points[p], box_cell[cell_candidate_idx].
second);
4469 if (my_pair.first != box_cell[cell_candidate_idx].second)
4471 for (
unsigned int i = 0; i < box_cell.size(); ++i)
4473 if (my_pair.first == box_cell[i].second)
4475 cell_candidate_idx = i;
4480 if (my_pair.first != box_cell[cell_candidate_idx].second)
4484 cell_candidate_idx = box_cell.size();
4486 std::make_pair(my_pair.first->bounding_box(),
4495 if (my_pair.first == cells_out.back())
4498 qpoints_out.back().emplace_back(my_pair.second);
4499 maps_out.back().emplace_back(p);
4504 typename std::vector<typename Triangulation<dim, spacedim>::
4505 active_cell_iterator>::iterator cells_it =
4506 std::find(cells_out.begin(), cells_out.end() - 1, my_pair.first);
4508 if (cells_it == cells_out.end() - 1)
4511 cells_out.emplace_back(my_pair.first);
4512 qpoints_out.emplace_back(1, my_pair.second);
4513 maps_out.emplace_back(1, p);
4519 unsigned int current_cell = cells_it - cells_out.begin();
4520 qpoints_out[current_cell].emplace_back(my_pair.second);
4521 maps_out[current_cell].emplace_back(p);
4527 Assert(cells_out.size() == maps_out.size(),
4530 Assert(cells_out.size() == qpoints_out.size(),
4534 unsigned int c = cells_out.size();
4535 unsigned int qps = 0;
4541 for (
unsigned int n = 0; n < c; ++n)
4543 Assert(qpoints_out[n].size() == maps_out[n].size(),
4545 qps += qpoints_out[n].size();
4548 Assert(qps + missing_points_out.size() == np,
4552 return std::make_tuple(std::move(cells_out),
4553 std::move(qpoints_out),
4554 std::move(maps_out),
4555 std::move(missing_points_out));
4563 namespace distributed_cptloc
4566 template <
int dim,
int spacedim>
4575 return k->active_cell_index();
4583 template <
int dim,
int spacedim>
4586 std::pair<std::vector<Point<dim>>, std::vector<unsigned int>>,
4587 cell_hash<dim, spacedim>>
4593 const unsigned int np = points.size();
4597 std::pair<std::vector<Point<dim>>, std::vector<unsigned int>>,
4603 return cell_qpoint_map;
4608 auto last_cell = cell_qpoint_map.emplace(
4609 std::make_pair(my_pair.first,
4610 std::make_pair(std::vector<
Point<dim>>{my_pair.second},
4611 std::vector<unsigned int>{0})));
4614 return cell_qpoint_map;
4617 double cell_diameter = my_pair.first->diameter() *
4621 for (
unsigned int p = 1; p < np; ++p)
4625 if (cell_center.
distance(points[p]) < cell_diameter)
4627 cache, points[p], last_cell.first->first);
4632 if (last_cell.first->first == my_pair.first)
4634 last_cell.first->second.first.emplace_back(my_pair.second);
4635 last_cell.first->second.second.emplace_back(p);
4640 last_cell = cell_qpoint_map.emplace(std::make_pair(
4642 std::make_pair(std::vector<
Point<dim>>{my_pair.second},
4643 std::vector<unsigned int>{p})));
4645 if (last_cell.second ==
false)
4648 last_cell.first->second.first.emplace_back(my_pair.second);
4649 last_cell.first->second.second.emplace_back(p);
4654 cell_center = my_pair.first->center();
4656 my_pair.first->diameter() *
4663 unsigned int qps = 0;
4668 for (
const auto &m : cell_qpoint_map)
4670 Assert(m.second.second.size() == m.second.first.size(),
4672 m.second.first.size()));
4673 qps += m.second.second.size();
4677 return cell_qpoint_map;
4690 template <
int dim,
int spacedim>
4696 std::vector<unsigned int>,
4698 std::vector<unsigned int>>,
4703 const std::vector<std::vector<
Point<dim>>> & in_qpoints,
4704 const std::vector<std::vector<unsigned int>> & in_maps,
4706 const unsigned int in_rank)
4709 for (
unsigned int c = 0; c < in_cells.size(); ++c)
4712 auto current_c = output_unmap.emplace(
4713 std::make_pair(in_cells[c],
4714 std::make_tuple(in_qpoints[c],
4717 std::vector<unsigned int>(
4718 in_points[c].size(), in_rank))));
4720 if (current_c.second ==
false)
4724 auto &cell_qpts = std::get<0>(current_c.first->second);
4725 auto &cell_maps = std::get<1>(current_c.first->second);
4726 auto &cell_pts = std::get<2>(current_c.first->second);
4727 auto &cell_ranks = std::get<3>(current_c.first->second);
4728 cell_qpts.insert(cell_qpts.end(),
4729 in_qpoints[c].begin(),
4730 in_qpoints[c].end());
4731 cell_maps.insert(cell_maps.end(),
4734 cell_pts.insert(cell_pts.end(),
4735 in_points[c].begin(),
4736 in_points[c].end());
4737 std::vector<unsigned int> ranks_tmp(in_points[c].size(),
4739 cell_ranks.insert(cell_ranks.end(),
4757 template <
int dim,
int spacedim>
4762 const std::vector<unsigned int> & local_points_idx,
4766 std::vector<unsigned int>,
4768 std::vector<unsigned int>>,
4770 std::map<
unsigned int,
4771 std::tuple<std::vector<CellId>,
4773 std::vector<std::vector<unsigned int>>,
4776 std::vector<unsigned int> &classified_pts)
4782 for (
const auto &cell_tuples : cpt_loc_pts)
4784 auto &cell_loc = cell_tuples.first;
4785 auto &q_loc = std::get<0>(cell_tuples.second);
4786 auto &indices_loc = std::get<1>(cell_tuples.second);
4787 if (cell_loc->is_locally_owned())
4790 std::vector<Point<spacedim>> cell_points(indices_loc.size());
4791 std::vector<unsigned int> cell_points_idx(indices_loc.size());
4792 for (
unsigned int i = 0; i < indices_loc.size(); ++i)
4795 cell_points[i] = local_points[indices_loc[i]];
4800 cell_points_idx[i] = local_points_idx[indices_loc[i]];
4801 classified_pts.emplace_back(
4802 local_points_idx[indices_loc[i]]);
4804 output_unmap.emplace(
4805 std::make_pair(cell_loc,
4806 std::make_tuple(q_loc,
4809 std::vector<unsigned int>(
4811 cell_loc->subdomain_id()))));
4813 else if (cell_loc->is_ghost())
4817 std::vector<Point<spacedim>> cell_points(indices_loc.size());
4818 std::vector<unsigned int> cell_points_idx(indices_loc.size());
4819 for (
unsigned int i = 0; i < indices_loc.size(); ++i)
4821 cell_points[i] = local_points[indices_loc[i]];
4822 cell_points_idx[i] = local_points_idx[indices_loc[i]];
4823 classified_pts.emplace_back(
4824 local_points_idx[indices_loc[i]]);
4830 auto &map_tuple_owner = ghost_loc_pts[cell_loc->subdomain_id()];
4832 std::get<0>(map_tuple_owner).emplace_back(cell_loc->id());
4833 std::get<1>(map_tuple_owner).emplace_back(q_loc);
4834 std::get<2>(map_tuple_owner).emplace_back(cell_points_idx);
4835 std::get<3>(map_tuple_owner).emplace_back(cell_points);
4848 template <
int dim,
int spacedim>
4852 const std::map<
unsigned int,
4854 std::vector<unsigned int>>> &map_pts,
4858 std::vector<unsigned int>,
4860 std::vector<unsigned int>>,
4862 const bool check_owned)
4864 bool no_check = !check_owned;
4868 for (
const auto &rank_and_points : map_pts)
4871 const auto &received_process = rank_and_points.first;
4872 const auto &received_points = rank_and_points.second.first;
4873 const auto &received_map = rank_and_points.second.second;
4880 std::vector<std::vector<Point<dim>>> in_qpoints;
4881 std::vector<std::vector<unsigned int>> in_maps;
4882 std::vector<std::vector<Point<spacedim>>> in_points;
4886 rank_and_points.second.first);
4887 for (
const auto &map_c_pt_idx : cpt_loc_pts)
4890 const auto &proc_cell = map_c_pt_idx.first;
4891 const auto &proc_qpoints = map_c_pt_idx.second.first;
4892 const auto &proc_maps = map_c_pt_idx.second.second;
4896 if (no_check || proc_cell->is_locally_owned())
4898 in_cell.emplace_back(proc_cell);
4899 in_qpoints.emplace_back(proc_qpoints);
4901 unsigned int loc_size = proc_qpoints.size();
4902 std::vector<unsigned int> cell_maps(loc_size);
4903 std::vector<Point<spacedim>> cell_points(loc_size);
4904 for (
unsigned int pt = 0; pt < loc_size; ++pt)
4906 cell_maps[pt] = received_map[proc_maps[pt]];
4907 cell_points[pt] = received_points[proc_maps[pt]];
4909 in_maps.emplace_back(cell_maps);
4910 in_points.emplace_back(cell_points);
4929 template <
int dim,
int spacedim>
4932 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
4933 std::vector<std::vector<Point<dim>>>,
4934 std::vector<std::vector<unsigned int>>,
4935 std::vector<std::vector<Point<spacedim>>>,
4936 std::vector<std::vector<unsigned int>>>
4945 #ifndef DEAL_II_WITH_MPI
4948 (void)global_bboxes;
4951 "GridTools::distributed_compute_point_locations() requires MPI."));
4953 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
4954 std::vector<std::vector<Point<dim>>>,
4955 std::vector<std::vector<unsigned int>>,
4956 std::vector<std::vector<Point<spacedim>>>,
4957 std::vector<std::vector<unsigned int>>>
4962 const auto &tria_mpi =
4970 "GridTools::distributed_compute_point_locations() requires a parallel triangulation."));
4971 auto mpi_communicator = tria_mpi->get_communicator();
4974 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
4975 std::vector<std::vector<Point<dim>>>,
4976 std::vector<std::vector<unsigned int>>,
4977 std::vector<std::vector<Point<spacedim>>>,
4978 std::vector<std::vector<unsigned int>>>
4984 std::tuple<std::vector<Point<dim>>,
4985 std::vector<unsigned int>,
4986 std::vector<Point<spacedim>>,
4987 std::vector<unsigned int>>,
4996 std::tuple<std::vector<std::vector<unsigned int>>,
4997 std::map<unsigned int, unsigned int>,
4998 std::map<unsigned int, std::vector<unsigned int>>>
5004 const auto &guess_loc_idx = std::get<0>(guessed_points)[my_rank];
5005 const unsigned int n_local_guess = guess_loc_idx.size();
5007 std::vector<Point<spacedim>> guess_local_pts(n_local_guess);
5008 for (
unsigned int i = 0; i < n_local_guess; ++i)
5009 guess_local_pts[i] = local_points[guess_loc_idx[i]];
5012 std::map<
unsigned int,
5013 std::tuple<std::vector<CellId>,
5014 std::vector<std::vector<Point<dim>>>,
5015 std::vector<std::vector<unsigned int>>,
5016 std::vector<std::vector<Point<spacedim>>>>>
5020 std::vector<unsigned int> classified_pts;
5024 &internal::distributed_cptloc::compute_and_classify_points<dim, spacedim>,
5034 const auto &other_owned_idx = std::get<1>(guessed_points);
5035 std::map<
unsigned int,
5036 std::pair<std::vector<Point<spacedim>>, std::vector<unsigned int>>>
5039 for (
const auto &indices : other_owned_idx)
5040 if (indices.second != my_rank)
5043 auto ¤t_pts = other_owned_pts[indices.second];
5045 current_pts.first.emplace_back(local_points[indices.first]);
5046 current_pts.second.emplace_back(indices.first);
5050 auto owned_rank_pts =
5057 &internal::distributed_cptloc::compute_and_merge_from_map<dim, spacedim>,
5071 std::map<
unsigned int,
5072 std::pair<std::vector<Point<spacedim>>, std::vector<unsigned int>>>
5077 const std::map<unsigned int, std::vector<unsigned int>> &other_check_idx =
5078 std::get<2>(guessed_points);
5085 std::sort(classified_pts.begin(), classified_pts.end());
5087 for (
const auto &pt_to_guesses : other_check_idx)
5089 const auto &point_idx = pt_to_guesses.first;
5090 const auto &probable_owners_rks = pt_to_guesses.second;
5091 if (!std::binary_search(classified_pts.begin(),
5092 classified_pts.end(),
5096 for (
const unsigned int probable_owners_rk : probable_owners_rks)
5097 if (probable_owners_rk != my_rank)
5100 auto ¤t_pts = other_check_pts[probable_owners_rk];
5102 current_pts.first.emplace_back(local_points[point_idx]);
5104 current_pts.second.emplace_back(point_idx);
5112 owned_pts_tsk.
join();
5115 for (
const auto &rank_vals : cpt_ghost)
5118 const auto &cell_ids = std::get<0>(rank_vals.second);
5119 unsigned int n_cells = cell_ids.size();
5120 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>
5122 for (
unsigned int c = 0; c <
n_cells; ++c)
5128 std::get<1>(rank_vals.second),
5129 std::get<2>(rank_vals.second),
5130 std::get<3>(rank_vals.second),
5143 unsigned int size_output = temporary_unmap.size();
5144 auto &out_cells = std::get<0>(output_tuple);
5145 auto &out_qpoints = std::get<1>(output_tuple);
5146 auto &out_maps = std::get<2>(output_tuple);
5147 auto &out_points = std::get<3>(output_tuple);
5148 auto &out_ranks = std::get<4>(output_tuple);
5150 out_cells.resize(size_output);
5151 out_qpoints.resize(size_output);
5152 out_maps.resize(size_output);
5153 out_points.resize(size_output);
5154 out_ranks.resize(size_output);
5157 for (
const auto &rank_and_tuple : temporary_unmap)
5159 out_cells[c] = rank_and_tuple.first;
5160 out_qpoints[c] = std::get<0>(rank_and_tuple.second);
5161 out_maps[c] = std::get<1>(rank_and_tuple.second);
5162 out_points[c] = std::get<2>(rank_and_tuple.second);
5163 out_ranks[c] = std::get<3>(rank_and_tuple.second);
5167 return output_tuple;
5172 template <
int dim,
int spacedim>
5173 std::map<unsigned int, Point<spacedim>>
5177 std::map<unsigned int, Point<spacedim>> result;
5180 if (!cell->is_artificial())
5183 for (
unsigned int i = 0; i < vs.size(); ++i)
5184 result[cell->vertex_index(i)] = vs[i];
5191 template <
int spacedim>
5196 auto id_and_v = std::min_element(
5201 return p1.second.distance(p) < p2.second.distance(p);
5203 return id_and_v->first;
5207 template <
int dim,
int spacedim>
5208 std::pair<typename Triangulation<dim, spacedim>::active_cell_iterator,
5215 const std::vector<bool> &marked_vertices)
5220 const auto &vertex_to_cell_centers =
5228 vertex_to_cell_centers,
5231 used_vertices_rtree);
5234 template <
int spacedim>
5235 std::vector<std::vector<BoundingBox<spacedim>>>
5240 #ifndef DEAL_II_WITH_MPI
5242 (void)mpi_communicator;
5245 "GridTools::exchange_local_bounding_boxes() requires MPI."));
5249 unsigned int n_bboxes = local_bboxes.size();
5251 int n_local_data = 2 * spacedim * n_bboxes;
5253 std::vector<double> loc_data_array(n_local_data);
5254 for (
unsigned int i = 0; i < n_bboxes; ++i)
5255 for (
unsigned int d = 0;
d < spacedim; ++
d)
5258 loc_data_array[2 * i * spacedim +
d] =
5259 local_bboxes[i].get_boundary_points().first[
d];
5260 loc_data_array[2 * i * spacedim + spacedim +
d] =
5261 local_bboxes[i].get_boundary_points().second[
d];
5268 std::vector<int> size_all_data(n_procs);
5271 int ierr = MPI_Allgather(&n_local_data,
5274 size_all_data.data(),
5282 std::vector<int> rdispls(n_procs);
5284 for (
unsigned int i = 1; i < n_procs; ++i)
5285 rdispls[i] = rdispls[i - 1] + size_all_data[i - 1];
5289 std::vector<double> data_array(rdispls.back() + size_all_data.back());
5291 ierr = MPI_Allgatherv(loc_data_array.data(),
5295 size_all_data.data(),
5302 std::vector<std::vector<BoundingBox<spacedim>>> global_bboxes(n_procs);
5303 unsigned int begin_idx = 0;
5304 for (
unsigned int i = 0; i < n_procs; ++i)
5307 unsigned int n_bbox_i = size_all_data[i] / (spacedim * 2);
5308 global_bboxes[i].resize(n_bbox_i);
5309 for (
unsigned int bbox = 0; bbox < n_bbox_i; ++bbox)
5312 for (
unsigned int d = 0;
d < spacedim; ++
d)
5314 p1[
d] = data_array[begin_idx + 2 * bbox * spacedim +
d];
5316 data_array[begin_idx + 2 * bbox * spacedim + spacedim +
d];
5319 global_bboxes[i][bbox] = loc_bbox;
5322 begin_idx += size_all_data[i];
5324 return global_bboxes;
5325 #endif // DEAL_II_WITH_MPI
5330 template <
int spacedim>
5336 #ifndef DEAL_II_WITH_MPI
5337 (void)mpi_communicator;
5339 std::vector<std::pair<BoundingBox<spacedim>,
unsigned int>> boxes_index(
5340 local_description.size());
5342 for (
unsigned int i = 0; i < local_description.size(); ++i)
5343 boxes_index[i] = std::make_pair(local_description[i], 0u);
5347 const std::vector<std::vector<BoundingBox<spacedim>>> global_bboxes =
5351 const unsigned int n_procs =
5355 std::vector<unsigned int> bboxes_position(n_procs);
5357 unsigned int tot_bboxes = 0;
5358 for (
const auto &process_bboxes : global_bboxes)
5359 tot_bboxes += process_bboxes.size();
5362 std::vector<std::pair<BoundingBox<spacedim>,
unsigned int>>
5364 flat_global_bboxes.reserve(tot_bboxes);
5365 unsigned int process_index = 0;
5366 for (
const auto &process_bboxes : global_bboxes)
5369 std::vector<std::pair<BoundingBox<spacedim>,
unsigned int>>
5370 boxes_and_indices(process_bboxes.size());
5373 for (
unsigned int i = 0; i < process_bboxes.size(); ++i)
5374 boxes_and_indices[i] =
5375 std::make_pair(process_bboxes[i], process_index);
5377 flat_global_bboxes.insert(flat_global_bboxes.end(),
5378 boxes_and_indices.begin(),
5379 boxes_and_indices.end());
5387 flat_global_bboxes.begin(), flat_global_bboxes.end());
5388 #endif // DEAL_II_WITH_MPI
5393 template <
int dim,
int spacedim>
5397 std::map<
unsigned int, std::vector<unsigned int>> &coinciding_vertex_groups,
5398 std::map<unsigned int, unsigned int> &vertex_to_coinciding_vertex_group)
5403 static const int lookup_table_2d[2][2] =
5410 static const int lookup_table_3d[2][2][2][4] =
5432 if (pair.first.first->level() != pair.second.first.first->level())
5435 const auto face_a = pair.first.first->face(pair.first.second);
5437 pair.second.first.first->face(pair.second.first.second);
5438 const auto mask = pair.second.second;
5441 for (
unsigned int i = 0; i < GeometryInfo<dim>::vertices_per_face;
5444 const bool face_orientation = mask[0];
5445 const bool face_flip = mask[1];
5446 const bool face_rotation = mask[2];
5456 j = lookup_table_2d[face_flip][i];
5459 j = lookup_table_3d[face_orientation][face_flip]
5467 const auto vertex_a = face_a->vertex_index(i);
5468 const auto vertex_b = face_b->vertex_index(j);
5469 unsigned int temp =
std::min(vertex_a, vertex_b);
5471 auto it_a = vertex_to_coinciding_vertex_group.find(vertex_a);
5472 if (it_a != vertex_to_coinciding_vertex_group.end())
5473 temp =
std::min(temp, it_a->second);
5475 auto it_b = vertex_to_coinciding_vertex_group.find(vertex_b);
5476 if (it_b != vertex_to_coinciding_vertex_group.end())
5477 temp =
std::min(temp, it_b->second);
5479 if (it_a != vertex_to_coinciding_vertex_group.end())
5480 it_a->second = temp;
5482 vertex_to_coinciding_vertex_group[vertex_a] = temp;
5484 if (it_b != vertex_to_coinciding_vertex_group.end())
5485 it_b->second = temp;
5487 vertex_to_coinciding_vertex_group[vertex_b] = temp;
5493 for (
auto &p : vertex_to_coinciding_vertex_group)
5495 if (p.first == p.second)
5497 unsigned int temp = p.second;
5498 while (temp != vertex_to_coinciding_vertex_group[temp])
5499 temp = vertex_to_coinciding_vertex_group[temp];
5505 for (
auto p : vertex_to_coinciding_vertex_group)
5506 coinciding_vertex_groups[p.second] = {};
5508 for (
auto p : vertex_to_coinciding_vertex_group)
5509 coinciding_vertex_groups[p.second].push_back(p.first);
5515 template <
int dim,
int spacedim>
5516 std::map<unsigned int, std::set<::types::subdomain_id>>
5526 std::map<unsigned int, std::vector<unsigned int>> coinciding_vertex_groups;
5527 std::map<unsigned int, unsigned int> vertex_to_coinciding_vertex_group;
5530 coinciding_vertex_groups,
5531 vertex_to_coinciding_vertex_group);
5534 std::vector<bool> vertex_of_own_cell(tria.
n_vertices(),
false);
5536 if (cell->is_locally_owned())
5538 vertex_of_own_cell[cell->vertex_index(v)] =
true;
5542 std::map<unsigned int, std::set<types::subdomain_id>> result;
5546 if (cell->is_ghost())
5554 if (vertex_of_own_cell[cell->vertex_index(v)])
5555 result[cell->vertex_index(v)].insert(owner);
5558 auto coinciding_vertex_group =
5559 vertex_to_coinciding_vertex_group.find(cell->vertex_index(v));
5560 if (coinciding_vertex_group !=
5561 vertex_to_coinciding_vertex_group.end())
5562 for (
auto coinciding_vertex :
5563 coinciding_vertex_groups[coinciding_vertex_group->second])
5564 if (vertex_of_own_cell[coinciding_vertex])
5565 result[coinciding_vertex].insert(owner);
5576 #define SPLIT_INSTANTIATIONS_COUNT 2
5577 #ifndef SPLIT_INSTANTIATIONS_INDEX
5578 # define SPLIT_INSTANTIATIONS_INDEX 0
5580 #include "grid_tools.inst"