17#include <deal.II/base/mpi.templates.h>
63#include <boost/random/mersenne_twister.hpp>
64#include <boost/random/uniform_real_distribution.hpp>
74#include <unordered_map>
81 template <
int dim,
int spacedim>
91#if defined(DEAL_II_WITH_P4EST) && defined(DEBUG)
106 std::vector<bool> boundary_vertices(
vertices.size(),
false);
112 for (; cell != endc; ++cell)
113 for (
const unsigned int face : cell->face_indices())
114 if (cell->face(face)->at_boundary())
115 for (
unsigned int i = 0; i < cell->face(face)->n_vertices(); ++i)
116 boundary_vertices[cell->face(face)->vertex_index(i)] =
true;
120 double max_distance_sqr = 0;
121 std::vector<bool>::const_iterator pi = boundary_vertices.begin();
122 const unsigned int N = boundary_vertices.size();
123 for (
unsigned int i = 0; i < N; ++i, ++pi)
125 std::vector<bool>::const_iterator pj = pi + 1;
126 for (
unsigned int j = i + 1; j < N; ++j, ++pj)
127 if ((*pi ==
true) && (*pj ==
true) &&
137 template <
int dim,
int spacedim>
143 unsigned int mapping_degree = 1;
145 mapping_degree = p->get_degree();
146 else if (
const auto *p =
148 mapping_degree = p->get_degree();
151 const QGauss<dim> quadrature_formula(mapping_degree + 1);
152 const unsigned int n_q_points = quadrature_formula.
size();
167 double local_volume = 0;
170 for (; cell != endc; ++cell)
171 if (cell->is_locally_owned())
174 for (
unsigned int q = 0; q < n_q_points; ++q)
175 local_volume += fe_values.
JxW(q);
178 double global_volume = 0;
180#ifdef DEAL_II_WITH_MPI
188 global_volume = local_volume;
190 return global_volume;
212 struct TransformR2UAffine
227 [1] = {{-1.000000}, {1.000000}};
231 {1.000000, 0.000000};
242 [2] = {{-0.500000, -0.500000},
243 {0.500000, -0.500000},
244 {-0.500000, 0.500000},
245 {0.500000, 0.500000}};
255 {0.750000, 0.250000, 0.250000, -0.250000};
261 {-0.250000, -0.250000, -0.250000},
262 {0.250000, -0.250000, -0.250000},
263 {-0.250000, 0.250000, -0.250000},
264 {0.250000, 0.250000, -0.250000},
265 {-0.250000, -0.250000, 0.250000},
266 {0.250000, -0.250000, 0.250000},
267 {-0.250000, 0.250000, 0.250000},
268 {0.250000, 0.250000, 0.250000}
287 template <
int dim,
int spacedim>
296 for (
unsigned int d = 0; d < spacedim; ++d)
297 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
298 for (
unsigned int e = 0; e < dim; ++e)
299 A[d][e] +=
vertices[v][d] * TransformR2UAffine<dim>::KA[v][e];
303 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
304 b +=
vertices[v] * TransformR2UAffine<dim>::Kb[v];
306 return std::make_pair(A, b);
323 for (
const auto &cell :
triangulation.active_cell_iterators())
325 if (cell->is_locally_owned())
327 double aspect_ratio_cell = 0.0;
332 for (
unsigned int q = 0; q < quadrature.
size(); ++q)
343 aspect_ratio_cell = std::numeric_limits<double>::infinity();
348 for (
unsigned int i = 0; i < dim; ++i)
349 for (
unsigned int j = 0; j < dim; ++j)
350 J(i, j) = jacobian[i][j];
356 double const ar = max_sv / min_sv;
363 aspect_ratio_cell =
std::max(aspect_ratio_cell, ar);
368 aspect_ratio_vector(cell->active_cell_index()) = aspect_ratio_cell;
372 return aspect_ratio_vector;
393 template <
int dim,
int spacedim>
399 const auto predicate = [](
const iterator &) {
return true; };
402 tria, std::function<
bool(
const iterator &)>(predicate));
428 template <
int structdim>
436 if (std::lexicographical_compare(std::begin(a.
vertices),
438 std::begin(b.vertices),
439 std::end(b.vertices)))
445 if (std::equal(std::begin(a.
vertices),
447 std::begin(b.vertices)))
452 "Two CellData objects with equal vertices must "
453 "have the same material/boundary ids and manifold "
478 template <
class FaceIteratorType>
482 CellData<dim - 1> face_cell_data(face->n_vertices());
483 for (
unsigned int vertex_n = 0; vertex_n < face->n_vertices();
485 face_cell_data.vertices[vertex_n] = face->vertex_index(vertex_n);
486 face_cell_data.boundary_id = face->boundary_id();
487 face_cell_data.manifold_id = face->manifold_id();
489 face_data.insert(std::move(face_cell_data));
517 template <
class FaceIteratorType>
532 template <
int dim,
int spacedim>
534 tuple<std::vector<Point<spacedim>>, std::vector<CellData<dim>>,
SubCellData>
538 ExcMessage(
"The input triangulation must be non-empty."));
540 std::vector<Point<spacedim>>
vertices;
541 std::vector<CellData<dim>> cells;
543 unsigned int max_level_0_vertex_n = 0;
545 for (
const unsigned int cell_vertex_n : cell->vertex_indices())
546 max_level_0_vertex_n =
547 std::max(cell->vertex_index(cell_vertex_n), max_level_0_vertex_n);
548 vertices.resize(max_level_0_vertex_n + 1);
558 for (
const unsigned int cell_vertex_n : cell->vertex_indices())
562 vertices[cell->vertex_index(cell_vertex_n)] =
563 cell->vertex(cell_vertex_n);
565 cell->vertex_index(cell_vertex_n);
569 cells.push_back(cell_data);
574 for (
const unsigned int face_n : cell->face_indices())
577 const auto face = cell->face(face_n);
586 for (
unsigned int line_n = 0; line_n < cell->n_lines(); ++line_n)
588 const auto line = cell->line(line_n);
594 for (
unsigned int vertex_n : line->vertex_indices())
596 line->vertex_index(vertex_n);
599 line_data.insert(std::move(line_cell_data));
608 std::vector<bool> used_vertices(
vertices.size());
610 for (
const auto v : cell_data.vertices)
611 used_vertices[v] =
true;
612 Assert(std::find(used_vertices.begin(), used_vertices.end(),
false) ==
614 ExcMessage(
"The level zero vertices should form a contiguous "
622 for (
const CellData<1> &face_line_data : line_data)
625 return std::tuple<std::vector<Point<spacedim>>,
626 std::vector<CellData<dim>>,
629 std::move(subcell_data));
634 template <
int dim,
int spacedim>
643 "Invalid SubCellData supplied according to ::check_consistency(). "
644 "This is caused by data containing objects for the wrong dimension."));
647 std::vector<bool> vertex_used(
vertices.size(),
false);
648 for (
unsigned int c = 0; c < cells.size(); ++c)
649 for (
unsigned int v = 0; v < cells[c].vertices.size(); ++v)
652 ExcMessage(
"Invalid vertex index encountered! cells[" +
656 " is invalid, because only " +
658 " vertices were supplied."));
659 vertex_used[cells[c].vertices[v]] =
true;
666 std::vector<unsigned int> new_vertex_numbers(
vertices.size(),
668 unsigned int next_free_number = 0;
669 for (
unsigned int i = 0; i <
vertices.size(); ++i)
670 if (vertex_used[i] ==
true)
672 new_vertex_numbers[i] = next_free_number;
677 for (
unsigned int c = 0; c < cells.size(); ++c)
679 v = new_vertex_numbers[v];
684 for (
unsigned int v = 0;
689 new_vertex_numbers.size(),
691 "Invalid vertex index in subcelldata.boundary_lines. "
692 "subcelldata.boundary_lines[" +
697 " is invalid, because only " +
699 " vertices were supplied."));
706 for (
unsigned int v = 0;
711 new_vertex_numbers.size(),
713 "Invalid vertex index in subcelldata.boundary_quads. "
714 "subcelldata.boundary_quads[" +
719 " is invalid, because only " +
721 " vertices were supplied."));
729 std::vector<Point<spacedim>> tmp;
730 tmp.reserve(std::count(vertex_used.begin(), vertex_used.end(),
true));
731 for (
unsigned int v = 0; v <
vertices.size(); ++v)
732 if (vertex_used[v] ==
true)
739 template <
int dim,
int spacedim>
744 std::vector<unsigned int> & considered_vertices,
748 std::vector<unsigned int> new_vertex_numbers(
vertices.size());
749 std::iota(new_vertex_numbers.begin(), new_vertex_numbers.end(), 0);
752 if (considered_vertices.size() == 0)
753 considered_vertices = new_vertex_numbers;
768 unsigned int longest_coordinate_direction = 0;
769 double longest_coordinate_length = bbox.
side_length(0);
770 for (
unsigned int d = 1; d < spacedim; ++d)
772 const double coordinate_length = bbox.
side_length(d);
773 if (longest_coordinate_length < coordinate_length)
775 longest_coordinate_length = coordinate_length;
776 longest_coordinate_direction = d;
782 std::vector<std::pair<unsigned int, Point<spacedim>>> sorted_vertices;
783 sorted_vertices.reserve(
vertices.size());
784 for (
const unsigned int vertex_n : considered_vertices)
787 sorted_vertices.emplace_back(vertex_n,
vertices[vertex_n]);
789 std::sort(sorted_vertices.begin(),
790 sorted_vertices.end(),
793 return a.second[longest_coordinate_direction] <
794 b.second[longest_coordinate_direction];
799 for (
unsigned int d = 0; d < spacedim; ++d)
807 auto range_start = sorted_vertices.begin();
808 while (range_start != sorted_vertices.end())
810 auto range_end = range_start + 1;
811 while (range_end != sorted_vertices.end() &&
812 std::abs(range_end->second[longest_coordinate_direction] -
813 range_start->second[longest_coordinate_direction]) <
819 std::sort(range_start,
823 return a.first < b.first;
832 for (
auto reference = range_start; reference != range_end; ++reference)
835 for (
auto it = reference + 1; it != range_end; ++it)
837 if (within_tolerance(reference->second, it->second))
839 new_vertex_numbers[it->first] = reference->first;
845 range_start = range_end;
852 for (
auto &cell : cells)
853 for (
auto &vertex_index : cell.vertices)
854 vertex_index = new_vertex_numbers[vertex_index];
856 for (
auto &vertex_index : quad.vertices)
857 vertex_index = new_vertex_numbers[vertex_index];
859 for (
auto &vertex_index : line.vertices)
860 vertex_index = new_vertex_numbers[vertex_index];
867 template <
int dim,
int spacedim>
878 if (dim == 2 && spacedim == 3)
881 std::size_t n_negative_cells = 0;
882 for (
auto &cell : cells)
887 const unsigned int n_vertices =
vertices.size();
897 std::swap(cell.vertices[1], cell.vertices[2]);
902 std::swap(cell.vertices[0], cell.vertices[2]);
903 std::swap(cell.vertices[1], cell.vertices[3]);
904 std::swap(cell.vertices[4], cell.vertices[6]);
905 std::swap(cell.vertices[5], cell.vertices[7]);
916 std::swap(cell.vertices[n_vertices - 2],
917 cell.vertices[n_vertices - 1]);
930 return n_negative_cells;
934 template <
int dim,
int spacedim>
940 const std::size_t n_negative_cells =
949 AssertThrow(n_negative_cells == 0 || n_negative_cells == cells.size(),
952 "This function assumes that either all cells have positive "
953 "volume, or that all cells have been specified in an "
954 "inverted vertex order so that their volume is negative. "
955 "(In the latter case, this class automatically inverts "
956 "every cell.) However, the mesh you have specified "
957 "appears to have both cells with positive and cells with "
958 "negative volume. You need to check your mesh which "
959 "cells these are and how they got there.\n"
960 "As a hint, of the total ") +
961 std::to_string(cells.size()) +
" cells in the mesh, " +
962 std::to_string(n_negative_cells) +
963 " appear to have a negative volume."));
981 CheapEdge(
const unsigned int v0,
const unsigned int v1)
993 return ((v0 <
e.v0) || ((v0 ==
e.v0) && (v1 <
e.v1)));
1016 std::set<CheapEdge> edges;
1018 for (
typename std::vector<
CellData<dim>>::const_iterator c =
1028 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
1030 const CheapEdge reverse_edge(
1033 if (edges.find(reverse_edge) != edges.end())
1038 const CheapEdge correct_edge(
1041 edges.insert(correct_edge);
1057 struct ParallelEdges
1071 static const unsigned int
1077 const unsigned int ParallelEdges<2>::starter_edges[2] = {0, 2};
1080 const unsigned int ParallelEdges<2>::parallel_edges[4][1] = {{1},
1086 const unsigned int ParallelEdges<3>::starter_edges[3] = {0, 2, 8};
1089 const unsigned int ParallelEdges<3>::parallel_edges[12][3] = {
1122 AdjacentCell(
const unsigned int cell_index,
1123 const unsigned int edge_within_cell)
1136 class AdjacentCells;
1144 class AdjacentCells<2>
1151 using const_iterator =
const AdjacentCell *;
1162 push_back(
const AdjacentCell &adjacent_cell)
1226 class AdjacentCells<3> :
public std::vector<AdjacentCell>
1248 Edge(
const CellData<dim> &cell,
const unsigned int edge_number)
1263 if (vertex_indices[0] > vertex_indices[1])
1264 std::swap(vertex_indices[0], vertex_indices[1]);
1274 return ((vertex_indices[0] <
e.vertex_indices[0]) ||
1275 ((vertex_indices[0] ==
e.vertex_indices[0]) &&
1276 (vertex_indices[1] <
e.vertex_indices[1])));
1285 return ((vertex_indices[0] ==
e.vertex_indices[0]) &&
1286 (vertex_indices[1] ==
e.vertex_indices[1]));
1299 enum OrientationStatus
1329 Cell(
const CellData<dim> &c,
const std::vector<Edge<dim>> &edge_list)
1336 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
1338 const Edge<dim>
e(c,
l);
1340 (std::lower_bound(edge_list.begin(), edge_list.end(),
e) -
1374 class EdgeDeltaSet<2>
1380 using const_iterator =
const unsigned int *;
1406 insert(
const unsigned int edge_index)
1467 class EdgeDeltaSet<3> :
public std::set<unsigned int>
1477 std::vector<Edge<dim>>
1484 std::vector<Edge<dim>> edge_list;
1486 for (
unsigned int i = 0; i < cells.size(); ++i)
1487 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
1488 edge_list.emplace_back(cells[i], l);
1491 std::sort(edge_list.begin(), edge_list.end());
1492 edge_list.erase(std::unique(edge_list.begin(), edge_list.end()),
1505 std::vector<Cell<dim>>
1506 build_cells_and_connect_edges(
const std::vector<
CellData<dim>> &cells,
1507 std::vector<Edge<dim>> & edges)
1509 std::vector<Cell<dim>> cell_list;
1510 cell_list.reserve(cells.size());
1511 for (
unsigned int i = 0; i < cells.size(); ++i)
1515 cell_list.emplace_back(cells[i], edges);
1519 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
1520 edges[cell_list.back().edge_indices[
l]].adjacent_cells.push_back(
1521 AdjacentCell(i, l));
1536 get_next_unoriented_cell(
const std::vector<Cell<dim>> &cells,
1537 const std::vector<Edge<dim>> &edges,
1538 const unsigned int current_cell)
1540 for (
unsigned int c = current_cell; c < cells.size(); ++c)
1541 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
1543 Edge<dim>::not_oriented)
1558 orient_one_set_of_parallel_edges(
const std::vector<Cell<dim>> &cells,
1559 std::vector<Edge<dim>> & edges,
1560 const unsigned int cell,
1561 const unsigned int local_edge)
1588 edges[cells[cell].edge_indices[local_edge]].orientation_status =
1589 (dim == 2 ? Edge<dim>::backward : Edge<dim>::forward);
1605 edges[cells[cell].edge_indices[local_edge]].orientation_status =
1606 (dim == 2 ? Edge<dim>::forward : Edge<dim>::backward);
1615 EdgeDeltaSet<dim> Delta_k;
1616 EdgeDeltaSet<dim> Delta_k_minus_1;
1617 Delta_k_minus_1.insert(cells[cell].
edge_indices[local_edge]);
1619 while (Delta_k_minus_1.begin() !=
1620 Delta_k_minus_1.end())
1624 for (
typename EdgeDeltaSet<dim>::const_iterator delta =
1625 Delta_k_minus_1.begin();
1626 delta != Delta_k_minus_1.end();
1630 Edge<dim>::not_oriented,
1634 for (
typename AdjacentCells<dim>::const_iterator adjacent_cell =
1636 adjacent_cell != edges[*delta].adjacent_cells.end();
1639 const unsigned int K = adjacent_cell->cell_index;
1640 const unsigned int delta_is_edge_in_K =
1641 adjacent_cell->edge_within_cell;
1645 const unsigned int first_edge_vertex =
1646 (edges[*delta].orientation_status == Edge<dim>::forward ?
1647 edges[*delta].vertex_indices[0] :
1648 edges[*delta].vertex_indices[1]);
1649 const unsigned int first_edge_vertex_in_K =
1652 delta_is_edge_in_K, 0)];
1654 first_edge_vertex == first_edge_vertex_in_K ||
1655 first_edge_vertex ==
1657 dim>::line_to_cell_vertices(delta_is_edge_in_K, 1)],
1662 for (
unsigned int o_e = 0;
1663 o_e < ParallelEdges<dim>::n_other_parallel_edges;
1669 const unsigned int opposite_edge =
1670 cells[K].edge_indices[ParallelEdges<
1672 const unsigned int first_opposite_edge_vertex =
1673 cells[K].vertex_indices
1677 (first_edge_vertex == first_edge_vertex_in_K ? 0 :
1684 const typename Edge<dim>::OrientationStatus
1685 opposite_edge_orientation =
1686 (edges[opposite_edge].vertex_indices[0] ==
1687 first_opposite_edge_vertex ?
1688 Edge<dim>::forward :
1689 Edge<dim>::backward);
1694 Edge<dim>::not_oriented)
1698 edges[opposite_edge].orientation_status =
1699 opposite_edge_orientation;
1700 Delta_k.insert(opposite_edge);
1716 opposite_edge_orientation,
1722 opposite_edge_orientation)
1735 Delta_k_minus_1 = Delta_k;
1749 rotate_cell(
const std::vector<Cell<dim>> &cell_list,
1750 const std::vector<Edge<dim>> &edge_list,
1757 for (
unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++
e)
1764 starting_vertex_of_edge[
e] =
1768 starting_vertex_of_edge[
e] =
1784 if ((starting_vertex_of_edge[0] == starting_vertex_of_edge[2]) ||
1785 (starting_vertex_of_edge[0] == starting_vertex_of_edge[3]))
1786 origin_vertex_of_cell = starting_vertex_of_edge[0];
1787 else if ((starting_vertex_of_edge[1] ==
1788 starting_vertex_of_edge[2]) ||
1789 (starting_vertex_of_edge[1] ==
1790 starting_vertex_of_edge[3]))
1791 origin_vertex_of_cell = starting_vertex_of_edge[1];
1803 for (origin_vertex_of_cell = 0;
1804 origin_vertex_of_cell < GeometryInfo<dim>::vertices_per_cell;
1805 ++origin_vertex_of_cell)
1806 if (std::count(starting_vertex_of_edge,
1807 starting_vertex_of_edge +
1812 Assert(origin_vertex_of_cell <
1837 const unsigned int tmp = raw_cells[
cell_index].vertices[0];
1860 static const unsigned int cube_permutations[8][8] = {
1861 {0, 1, 2, 3, 4, 5, 6, 7},
1862 {1, 5, 3, 7, 0, 4, 2, 6},
1863 {2, 6, 0, 4, 3, 7, 1, 5},
1864 {3, 2, 1, 0, 7, 6, 5, 4},
1865 {4, 0, 6, 2, 5, 1, 7, 3},
1866 {5, 4, 7, 6, 1, 0, 3, 2},
1867 {6, 7, 4, 5, 2, 3, 0, 1},
1868 {7, 3, 5, 1, 6, 2, 4, 0}};
1873 temp_vertex_indices[v] =
1875 .vertices[cube_permutations[origin_vertex_of_cell][v]];
1877 raw_cells[
cell_index].vertices[v] = temp_vertex_indices[v];
1901 std::vector<Edge<dim>> edge_list = build_edges(cells);
1902 std::vector<Cell<dim>> cell_list =
1903 build_cells_and_connect_edges(cells, edge_list);
1907 unsigned int next_cell_with_unoriented_edge = 0;
1908 while ((next_cell_with_unoriented_edge = get_next_unoriented_cell(
1909 cell_list, edge_list, next_cell_with_unoriented_edge)) !=
1923 for (
unsigned int l = 0;
l < dim; ++
l)
1924 if (edge_list[cell_list[next_cell_with_unoriented_edge]
1927 orient_one_set_of_parallel_edges(
1930 next_cell_with_unoriented_edge,
1931 ParallelEdges<dim>::starter_edges[l]);
1935 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
1936 Assert(edge_list[cell_list[next_cell_with_unoriented_edge]
1945 for (
unsigned int c = 0; c < cells.size(); ++c)
1946 rotate_cell(cell_list, edge_list, c, cells);
1961 Assert(cells.size() != 0,
1963 "List of elements to orient must have at least one cell"));
1971 if (!is_consistent(cells))
1990 template <
int spacedim>
2014 Physics::Transformations::Rotations::rotation_matrix_3d(axis,
2029 template <
int spacedim>
2048 template <
int dim,
int spacedim>
2070 const unsigned int axis,
2082 template <
int dim,
int spacedim>
2104 const unsigned int n_dofs = S.
n();
2116 const auto constrained_rhs =
2118 solver.
solve(SF, u, constrained_rhs, prec);
2131 const bool solve_for_absolute_positions)
2159 std::array<AffineConstraints<double>, dim> constraints;
2160 typename std::map<unsigned int, Point<dim>>::const_iterator map_end =
2168 for (
const unsigned int vertex_no : cell->vertex_indices())
2170 const unsigned int vertex_index = cell->vertex_index(vertex_no);
2171 const Point<dim> & vertex_point = cell->vertex(vertex_no);
2173 const typename std::map<unsigned int, Point<dim>>::const_iterator
2174 map_iter = new_points.find(vertex_index);
2176 if (map_iter != map_end)
2177 for (
unsigned int i = 0; i < dim; ++i)
2179 constraints[i].add_line(cell->vertex_dof_index(vertex_no, 0));
2180 constraints[i].set_inhomogeneity(
2181 cell->vertex_dof_index(vertex_no, 0),
2182 (solve_for_absolute_positions ?
2183 map_iter->second(i) :
2184 map_iter->second(i) - vertex_point[i]));
2189 for (
unsigned int i = 0; i < dim; ++i)
2190 constraints[i].close();
2194 for (
unsigned int i = 0; i < dim; ++i)
2195 us[i].reinit(dof_handler.
n_dofs());
2199 for (
unsigned int i = 0; i < dim; ++i)
2206 std::vector<bool> vertex_touched(
triangulation.n_vertices(),
false);
2208 for (
const unsigned int vertex_no : cell->vertex_indices())
2209 if (vertex_touched[cell->vertex_index(vertex_no)] ==
false)
2214 cell->vertex_dof_index(vertex_no, 0);
2215 for (
unsigned int i = 0; i < dim; ++i)
2216 if (solve_for_absolute_positions)
2217 v(i) = us[i](dof_index);
2219 v(i) += us[i](dof_index);
2221 vertex_touched[cell->vertex_index(vertex_no)] =
true;
2225 template <
int dim,
int spacedim>
2226 std::map<unsigned int, Point<spacedim>>
2229 std::map<unsigned int, Point<spacedim>> vertex_map;
2233 for (; cell != endc; ++cell)
2235 for (
unsigned int i : cell->face_indices())
2239 if (face->at_boundary())
2241 for (
unsigned j = 0; j < face->n_vertices(); ++j)
2244 const unsigned int vertex_index = face->vertex_index(j);
2245 vertex_map[vertex_index] = vertex;
2257 template <
int dim,
int spacedim>
2261 const bool keep_boundary,
2262 const unsigned int seed)
2279 double almost_infinite_length = 0;
2284 almost_infinite_length += cell->diameter();
2286 std::vector<double> minimal_length(
triangulation.n_vertices(),
2287 almost_infinite_length);
2290 std::vector<bool> at_boundary(keep_boundary ?
triangulation.n_vertices() :
2295 const bool is_parallel_shared =
2298 for (
const auto &cell :
triangulation.active_cell_iterators())
2299 if (is_parallel_shared || cell->is_locally_owned())
2303 for (
unsigned int i = 0; i < cell->n_lines(); ++i)
2306 line = cell->line(i);
2308 if (keep_boundary && line->at_boundary())
2310 at_boundary[line->vertex_index(0)] =
true;
2311 at_boundary[line->vertex_index(1)] =
true;
2314 minimal_length[line->vertex_index(0)] =
2316 minimal_length[line->vertex_index(0)]);
2317 minimal_length[line->vertex_index(1)] =
2319 minimal_length[line->vertex_index(1)]);
2325 for (
unsigned int vertex = 0; vertex < 2; ++vertex)
2326 if (cell->at_boundary(vertex) ==
true)
2327 at_boundary[cell->vertex_index(vertex)] =
true;
2329 minimal_length[cell->vertex_index(0)] =
2331 minimal_length[cell->vertex_index(0)]);
2332 minimal_length[cell->vertex_index(1)] =
2334 minimal_length[cell->vertex_index(1)]);
2339 boost::random::mt19937 rng(seed);
2340 boost::random::uniform_real_distribution<> uniform_distribution(-1, 1);
2344 if (
auto distributed_triangulation =
2348 const std::vector<bool> locally_owned_vertices =
2350 std::vector<bool> vertex_moved(
triangulation.n_vertices(),
false);
2353 for (
const auto &cell :
triangulation.active_cell_iterators())
2354 if (cell->is_locally_owned())
2356 for (
const unsigned int vertex_no : cell->vertex_indices())
2358 const unsigned global_vertex_no =
2359 cell->vertex_index(vertex_no);
2364 if ((keep_boundary && at_boundary[global_vertex_no]) ||
2365 vertex_moved[global_vertex_no] ||
2366 !locally_owned_vertices[global_vertex_no])
2371 for (
unsigned int d = 0; d < spacedim; ++d)
2372 shift_vector(d) = uniform_distribution(rng);
2374 shift_vector *= factor * minimal_length[global_vertex_no] /
2378 cell->vertex(vertex_no) += shift_vector;
2379 vertex_moved[global_vertex_no] =
true;
2383 distributed_triangulation->communicate_locally_moved_vertices(
2384 locally_owned_vertices);
2394 std::vector<Point<spacedim>> new_vertex_locations(n_vertices);
2395 const std::vector<Point<spacedim>> &old_vertex_locations =
2398 for (
unsigned int vertex = 0; vertex < n_vertices; ++vertex)
2402 if (keep_boundary && at_boundary[vertex])
2403 new_vertex_locations[vertex] = old_vertex_locations[vertex];
2408 for (
unsigned int d = 0; d < spacedim; ++d)
2409 shift_vector(d) = uniform_distribution(rng);
2411 shift_vector *= factor * minimal_length[vertex] /
2415 new_vertex_locations[vertex] =
2416 old_vertex_locations[vertex] + shift_vector;
2421 for (
const auto &cell :
triangulation.active_cell_iterators())
2422 for (
const unsigned int vertex_no : cell->vertex_indices())
2423 cell->vertex(vertex_no) =
2424 new_vertex_locations[cell->vertex_index(vertex_no)];
2440 for (; cell != endc; ++cell)
2441 if (!cell->is_artificial())
2442 for (
const unsigned int face : cell->face_indices())
2443 if (cell->face(face)->has_children() &&
2444 !cell->face(face)->at_boundary())
2448 cell->face(face)->child(0)->vertex(1) =
2449 (cell->face(face)->vertex(0) +
2450 cell->face(face)->vertex(1)) /
2454 cell->face(face)->child(0)->vertex(1) =
2455 .5 * (cell->face(face)->vertex(0) +
2456 cell->face(face)->vertex(1));
2457 cell->face(face)->child(0)->vertex(2) =
2458 .5 * (cell->face(face)->vertex(0) +
2459 cell->face(face)->vertex(2));
2460 cell->face(face)->child(1)->vertex(3) =
2461 .5 * (cell->face(face)->vertex(1) +
2462 cell->face(face)->vertex(3));
2463 cell->face(face)->child(2)->vertex(3) =
2464 .5 * (cell->face(face)->vertex(2) +
2465 cell->face(face)->vertex(3));
2468 cell->face(face)->child(0)->vertex(3) =
2469 .25 * (cell->face(face)->vertex(0) +
2470 cell->face(face)->vertex(1) +
2471 cell->face(face)->vertex(2) +
2472 cell->face(face)->vertex(3));
2480 template <
int dim,
template <
int,
int>
class MeshType,
int spacedim>
2484 const std::vector<bool> & marked_vertices)
2493 marked_vertices.size() == 0,
2495 marked_vertices.size()));
2502 marked_vertices.size() == 0 ||
2503 std::equal(marked_vertices.begin(),
2504 marked_vertices.end(),
2506 [](
bool p,
bool q) { return !p || q; }),
2508 "marked_vertices should be a subset of used vertices in the triangulation "
2509 "but marked_vertices contains one or more vertices that are not used vertices!"));
2513 const std::vector<bool> &vertices_to_use = (marked_vertices.size() == 0) ?
2519 std::vector<bool>::const_iterator
first =
2520 std::find(vertices_to_use.begin(), vertices_to_use.end(),
true);
2525 unsigned int best_vertex = std::distance(vertices_to_use.begin(),
first);
2526 double best_dist = (p -
vertices[best_vertex]).norm_square();
2530 for (
unsigned int j = best_vertex + 1; j <
vertices.size(); ++j)
2531 if (vertices_to_use[j])
2533 const double dist = (p -
vertices[j]).norm_square();
2534 if (dist < best_dist)
2546 template <
int dim,
template <
int,
int>
class MeshType,
int spacedim>
2549 const MeshType<dim, spacedim> &mesh,
2551 const std::vector<bool> & marked_vertices)
2564 marked_vertices.size() == 0,
2566 marked_vertices.size()));
2574 marked_vertices.size() == 0 ||
2575 std::equal(marked_vertices.begin(),
2576 marked_vertices.end(),
2578 [](
bool p,
bool q) { return !p || q; }),
2580 "marked_vertices should be a subset of used vertices in the triangulation "
2581 "but marked_vertices contains one or more vertices that are not used vertices!"));
2584 if (marked_vertices.size() != 0)
2587 if (marked_vertices[it->first] ==
false)
2602 template <
int dim,
template <
int,
int>
class MeshType,
int spacedim>
2604 std::vector<typename MeshType<dim, spacedim>::active_cell_iterator>
2607 typename ::internal::
2608 ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>
2611 const unsigned int vertex)
2617 Assert(mesh.get_triangulation().get_used_vertices()[vertex],
2623 std::set<typename ::internal::
2624 ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>
2660 for (
const auto &cell : mesh.active_cell_iterators())
2662 for (
const unsigned int v : cell->vertex_indices())
2663 if (cell->vertex_index(v) == vertex)
2675 for (
const auto face :
2676 cell->reference_cell().faces_for_given_vertex(v))
2677 if (!cell->at_boundary(face) &&
2678 cell->neighbor(face)->is_active())
2700 for (
unsigned int e = 0; e < cell->n_lines(); ++e)
2701 if (cell->line(e)->has_children())
2705 if (cell->line(e)->child(0)->vertex_index(1) == vertex)
2729 typename ::internal::
2730 ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>(
2736 template <
int dim,
int spacedim>
2737 std::vector<std::vector<Tensor<1, spacedim>>>
2745 const unsigned int n_vertices = vertex_to_cells.size();
2750 std::vector<std::vector<Tensor<1, spacedim>>> vertex_to_cell_centers(
2752 for (
unsigned int vertex = 0; vertex < n_vertices; ++vertex)
2755 const unsigned int n_neighbor_cells = vertex_to_cells[vertex].size();
2756 vertex_to_cell_centers[vertex].resize(n_neighbor_cells);
2758 typename std::set<typename Triangulation<dim, spacedim>::
2759 active_cell_iterator>::iterator it =
2760 vertex_to_cells[vertex].begin();
2761 for (
unsigned int cell = 0; cell < n_neighbor_cells; ++cell, ++it)
2763 vertex_to_cell_centers[vertex][cell] =
2764 (*it)->center() -
vertices[vertex];
2765 vertex_to_cell_centers[vertex][cell] /=
2766 vertex_to_cell_centers[vertex][cell].
norm();
2769 return vertex_to_cell_centers;
2775 template <
int spacedim>
2778 const unsigned int a,
2779 const unsigned int b,
2783 const double scalar_product_a = center_directions[a] * point_direction;
2784 const double scalar_product_b = center_directions[b] * point_direction;
2789 return (scalar_product_a > scalar_product_b);
2793 template <
int dim,
template <
int,
int>
class MeshType,
int spacedim>
2795 std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
Point<dim>>
2797 std::pair<typename ::internal::
2798 ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type,
2803 const MeshType<dim, spacedim> &mesh,
2806 std::set<
typename MeshType<dim, spacedim>::active_cell_iterator>>
2809 const typename MeshType<dim, spacedim>::active_cell_iterator &cell_hint,
2810 const std::vector<bool> & marked_vertices,
2812 const double tolerance,
2816 *relevant_cell_bounding_boxes_rtree)
2818 std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
2821 cell_and_position.first = mesh.end();
2825 std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
2827 cell_and_position_approx;
2829 if (relevant_cell_bounding_boxes_rtree !=
nullptr &&
2830 !relevant_cell_bounding_boxes_rtree->empty())
2836 for (
unsigned int d = 0; d < spacedim; ++d)
2838 p1[d] = p1[d] - tolerance;
2839 p2[d] = p2[d] + tolerance;
2844 if (relevant_cell_bounding_boxes_rtree->qbegin(
2845 boost::geometry::index::intersects(bb)) ==
2846 relevant_cell_bounding_boxes_rtree->qend())
2847 return cell_and_position;
2850 bool found_cell =
false;
2851 bool approx_cell =
false;
2853 unsigned int closest_vertex_index = 0;
2855 auto current_cell = cell_hint;
2857 while (found_cell ==
false)
2863 const auto cell_vertices = mapping.
get_vertices(current_cell);
2864 const unsigned int closest_vertex =
2865 find_closest_vertex_of_cell<dim, spacedim>(current_cell,
2868 vertex_to_point = p - cell_vertices[closest_vertex];
2869 closest_vertex_index = current_cell->vertex_index(closest_vertex);
2873 if (!used_vertices_rtree.empty())
2876 using ValueType = std::pair<Point<spacedim>,
unsigned int>;
2877 std::function<
bool(
const ValueType &)> marked;
2878 if (marked_vertices.size() == mesh.n_vertices())
2879 marked = [&marked_vertices](
const ValueType &value) ->
bool {
2880 return marked_vertices[value.second];
2883 marked = [](
const ValueType &) ->
bool {
return true; };
2885 std::vector<std::pair<Point<spacedim>,
unsigned int>> res;
2886 used_vertices_rtree.query(
2887 boost::geometry::index::nearest(p, 1) &&
2888 boost::geometry::index::satisfies(marked),
2889 std::back_inserter(res));
2893 closest_vertex_index = res[0].second;
2898 mapping, mesh, p, marked_vertices);
2900 vertex_to_point = p - mesh.get_vertices()[closest_vertex_index];
2903 const double vertex_point_norm = vertex_to_point.
norm();
2904 if (vertex_point_norm > 0)
2905 vertex_to_point /= vertex_point_norm;
2907 const unsigned int n_neighbor_cells =
2908 vertex_to_cells[closest_vertex_index].size();
2911 std::vector<unsigned int> neighbor_permutation(n_neighbor_cells);
2913 for (
unsigned int i = 0; i < n_neighbor_cells; ++i)
2914 neighbor_permutation[i] = i;
2916 auto comp = [&](
const unsigned int a,
const unsigned int b) ->
bool {
2917 return internal::compare_point_association<spacedim>(
2921 vertex_to_cell_centers[closest_vertex_index]);
2924 std::sort(neighbor_permutation.begin(),
2925 neighbor_permutation.end(),
2930 double best_distance = tolerance;
2934 for (
unsigned int i = 0; i < n_neighbor_cells; ++i)
2938 auto cell = vertex_to_cells[closest_vertex_index].begin();
2939 std::advance(cell, neighbor_permutation[i]);
2941 if (!(*cell)->is_artificial())
2948 cell_and_position.first = *cell;
2949 cell_and_position.second = p_unit;
2951 approx_cell =
false;
2960 if (dist < best_distance)
2962 best_distance = dist;
2963 cell_and_position_approx.first = *cell;
2964 cell_and_position_approx.second = p_unit;
2973 if (found_cell ==
true)
2974 return cell_and_position;
2975 else if (approx_cell ==
true)
2976 return cell_and_position_approx;
2992 mapping, mesh, p, marked_vertices, tolerance);
2994 current_cell =
typename MeshType<dim, spacedim>::active_cell_iterator();
2996 return cell_and_position;
3001 template <
int dim,
int spacedim>
3010 unsigned int closest_vertex = 0;
3012 for (
unsigned int v = 1; v < cell->n_vertices(); ++v)
3015 if (vertex_distance < minimum_distance)
3018 minimum_distance = vertex_distance;
3021 return closest_vertex;
3028 namespace BoundingBoxPredicate
3030 template <
class MeshType>
3031 std::tuple<BoundingBox<MeshType::space_dimension>,
bool>
3033 const typename MeshType::cell_iterator &parent_cell,
3034 const std::function<
3035 bool(
const typename MeshType::active_cell_iterator &)> &predicate)
3037 bool has_predicate =
3039 std::vector<typename MeshType::active_cell_iterator> active_cells;
3040 if (parent_cell->is_active())
3041 active_cells = {parent_cell};
3045 active_cells = get_active_child_cells<MeshType>(parent_cell);
3047 const unsigned int spacedim = MeshType::space_dimension;
3051 while (i < active_cells.size() && !predicate(active_cells[i]))
3055 if (active_cells.size() == 0 || i == active_cells.size())
3058 return std::make_tuple(bbox, has_predicate);
3065 for (; i < active_cells.size(); ++i)
3066 if (predicate(active_cells[i]))
3068 for (
unsigned int d = 0; d < spacedim; ++d)
3070 minp[d] =
std::min(minp[d], active_cells[i]->vertex(v)[d]);
3071 maxp[d] =
std::max(maxp[d], active_cells[i]->vertex(v)[d]);
3074 has_predicate =
true;
3076 return std::make_tuple(bbox, has_predicate);
3083 template <
class MeshType>
3084 std::vector<BoundingBox<MeshType::space_dimension>>
3086 const MeshType &mesh,
3087 const std::function<
bool(
const typename MeshType::active_cell_iterator &)>
3089 const unsigned int refinement_level,
3090 const bool allow_merge,
3091 const unsigned int max_boxes)
3098 refinement_level <= mesh.n_levels(),
3100 "Error: refinement level is higher then total levels in the triangulation!"));
3102 const unsigned int spacedim = MeshType::space_dimension;
3103 std::vector<BoundingBox<spacedim>> bounding_boxes;
3107 for (
unsigned int i = 0; i < refinement_level; ++i)
3108 for (
const typename MeshType::cell_iterator &cell :
3109 mesh.active_cell_iterators_on_level(i))
3111 bool has_predicate =
false;
3113 std::tie(bbox, has_predicate) =
3115 MeshType>(cell, predicate);
3117 bounding_boxes.push_back(bbox);
3121 for (
const typename MeshType::cell_iterator &cell :
3122 mesh.cell_iterators_on_level(refinement_level))
3124 bool has_predicate =
false;
3126 std::tie(bbox, has_predicate) =
3128 MeshType>(cell, predicate);
3130 bounding_boxes.push_back(bbox);
3135 return bounding_boxes;
3141 std::vector<unsigned int> merged_boxes_idx;
3142 bool found_neighbors =
true;
3147 while (found_neighbors)
3149 found_neighbors =
false;
3150 for (
unsigned int i = 0; i < bounding_boxes.size() - 1; ++i)
3152 if (std::find(merged_boxes_idx.begin(),
3153 merged_boxes_idx.end(),
3154 i) == merged_boxes_idx.end())
3155 for (
unsigned int j = i + 1; j < bounding_boxes.size(); ++j)
3156 if (std::find(merged_boxes_idx.begin(),
3157 merged_boxes_idx.end(),
3158 j) == merged_boxes_idx.end() &&
3159 bounding_boxes[i].get_neighbor_type(
3160 bounding_boxes[j]) ==
3161 NeighborType::mergeable_neighbors)
3163 bounding_boxes[i].merge_with(bounding_boxes[j]);
3164 merged_boxes_idx.push_back(j);
3165 found_neighbors =
true;
3171 std::vector<BoundingBox<spacedim>> merged_b_boxes;
3172 for (
unsigned int i = 0; i < bounding_boxes.size(); ++i)
3173 if (std::find(merged_boxes_idx.begin(), merged_boxes_idx.end(), i) ==
3174 merged_boxes_idx.end())
3175 merged_b_boxes.push_back(bounding_boxes[i]);
3180 if ((merged_b_boxes.size() > max_boxes) && (spacedim > 1))
3182 std::vector<double> volumes;
3183 for (
unsigned int i = 0; i < merged_b_boxes.size(); ++i)
3184 volumes.push_back(merged_b_boxes[i].volume());
3186 while (merged_b_boxes.size() > max_boxes)
3188 unsigned int min_idx =
3189 std::min_element(volumes.begin(), volumes.end()) -
3191 volumes.erase(volumes.begin() + min_idx);
3193 bool not_removed =
true;
3194 for (
unsigned int i = 0;
3195 i < merged_b_boxes.size() && not_removed;
3200 if (i != min_idx && (merged_b_boxes[i].get_neighbor_type(
3201 merged_b_boxes[min_idx]) ==
3202 NeighborType::attached_neighbors ||
3203 merged_b_boxes[i].get_neighbor_type(
3204 merged_b_boxes[min_idx]) ==
3205 NeighborType::mergeable_neighbors))
3207 merged_b_boxes[i].merge_with(merged_b_boxes[min_idx]);
3208 merged_b_boxes.erase(merged_b_boxes.begin() + min_idx);
3209 not_removed =
false;
3212 ExcMessage(
"Error: couldn't merge bounding boxes!"));
3215 Assert(merged_b_boxes.size() <= max_boxes,
3217 "Error: couldn't reach target number of bounding boxes!"));
3218 return merged_b_boxes;
3224 template <
int spacedim>
3226 std::tuple<std::vector<std::vector<unsigned int>>,
3227 std::map<unsigned int, unsigned int>,
3228 std::map<unsigned int, std::vector<unsigned int>>>
3236 unsigned int n_procs = global_bboxes.size();
3237 std::vector<std::vector<unsigned int>> point_owners(n_procs);
3238 std::map<unsigned int, unsigned int> map_owners_found;
3239 std::map<unsigned int, std::vector<unsigned int>> map_owners_guessed;
3241 unsigned int n_points = points.size();
3242 for (
unsigned int pt = 0; pt < n_points; ++pt)
3245 std::vector<unsigned int> owners_found;
3247 for (
unsigned int rk = 0; rk < n_procs; ++rk)
3250 if (bbox.point_inside(points[pt]))
3252 point_owners[rk].emplace_back(pt);
3253 owners_found.emplace_back(rk);
3257 Assert(owners_found.size() > 0,
3258 ExcMessage(
"No owners found for the point " +
3259 std::to_string(pt)));
3260 if (owners_found.size() == 1)
3261 map_owners_found[pt] = owners_found[0];
3264 map_owners_guessed[pt] = owners_found;
3267 return std::make_tuple(std::move(point_owners),
3268 std::move(map_owners_found),
3269 std::move(map_owners_guessed));
3272 template <
int spacedim>
3274 std::tuple<std::map<unsigned int, std::vector<unsigned int>>,
3275 std::map<unsigned int, unsigned int>,
3276 std::map<unsigned int, std::vector<unsigned int>>>
3284 std::map<unsigned int, std::vector<unsigned int>> point_owners;
3285 std::map<unsigned int, unsigned int> map_owners_found;
3286 std::map<unsigned int, std::vector<unsigned int>> map_owners_guessed;
3287 std::vector<std::pair<BoundingBox<spacedim>,
unsigned int>> search_result;
3289 unsigned int n_points = points.size();
3290 for (
unsigned int pt_n = 0; pt_n < n_points; ++pt_n)
3292 search_result.clear();
3295 covering_rtree.query(boost::geometry::index::intersects(points[pt_n]),
3296 std::back_inserter(search_result));
3299 std::set<unsigned int> owners_found;
3301 for (
const auto &rank_bbox : search_result)
3305 const bool pt_inserted = owners_found.insert(pt_n).second;
3307 point_owners[rank_bbox.second].emplace_back(pt_n);
3309 Assert(owners_found.size() > 0,
3310 ExcMessage(
"No owners found for the point " +
3311 std::to_string(pt_n)));
3312 if (owners_found.size() == 1)
3313 map_owners_found[pt_n] = *owners_found.begin();
3316 std::copy(owners_found.begin(),
3318 std::back_inserter(map_owners_guessed[pt_n]));
3321 return std::make_tuple(std::move(point_owners),
3322 std::move(map_owners_found),
3323 std::move(map_owners_guessed));
3327 template <
int dim,
int spacedim>
3329 std::set<typename Triangulation<dim, spacedim>::active_cell_iterator>>
3333 std::set<typename Triangulation<dim, spacedim>::active_cell_iterator>>
3338 for (; cell != endc; ++cell)
3339 for (
const unsigned int i : cell->vertex_indices())
3344 for (; cell != endc; ++cell)
3346 for (
unsigned int i : cell->face_indices())
3348 if ((cell->at_boundary(i) ==
false) &&
3349 (cell->neighbor(i)->is_active()))
3352 adjacent_cell = cell->neighbor(i);
3353 for (
unsigned int j = 0; j < cell->face(i)->n_vertices(); ++j)
3362 for (
unsigned int i = 0; i < cell->n_lines(); ++i)
3363 if (cell->line(i)->has_children())
3377 template <
int dim,
int spacedim>
3378 std::map<unsigned int, types::global_vertex_index>
3382 std::map<unsigned int, types::global_vertex_index>
3383 local_to_global_vertex_index;
3385#ifndef DEAL_II_WITH_MPI
3392 ExcMessage(
"This function does not make any sense "
3393 "for parallel::distributed::Triangulation "
3394 "objects if you do not have MPI enabled."));
3398 using active_cell_iterator =
3400 const std::vector<std::set<active_cell_iterator>> vertex_to_cell =
3405 unsigned int max_cellid_size = 0;
3406 std::set<std::pair<types::subdomain_id, types::global_vertex_index>>
3408 std::map<types::subdomain_id, std::set<unsigned int>> vertices_to_recv;
3416 std::set<active_cell_iterator> missing_vert_cells;
3417 std::set<unsigned int> used_vertex_index;
3418 for (; cell != endc; ++cell)
3420 if (cell->is_locally_owned())
3422 for (
const unsigned int i : cell->vertex_indices())
3425 typename std::set<active_cell_iterator>::iterator
3426 adjacent_cell = vertex_to_cell[cell->vertex_index(i)].begin(),
3427 end_adj_cell = vertex_to_cell[cell->vertex_index(i)].end();
3428 for (; adjacent_cell != end_adj_cell; ++adjacent_cell)
3429 lowest_subdomain_id =
3431 (*adjacent_cell)->subdomain_id());
3434 if (lowest_subdomain_id == cell->subdomain_id())
3438 if (used_vertex_index.find(cell->vertex_index(i)) ==
3439 used_vertex_index.end())
3442 local_to_global_vertex_index[cell->vertex_index(i)] =
3448 vertex_to_cell[cell->vertex_index(i)].begin();
3449 for (; adjacent_cell != end_adj_cell; ++adjacent_cell)
3450 if ((*adjacent_cell)->subdomain_id() !=
3451 cell->subdomain_id())
3455 tmp((*adjacent_cell)->subdomain_id(),
3456 cell->vertex_index(i));
3457 if (vertices_added.find(tmp) ==
3458 vertices_added.end())
3460 vertices_to_send[(*adjacent_cell)
3463 cell->vertex_index(i),
3464 cell->id().to_string());
3465 if (cell->id().to_string().size() >
3468 cell->id().to_string().size();
3469 vertices_added.insert(tmp);
3472 used_vertex_index.insert(cell->vertex_index(i));
3479 vertices_to_recv[lowest_subdomain_id].insert(
3480 cell->vertex_index(i));
3481 missing_vert_cells.insert(cell);
3488 if (cell->is_ghost())
3490 for (
unsigned int i : cell->face_indices())
3492 if (cell->at_boundary(i) ==
false)
3494 if (cell->neighbor(i)->is_active())
3497 spacedim>::active_cell_iterator
3498 adjacent_cell = cell->neighbor(i);
3499 if ((adjacent_cell->is_locally_owned()))
3502 adjacent_cell->subdomain_id();
3503 if (cell->subdomain_id() < adj_subdomain_id)
3504 for (
unsigned int j = 0;
3505 j < cell->face(i)->n_vertices();
3508 vertices_to_recv[cell->subdomain_id()].insert(
3509 cell->face(i)->vertex_index(j));
3510 missing_vert_cells.insert(cell);
3526 int ierr = MPI_Exscan(&next_index,
3534 std::map<unsigned int, types::global_vertex_index>::iterator
3535 global_index_it = local_to_global_vertex_index.begin(),
3536 global_index_end = local_to_global_vertex_index.end();
3537 for (; global_index_it != global_index_end; ++global_index_it)
3538 global_index_it->second +=
shift;
3542 grid_tools_compute_local_to_global_vertex_index_map;
3544 grid_tools_compute_local_to_global_vertex_index_map2;
3552 std::vector<std::vector<types::global_vertex_index>> vertices_send_buffers(
3553 vertices_to_send.size());
3554 std::vector<MPI_Request> first_requests(vertices_to_send.size());
3558 std::string>>>::iterator
3559 vert_to_send_it = vertices_to_send.begin(),
3560 vert_to_send_end = vertices_to_send.end();
3561 for (
unsigned int i = 0; vert_to_send_it != vert_to_send_end;
3562 ++vert_to_send_it, ++i)
3564 int destination = vert_to_send_it->first;
3565 const unsigned int n_vertices = vert_to_send_it->second.size();
3566 const int buffer_size = 2 * n_vertices;
3567 vertices_send_buffers[i].resize(buffer_size);
3570 for (
unsigned int j = 0; j < n_vertices; ++j)
3572 vertices_send_buffers[i][2 * j] =
3573 std::get<0>(vert_to_send_it->second[j]);
3574 vertices_send_buffers[i][2 * j + 1] =
3575 local_to_global_vertex_index[std::get<1>(
3576 vert_to_send_it->second[j])];
3580 ierr = MPI_Isend(vertices_send_buffers[i].data(),
3586 &first_requests[i]);
3591 std::vector<std::vector<types::global_vertex_index>> vertices_recv_buffers(
3592 vertices_to_recv.size());
3593 typename std::map<types::subdomain_id, std::set<unsigned int>>::iterator
3594 vert_to_recv_it = vertices_to_recv.begin(),
3595 vert_to_recv_end = vertices_to_recv.end();
3596 for (
unsigned int i = 0; vert_to_recv_it != vert_to_recv_end;
3597 ++vert_to_recv_it, ++i)
3599 int source = vert_to_recv_it->first;
3600 const unsigned int n_vertices = vert_to_recv_it->second.size();
3601 const int buffer_size = 2 * n_vertices;
3602 vertices_recv_buffers[i].resize(buffer_size);
3605 ierr = MPI_Recv(vertices_recv_buffers[i].data(),
3617 std::vector<std::vector<char>> cellids_send_buffers(
3618 vertices_to_send.size());
3619 std::vector<MPI_Request> second_requests(vertices_to_send.size());
3620 vert_to_send_it = vertices_to_send.begin();
3621 for (
unsigned int i = 0; vert_to_send_it != vert_to_send_end;
3622 ++vert_to_send_it, ++i)
3624 int destination = vert_to_send_it->first;
3625 const unsigned int n_vertices = vert_to_send_it->second.size();
3626 const int buffer_size = max_cellid_size * n_vertices;
3627 cellids_send_buffers[i].resize(buffer_size);
3630 unsigned int pos = 0;
3631 for (
unsigned int j = 0; j < n_vertices; ++j)
3633 std::string cell_id = std::get<2>(vert_to_send_it->second[j]);
3634 for (
unsigned int k = 0; k < max_cellid_size; ++k, ++pos)
3636 if (k < cell_id.size())
3637 cellids_send_buffers[i][pos] = cell_id[k];
3641 cellids_send_buffers[i][pos] =
'-';
3646 ierr = MPI_Isend(cellids_send_buffers[i].data(),
3652 &second_requests[i]);
3657 std::vector<std::vector<char>> cellids_recv_buffers(
3658 vertices_to_recv.size());
3659 vert_to_recv_it = vertices_to_recv.begin();
3660 for (
unsigned int i = 0; vert_to_recv_it != vert_to_recv_end;
3661 ++vert_to_recv_it, ++i)
3663 int source = vert_to_recv_it->first;
3664 const unsigned int n_vertices = vert_to_recv_it->second.size();
3665 const int buffer_size = max_cellid_size * n_vertices;
3666 cellids_recv_buffers[i].resize(buffer_size);
3669 ierr = MPI_Recv(cellids_recv_buffers[i].data(),
3681 vert_to_recv_it = vertices_to_recv.begin();
3682 for (
unsigned int i = 0; vert_to_recv_it != vert_to_recv_end;
3683 ++i, ++vert_to_recv_it)
3685 for (
unsigned int j = 0; j < vert_to_recv_it->second.size(); ++j)
3687 const unsigned int local_pos_recv = vertices_recv_buffers[i][2 * j];
3689 vertices_recv_buffers[i][2 * j + 1];
3690 const std::string cellid_recv(
3691 &cellids_recv_buffers[i][max_cellid_size * j],
3692 &cellids_recv_buffers[i][max_cellid_size * j] + max_cellid_size);
3694 typename std::set<active_cell_iterator>::iterator
3695 cell_set_it = missing_vert_cells.begin(),
3696 end_cell_set = missing_vert_cells.end();
3697 for (; (found ==
false) && (cell_set_it != end_cell_set);
3700 typename std::set<active_cell_iterator>::iterator
3702 vertex_to_cell[(*cell_set_it)->vertex_index(i)].begin(),
3704 vertex_to_cell[(*cell_set_it)->vertex_index(i)].end();
3705 for (; candidate_cell != end_cell; ++candidate_cell)
3707 std::string current_cellid =
3708 (*candidate_cell)->id().to_string();
3709 current_cellid.resize(max_cellid_size,
'-');
3710 if (current_cellid.compare(cellid_recv) == 0)
3712 local_to_global_vertex_index
3713 [(*candidate_cell)->vertex_index(local_pos_recv)] =
3725 return local_to_global_vertex_index;
3730 template <
int dim,
int spacedim>
3746 for (
const auto &cell :
triangulation.active_cell_iterators())
3748 const unsigned int index = cell->active_cell_index();
3749 cell_connectivity.
add(index, index);
3750 for (
auto f : cell->face_indices())
3751 if ((cell->at_boundary(f) ==
false) &&
3752 (cell->neighbor(f)->has_children() ==
false))
3754 const unsigned int other_index =
3755 cell->neighbor(f)->active_cell_index();
3756 cell_connectivity.
add(index, other_index);
3757 cell_connectivity.
add(other_index, index);
3764 template <
int dim,
int spacedim>
3770 std::vector<std::vector<unsigned int>> vertex_to_cell(
3772 for (
const auto &cell :
triangulation.active_cell_iterators())
3774 for (
const unsigned int v : cell->vertex_indices())
3775 vertex_to_cell[cell->vertex_index(v)].push_back(
3776 cell->active_cell_index());
3781 for (
const auto &cell :
triangulation.active_cell_iterators())
3783 for (
const unsigned int v : cell->vertex_indices())
3784 for (
unsigned int n = 0;
3785 n < vertex_to_cell[cell->vertex_index(v)].size();
3787 cell_connectivity.
add(cell->active_cell_index(),
3788 vertex_to_cell[cell->vertex_index(v)][n]);
3793 template <
int dim,
int spacedim>
3797 const unsigned int level,
3800 std::vector<std::vector<unsigned int>> vertex_to_cell(
3807 for (
const unsigned int v : cell->vertex_indices())
3808 vertex_to_cell[cell->vertex_index(v)].push_back(cell->index());
3818 for (
const unsigned int v : cell->vertex_indices())
3819 for (
unsigned int n = 0;
3820 n < vertex_to_cell[cell->vertex_index(v)].size();
3822 cell_connectivity.
add(cell->index(),
3823 vertex_to_cell[cell->vertex_index(v)][n]);
3829 template <
int dim,
int spacedim>
3837 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
3838 "are already partitioned implicitly and can not be "
3839 "partitioned again explicitly."));
3841 std::vector<unsigned int> cell_weights;
3851 for (
const auto &cell :
triangulation.active_cell_iterators())
3852 if (cell->is_locally_owned())
3853 cell_weights[cell->active_cell_index()] =
3863 if (
const auto shared_tria =
3867 shared_tria->get_communicator(),
3871 Assert(std::accumulate(cell_weights.begin(),
3873 std::uint64_t(0)) > 0,
3874 ExcMessage(
"The global sum of weights over all active cells "
3875 "is zero. Please verify how you generate weights."));
3887 template <
int dim,
int spacedim>
3890 const std::vector<unsigned int> &cell_weights,
3896 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
3897 "are already partitioned implicitly and can not be "
3898 "partitioned again explicitly."));
3902 if (n_partitions == 1)
3904 for (
const auto &cell :
triangulation.active_cell_iterators())
3905 cell->set_subdomain_id(0);
3919 sp_cell_connectivity.
copy_from(cell_connectivity);
3922 sp_cell_connectivity,
3929 template <
int dim,
int spacedim>
3938 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
3939 "are already partitioned implicitly and can not be "
3940 "partitioned again explicitly."));
3942 std::vector<unsigned int> cell_weights;
3952 for (
const auto &cell :
triangulation.active_cell_iterators() |
3954 cell_weights[cell->active_cell_index()] =
3964 if (
const auto shared_tria =
3968 shared_tria->get_communicator(),
3972 Assert(std::accumulate(cell_weights.begin(),
3974 std::uint64_t(0)) > 0,
3975 ExcMessage(
"The global sum of weights over all active cells "
3976 "is zero. Please verify how you generate weights."));
3982 cell_connection_graph,
3989 template <
int dim,
int spacedim>
3992 const std::vector<unsigned int> &cell_weights,
3999 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
4000 "are already partitioned implicitly and can not be "
4001 "partitioned again explicitly."));
4004 ExcMessage(
"Connectivity graph has wrong size"));
4006 ExcMessage(
"Connectivity graph has wrong size"));
4012 if (n_partitions == 1)
4014 for (
const auto &cell :
triangulation.active_cell_iterators())
4015 cell->set_subdomain_id(0);
4023 std::vector<unsigned int> partition_indices(
triangulation.n_active_cells());
4031 for (
const auto &cell :
triangulation.active_cell_iterators())
4032 cell->set_subdomain_id(partition_indices[cell->active_cell_index()]);
4044 unsigned int & current_proc_idx,
4045 unsigned int & current_cell_idx,
4046 const unsigned int n_active_cells,
4047 const unsigned int n_partitions)
4049 if (cell->is_active())
4051 while (current_cell_idx >=
4052 std::floor(
static_cast<uint_least64_t
>(n_active_cells) *
4053 (current_proc_idx + 1) / n_partitions))
4055 cell->set_subdomain_id(current_proc_idx);
4060 for (
unsigned int n = 0; n < cell->n_children(); ++n)
4070 template <
int dim,
int spacedim>
4074 const bool group_siblings)
4078 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
4079 "are already partitioned implicitly and can not be "
4080 "partitioned again explicitly."));
4088 if (n_partitions == 1)
4090 for (
const auto &cell :
triangulation.active_cell_iterators())
4091 cell->set_subdomain_id(0);
4097 std::vector<types::global_dof_index> coarse_cell_to_p4est_tree_permutation;
4098 std::vector<types::global_dof_index> p4est_tree_to_coarse_cell_permutation;
4104 coarse_cell_to_p4est_tree_permutation.resize(
triangulation.n_cells(0));
4106 coarse_cell_to_p4est_tree_permutation);
4108 p4est_tree_to_coarse_cell_permutation =
4111 unsigned int current_proc_idx = 0;
4112 unsigned int current_cell_idx = 0;
4113 const unsigned int n_active_cells =
triangulation.n_active_cells();
4117 for (
unsigned int idx = 0; idx <
triangulation.n_cells(0); ++idx)
4119 const unsigned int coarse_cell_idx =
4120 p4est_tree_to_coarse_cell_permutation[idx];
4143 for (; cell != endc; ++cell)
4145 if (cell->is_active())
4147 bool all_children_active =
true;
4148 std::map<unsigned int, unsigned int> map_cpu_n_cells;
4149 for (
unsigned int n = 0; n < cell->n_children(); ++n)
4150 if (!cell->child(n)->is_active())
4152 all_children_active =
false;
4156 ++map_cpu_n_cells[cell->child(n)->subdomain_id()];
4158 if (!all_children_active)
4161 unsigned int new_owner = cell->child(0)->subdomain_id();
4162 for (std::map<unsigned int, unsigned int>::iterator it =
4163 map_cpu_n_cells.begin();
4164 it != map_cpu_n_cells.end();
4166 if (it->second > map_cpu_n_cells[new_owner])
4167 new_owner = it->first;
4169 for (
unsigned int n = 0; n < cell->n_children(); ++n)
4170 cell->child(n)->set_subdomain_id(new_owner);
4176 template <
int dim,
int spacedim>
4181 for (
int lvl = n_levels - 1; lvl >= 0; --lvl)
4183 for (
const auto &cell :
triangulation.cell_iterators_on_level(lvl))
4185 if (cell->is_active())
4186 cell->set_level_subdomain_id(cell->subdomain_id());
4189 Assert(cell->child(0)->level_subdomain_id() !=
4192 cell->set_level_subdomain_id(
4193 cell->child(0)->level_subdomain_id());
4205 template <
int dim,
int spacedim>
4210 const std::vector<CellId> & cell_ids,
4211 std::vector<types::subdomain_id> &subdomain_ids)
4213#ifndef DEAL_II_WITH_P4EST
4216 (void)subdomain_ids;
4220 "You are attempting to use a functionality that is only available "
4221 "if deal.II was configured to use p4est, but cmake did not find a "
4222 "valid p4est library."));
4227 for (
const auto &cell_id : cell_ids)
4230 typename ::internal::p4est::types<dim>::quadrant p4est_cell,
4233 ::internal::p4est::init_coarse_quadrant<dim>(p4est_cell);
4234 for (
const auto &child_index : cell_id.get_child_indices())
4236 ::internal::p4est::init_quadrant_children<dim>(
4237 p4est_cell, p4est_children);
4239 p4est_children[
static_cast<unsigned int>(child_index)];
4245 const_cast<typename ::internal::p4est::types<dim>::forest
4247 cell_id.get_coarse_cell_id(),
4254 subdomain_ids.push_back(owner);
4261 template <
int spacedim>
4265 const std::vector<CellId> &,
4266 std::vector<types::subdomain_id> &)
4275 template <
int dim,
int spacedim>
4276 std::vector<types::subdomain_id>
4278 const std::vector<CellId> & cell_ids)
4280 std::vector<types::subdomain_id> subdomain_ids;
4281 subdomain_ids.reserve(cell_ids.size());
4290 *parallel_tria =
dynamic_cast<
4294 internal::get_subdomain_association(*parallel_tria,
4304 const std::vector<types::subdomain_id> &true_subdomain_ids_of_cells =
4305 shared_tria->get_true_subdomain_ids_of_cells();
4307 for (
const auto &cell_id : cell_ids)
4309 const unsigned int active_cell_index =
4310 shared_tria->create_cell_iterator(cell_id)->active_cell_index();
4311 subdomain_ids.push_back(
4312 true_subdomain_ids_of_cells[active_cell_index]);
4319 for (
const auto &cell_id : cell_ids)
4321 subdomain_ids.push_back(
4322 triangulation.create_cell_iterator(cell_id)->subdomain_id());
4326 return subdomain_ids;
4331 template <
int dim,
int spacedim>
4334 std::vector<types::subdomain_id> & subdomain)
4339 for (
const auto &cell :
triangulation.active_cell_iterators())
4340 subdomain[cell->active_cell_index()] = cell->subdomain_id();
4345 template <
int dim,
int spacedim>
4351 unsigned int count = 0;
4352 for (
const auto &cell :
triangulation.active_cell_iterators())
4353 if (cell->subdomain_id() == subdomain)
4361 template <
int dim,
int spacedim>
4366 std::vector<bool> locally_owned_vertices =
4373 if (
const auto *tr =
dynamic_cast<
4376 for (
const auto &cell :
triangulation.active_cell_iterators())
4377 if (cell->is_artificial() ||
4378 (cell->is_ghost() &&
4379 (cell->subdomain_id() < tr->locally_owned_subdomain())))
4380 for (
const unsigned int v : cell->vertex_indices())
4381 locally_owned_vertices[cell->vertex_index(v)] =
false;
4383 return locally_owned_vertices;
4388 template <
int dim,
int spacedim>
4393 double min_diameter = std::numeric_limits<double>::max();
4394 for (
const auto &cell :
triangulation.active_cell_iterators())
4395 if (!cell->is_artificial())
4396 min_diameter =
std::min(min_diameter, cell->diameter(mapping));
4398 double global_min_diameter = 0;
4400#ifdef DEAL_II_WITH_MPI
4404 global_min_diameter =
4408 global_min_diameter = min_diameter;
4410 return global_min_diameter;
4415 template <
int dim,
int spacedim>
4420 double max_diameter = 0.;
4421 for (
const auto &cell :
triangulation.active_cell_iterators())
4422 if (!cell->is_artificial())
4423 max_diameter =
std::max(max_diameter, cell->diameter(mapping));
4425 double global_max_diameter = 0;
4427#ifdef DEAL_II_WITH_MPI
4431 global_max_diameter =
4435 global_max_diameter = max_diameter;
4437 return global_max_diameter;
4444 namespace FixUpDistortedChildCells
4467 template <
typename Iterator,
int spacedim>
4472 const unsigned int structdim =
4473 Iterator::AccessorType::structure_dimension;
4474 Assert(spacedim == Iterator::AccessorType::dimension,
4480 Assert(object->refinement_case() ==
4488 Tensor<spacedim - structdim, spacedim>
4491 for (
const unsigned int i : object->vertex_indices())
4492 parent_vertices[i] =
object->vertex(i);
4495 parent_vertices, parent_alternating_forms);
4497 const Tensor<spacedim - structdim, spacedim>
4498 average_parent_alternating_form =
4499 std::accumulate(parent_alternating_forms,
4500 parent_alternating_forms +
4514 Tensor<spacedim - structdim, spacedim> child_alternating_forms
4518 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4519 for (
const unsigned int i : object->child(c)->vertex_indices())
4520 child_vertices[c][i] =
object->child(c)->vertex(i);
4528 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4530 1] = object_mid_point;
4532 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4534 child_vertices[c], child_alternating_forms[c]);
4546 double objective = 0;
4547 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4548 for (
const unsigned int i : object->child(c)->vertex_indices())
4550 (child_alternating_forms[c][i] -
4551 average_parent_alternating_form /
std::pow(2., 1. * structdim))
4563 template <
typename Iterator>
4566 const unsigned int f,
4567 std::integral_constant<int, 1>)
4569 return object->vertex(f);
4579 template <
typename Iterator>
4582 const unsigned int f,
4583 std::integral_constant<int, 2>)
4585 return object->line(f)->center();
4595 template <
typename Iterator>
4598 const unsigned int f,
4599 std::integral_constant<int, 3>)
4601 return object->face(f)->center();
4628 template <
typename Iterator>
4632 const unsigned int structdim =
4633 Iterator::AccessorType::structure_dimension;
4635 double diameter =
object->diameter();
4636 for (
const unsigned int f : object->face_indices())
4637 for (
unsigned int e = f + 1; e <
object->n_faces(); ++e)
4642 std::integral_constant<int, structdim>())
4644 object, e, std::integral_constant<int, structdim>())));
4655 template <
typename Iterator>
4659 const unsigned int structdim =
4660 Iterator::AccessorType::structure_dimension;
4661 const unsigned int spacedim = Iterator::AccessorType::space_dimension;
4668 Assert(object->refinement_case() ==
4678 unsigned int iteration = 0;
4683 double initial_delta = 0;
4690 const double step_length =
diameter / 4 / (iteration + 1);
4695 for (
unsigned int d = 0; d < spacedim; ++d)
4697 const double eps = step_length / 10;
4711 if (gradient.norm() == 0)
4720 std::min(2 * current_value / (gradient * gradient),
4721 step_length / gradient.norm()) *
4726 const double previous_value = current_value;
4730 initial_delta = (previous_value - current_value);
4733 if ((iteration >= 1) &&
4734 ((previous_value - current_value < 0) ||
4735 (std::fabs(previous_value - current_value) <
4736 0.001 * initial_delta)))
4741 while (iteration < 20);
4757 double old_min_product, new_min_product;
4762 parent_vertices[i] = object->vertex(i);
4764 Tensor<spacedim - structdim, spacedim>
4767 parent_vertices, parent_alternating_forms);
4773 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4774 for (
const unsigned int i : object->child(c)->vertex_indices())
4775 child_vertices[c][i] =
object->child(c)->vertex(i);
4777 Tensor<spacedim - structdim, spacedim> child_alternating_forms
4781 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4783 child_vertices[c], child_alternating_forms[c]);
4786 child_alternating_forms[0][0] * parent_alternating_forms[0];
4787 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4788 for (
const unsigned int i : object->child(c)->vertex_indices())
4789 for (
const unsigned int j : object->vertex_indices())
4790 old_min_product = std::min<double>(old_min_product,
4791 child_alternating_forms[c][i] *
4792 parent_alternating_forms[j]);
4800 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4802 1] = object_mid_point;
4804 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4806 child_vertices[c], child_alternating_forms[c]);
4809 child_alternating_forms[0][0] * parent_alternating_forms[0];
4810 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4811 for (
const unsigned int i : object->child(c)->vertex_indices())
4812 for (
const unsigned int j : object->vertex_indices())
4813 new_min_product = std::min<double>(new_min_product,
4814 child_alternating_forms[c][i] *
4815 parent_alternating_forms[j]);
4823 if (new_min_product >= old_min_product)
4824 object->child(0)->vertex(
4831 return (
std::max(new_min_product, old_min_product) > 0);
4837 template <
int dim,
int spacedim>
4840 const typename ::Triangulation<dim, spacedim>::cell_iterator
4842 std::integral_constant<int, dim>,
4843 std::integral_constant<int, spacedim>)
4853 for (
auto f : cell->face_indices())
4856 Assert(cell->face(f)->refinement_case() ==
4860 bool subface_is_more_refined =
false;
4861 for (
unsigned int g = 0;
4862 g < GeometryInfo<dim>::max_children_per_face;
4864 if (cell->face(f)->child(g)->has_children())
4866 subface_is_more_refined =
true;
4870 if (subface_is_more_refined ==
true)
4881 template <
int dim,
int spacedim>
4889 dim != 1 && spacedim != 1,
4890 "This function is only valid when dim != 1 or spacedim != 1.");
4894 for (
typename std::list<
4903 Assert(!cell->is_active(),
4905 "This function is only valid for a list of cells that "
4906 "have children (i.e., no cell in the list may be active)."));
4910 std::integral_constant<int, dim>(),
4911 std::integral_constant<int, spacedim>());
4918 return unfixable_subset;
4923 template <
int dim,
int spacedim>
4926 const bool reset_boundary_ids)
4929 std::vector<types::manifold_id> dst_manifold_ids(src_boundary_ids.size());
4930 auto m_it = dst_manifold_ids.begin();
4931 for (
const auto b : src_boundary_ids)
4936 const std::vector<types::boundary_id> reset_boundary_id =
4937 reset_boundary_ids ?
4938 std::vector<types::boundary_id>(src_boundary_ids.size(), 0) :
4948 template <
int dim,
int spacedim>
4951 const std::vector<types::boundary_id> &src_boundary_ids,
4952 const std::vector<types::manifold_id> &dst_manifold_ids,
4954 const std::vector<types::boundary_id> &reset_boundary_ids_)
4957 const auto reset_boundary_ids =
4958 reset_boundary_ids_.size() ? reset_boundary_ids_ : src_boundary_ids;
4967 for (
auto f : cell->face_indices())
4968 if (cell->face(f)->at_boundary())
4969 for (
unsigned int e = 0; e < cell->face(f)->n_lines(); ++e)
4971 const auto bid = cell->face(f)->line(e)->boundary_id();
4972 const unsigned int ind = std::find(src_boundary_ids.begin(),
4973 src_boundary_ids.end(),
4975 src_boundary_ids.begin();
4976 if (ind < src_boundary_ids.size())
4977 cell->face(f)->line(e)->set_manifold_id(
4978 dst_manifold_ids[ind]);
4983 for (
auto f : cell->face_indices())
4984 if (cell->face(f)->at_boundary())
4986 const auto bid = cell->face(f)->boundary_id();
4987 const unsigned int ind =
4988 std::find(src_boundary_ids.begin(), src_boundary_ids.end(), bid) -
4989 src_boundary_ids.begin();
4991 if (ind < src_boundary_ids.size())
4994 cell->face(f)->set_manifold_id(dst_manifold_ids[ind]);
4996 cell->face(f)->set_boundary_id(reset_boundary_ids[ind]);
5000 for (
unsigned int e = 0; e < cell->face(f)->n_lines(); ++e)
5002 const auto bid = cell->face(f)->line(e)->boundary_id();
5003 const unsigned int ind = std::find(src_boundary_ids.begin(),
5004 src_boundary_ids.end(),
5006 src_boundary_ids.begin();
5007 if (ind < src_boundary_ids.size())
5008 cell->face(f)->line(e)->set_boundary_id(
5009 reset_boundary_ids[ind]);
5015 template <
int dim,
int spacedim>
5018 const bool compute_face_ids)
5024 for (; cell != endc; ++cell)
5026 cell->set_manifold_id(cell->material_id());
5027 if (compute_face_ids ==
true)
5029 for (
auto f : cell->face_indices())
5031 if (cell->at_boundary(f) ==
false)
5032 cell->face(f)->set_manifold_id(
5034 cell->neighbor(f)->material_id()));
5036 cell->face(f)->set_manifold_id(cell->material_id());
5043 template <
int dim,
int spacedim>
5048 const std::set<types::manifold_id> &)> &disambiguation_function,
5049 bool overwrite_only_flat_manifold_ids)
5054 const unsigned int n_subobjects =
5058 std::vector<std::set<types::manifold_id>> manifold_ids(n_subobjects + 1);
5059 std::vector<unsigned int> backup;
5063 unsigned next_index = 1;
5067 for (
unsigned int l = 0; l < cell->n_lines(); ++l)
5069 if (cell->line(l)->user_index() == 0)
5072 manifold_ids[next_index].insert(cell->manifold_id());
5073 cell->line(l)->set_user_index(next_index++);
5076 manifold_ids[cell->line(l)->user_index()].insert(
5077 cell->manifold_id());
5080 for (
unsigned int l = 0; l < cell->n_faces(); ++l)
5082 if (cell->quad(l)->user_index() == 0)
5085 manifold_ids[next_index].insert(cell->manifold_id());
5086 cell->quad(l)->set_user_index(next_index++);
5089 manifold_ids[cell->quad(l)->user_index()].insert(
5090 cell->manifold_id());
5096 for (
unsigned int l = 0; l < cell->n_lines(); ++l)
5098 const auto id = cell->line(l)->user_index();
5102 if (cell->line(l)->manifold_id() ==
5104 overwrite_only_flat_manifold_ids ==
false)
5105 cell->line(l)->set_manifold_id(
5106 disambiguation_function(manifold_ids[
id]));
5107 cell->line(l)->set_user_index(0);
5111 for (
unsigned int l = 0; l < cell->n_faces(); ++l)
5113 const auto id = cell->quad(l)->user_index();
5117 if (cell->quad(l)->manifold_id() ==
5119 overwrite_only_flat_manifold_ids ==
false)
5120 cell->quad(l)->set_manifold_id(
5121 disambiguation_function(manifold_ids[
id]));
5122 cell->quad(l)->set_user_index(0);
5131 template <
int dim,
int spacedim>
5132 std::pair<unsigned int, double>
5136 double max_ratio = 1;
5137 unsigned int index = 0;
5139 for (
unsigned int i = 0; i < dim; ++i)
5140 for (
unsigned int j = i + 1; j < dim; ++j)
5142 unsigned int ax = i % dim;
5143 unsigned int next_ax = j % dim;
5146 cell->extent_in_direction(ax) / cell->extent_in_direction(next_ax);
5148 if (ratio > max_ratio)
5153 else if (1.0 / ratio > max_ratio)
5155 max_ratio = 1.0 / ratio;
5159 return std::make_pair(index, max_ratio);
5163 template <
int dim,
int spacedim>
5166 const bool isotropic,
5167 const unsigned int max_iterations)
5169 unsigned int iter = 0;
5170 bool continue_refinement =
true;
5172 while (continue_refinement && (iter < max_iterations))
5176 continue_refinement =
false;
5179 for (
const unsigned int j : cell->face_indices())
5180 if (cell->at_boundary(j) ==
false &&
5181 cell->neighbor(j)->has_children())
5185 cell->set_refine_flag();
5186 continue_refinement =
true;
5189 continue_refinement |= cell->flag_for_face_refinement(j);
5196 template <
int dim,
int spacedim>
5199 const double max_ratio,
5200 const unsigned int max_iterations)
5202 unsigned int iter = 0;
5203 bool continue_refinement =
true;
5205 while (continue_refinement && (iter < max_iterations))
5208 continue_refinement =
false;
5211 std::pair<unsigned int, double> info =
5212 GridTools::get_longest_direction<dim, spacedim>(cell);
5213 if (info.second > max_ratio)
5215 cell->set_refine_flag(
5217 continue_refinement =
true;
5225 template <
int dim,
int spacedim>
5228 const double limit_angle_fraction)
5236 "have hanging nodes."));
5240 bool has_cells_with_more_than_dim_faces_on_boundary =
true;
5241 bool has_cells_with_dim_faces_on_boundary =
false;
5243 unsigned int refinement_cycles = 0;
5245 while (has_cells_with_more_than_dim_faces_on_boundary)
5247 has_cells_with_more_than_dim_faces_on_boundary =
false;
5251 unsigned int boundary_face_counter = 0;
5252 for (
auto f : cell->face_indices())
5253 if (cell->face(f)->at_boundary())
5254 boundary_face_counter++;
5255 if (boundary_face_counter > dim)
5257 has_cells_with_more_than_dim_faces_on_boundary =
true;
5260 else if (boundary_face_counter == dim)
5261 has_cells_with_dim_faces_on_boundary =
true;
5263 if (has_cells_with_more_than_dim_faces_on_boundary)
5266 refinement_cycles++;
5270 if (has_cells_with_dim_faces_on_boundary)
5273 refinement_cycles++;
5277 while (refinement_cycles > 0)
5280 cell->set_coarsen_flag();
5282 refinement_cycles--;
5292 std::vector<CellData<dim>> cells_to_add;
5296 const unsigned int v0 = 0,
v1 = 1, v2 = (dim > 1 ? 2 : 0),
5297 v3 = (dim > 1 ? 3 : 0);
5301 double angle_fraction = 0;
5307 p0[spacedim > 1 ? 1 : 0] = 1;
5311 if (cell->face(
v0)->at_boundary() && cell->face(v3)->at_boundary())
5313 p0 = cell->vertex(
v0) - cell->vertex(v2);
5314 p1 = cell->vertex(v3) - cell->vertex(v2);
5315 vertex_at_corner = v2;
5317 else if (cell->face(v3)->at_boundary() &&
5318 cell->face(
v1)->at_boundary())
5320 p0 = cell->vertex(v2) - cell->vertex(v3);
5321 p1 = cell->vertex(
v1) - cell->vertex(v3);
5322 vertex_at_corner = v3;
5324 else if (cell->face(1)->at_boundary() &&
5325 cell->face(2)->at_boundary())
5327 p0 = cell->vertex(
v0) - cell->vertex(
v1);
5328 p1 = cell->vertex(v3) - cell->vertex(
v1);
5329 vertex_at_corner =
v1;
5331 else if (cell->face(2)->at_boundary() &&
5332 cell->face(0)->at_boundary())
5334 p0 = cell->vertex(v2) - cell->vertex(
v0);
5335 p1 = cell->vertex(
v1) - cell->vertex(
v0);
5336 vertex_at_corner =
v0;
5340 angle_fraction = std::acos(p0 * p1) /
numbers::PI;
5347 if (angle_fraction > limit_angle_fraction)
5349 auto flags_removal = [&](
unsigned int f1,
5352 unsigned int n2) ->
void {
5353 cells_to_remove[cell->active_cell_index()] =
true;
5354 cells_to_remove[cell->neighbor(n1)->active_cell_index()] =
true;
5355 cells_to_remove[cell->neighbor(n2)->active_cell_index()] =
true;
5357 faces_to_remove[cell->face(f1)->index()] =
true;
5358 faces_to_remove[cell->face(f2)->index()] =
true;
5360 faces_to_remove[cell->neighbor(n1)->face(f1)->index()] =
true;
5361 faces_to_remove[cell->neighbor(n2)->face(f2)->index()] =
true;
5364 auto cell_creation = [&](
const unsigned int vv0,
5365 const unsigned int vv1,
5366 const unsigned int f0,
5367 const unsigned int f1,
5369 const unsigned int n0,
5370 const unsigned int v0n0,
5371 const unsigned int v1n0,
5373 const unsigned int n1,
5374 const unsigned int v0n1,
5375 const unsigned int v1n1) {
5381 c1.
vertices[v2] = cell->neighbor(n0)->vertex_index(v0n0);
5382 c1.
vertices[v3] = cell->neighbor(n0)->vertex_index(v1n0);
5388 c2.
vertices[
v1] = cell->neighbor(n1)->vertex_index(v0n1);
5389 c2.
vertices[v2] = cell->vertex_index(vv1);
5390 c2.
vertices[v3] = cell->neighbor(n1)->vertex_index(v1n1);
5395 l1.
vertices[0] = cell->vertex_index(vv0);
5396 l1.
vertices[1] = cell->neighbor(n0)->vertex_index(v0n0);
5402 l2.
vertices[0] = cell->vertex_index(vv0);
5403 l2.
vertices[1] = cell->neighbor(n1)->vertex_index(v0n1);
5409 cells_to_add.push_back(c1);
5410 cells_to_add.push_back(c2);
5415 switch (vertex_at_corner)
5418 flags_removal(0, 2, 3, 1);
5419 cell_creation(0, 3, 0, 2, 3, 2, 3, 1, 1, 3);
5422 flags_removal(1, 2, 3, 0);
5423 cell_creation(1, 2, 2, 1, 0, 0, 2, 3, 3, 2);
5426 flags_removal(3, 0, 1, 2);
5427 cell_creation(2, 1, 3, 0, 1, 3, 1, 2, 0, 1);
5430 flags_removal(3, 1, 0, 2);
5431 cell_creation(3, 0, 1, 3, 2, 1, 0, 0, 2, 0);
5444 if (cells_to_add.size() == 0)
5446 while (refinement_cycles > 0)
5449 cell->set_coarsen_flag();
5451 refinement_cycles--;
5459 if (cells_to_remove[cell->active_cell_index()] ==
false)
5462 for (
const unsigned int v : cell->vertex_indices())
5463 c.
vertices[v] = cell->vertex_index(v);
5466 cells_to_add.push_back(c);
5474 for (; face != endf; ++face)
5475 if ((face->at_boundary() ||
5477 faces_to_remove[face->index()] ==
false)
5479 for (
unsigned int l = 0; l < face->n_lines(); ++l)
5484 for (
const unsigned int v : face->vertex_indices())
5485 line.
vertices[v] = face->vertex_index(v);
5491 for (
const unsigned int v : face->line(l)->vertex_indices())
5492 line.
vertices[v] = face->line(l)->vertex_index(v);
5501 for (
const unsigned int v : face->vertex_indices())
5502 quad.
vertices[v] = face->vertex_index(v);
5510 subcelldata_to_add);
5515 std::map<types::manifold_id, std::unique_ptr<Manifold<dim, spacedim>>>
5518 for (
const auto manifold_id : manifold_ids)
5527 for (
const auto manifold_id : manifold_ids)
5534 template <
int dim,
int spacedim>
5537 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
5538 std::vector<std::vector<Point<dim>>>,
5539 std::vector<std::vector<unsigned int>>>
5551 auto &cells = std::get<0>(cqmp);
5552 auto &qpoints = std::get<1>(cqmp);
5553 auto &maps = std::get<2>(cqmp);
5555 return std::make_tuple(std::move(cells),
5562 template <
int dim,
int spacedim>
5565 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
5566 std::vector<std::vector<Point<dim>>>,
5567 std::vector<std::vector<unsigned int>>,
5568 std::vector<unsigned int>>
5578 Assert((dim == spacedim),
5579 ExcMessage(
"Only implemented for dim==spacedim."));
5588 const unsigned int np = points.size();
5590 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>
5592 std::vector<std::vector<Point<dim>>> qpoints_out;
5593 std::vector<std::vector<unsigned int>> maps_out;
5594 std::vector<unsigned int> missing_points_out;
5598 return std::make_tuple(std::move(cells_out),
5599 std::move(qpoints_out),
5600 std::move(maps_out),
5601 std::move(missing_points_out));
5609 std::vector<std::pair<Point<spacedim>,
unsigned int>> points_and_ids(np);
5610 for (
unsigned int i = 0; i < np; ++i)
5611 points_and_ids[i] = std::make_pair(points[i], i);
5612 const auto p_tree =
pack_rtree(points_and_ids);
5615 std::vector<bool> found_points(points.size(),
false);
5618 const auto already_found = [&found_points](
const auto &id) {
5620 return found_points[
id.second];
5626 const auto store_cell_point_and_id =
5630 const unsigned int &id) {
5631 const auto it = std::find(cells_out.rbegin(), cells_out.rend(), cell);
5632 if (it != cells_out.rend())
5634 const auto cell_id =
5635 (cells_out.size() - 1 - (it - cells_out.rbegin()));
5636 qpoints_out[cell_id].emplace_back(ref_point);
5637 maps_out[cell_id].emplace_back(
id);
5641 cells_out.emplace_back(cell);
5642 qpoints_out.emplace_back(std::vector<
Point<dim>>({ref_point}));
5643 maps_out.emplace_back(std::vector<unsigned int>({
id}));
5648 const auto check_all_points_within_box = [&](
const auto &leaf) {
5649 const auto &box = leaf.first;
5650 const auto &cell_hint = leaf.second;
5652 for (
const auto &point_and_id :
5653 p_tree | bgi::adaptors::queried(!bgi::satisfies(already_found) &&
5654 bgi::intersects(box)))
5656 const auto id = point_and_id.second;
5657 const auto cell_and_ref =
5661 const auto &cell = cell_and_ref.first;
5662 const auto &ref_point = cell_and_ref.second;
5665 store_cell_point_and_id(cell, ref_point,
id);
5667 missing_points_out.emplace_back(
id);
5670 found_points[id] =
true;
5676 check_all_points_within_box(
5677 std::make_pair(mapping.get_bounding_box(cell_hint), cell_hint));
5680 for (
unsigned int i = 0; i < np; ++i)
5681 if (found_points[i] ==
false)
5684 const auto leaf = b_tree.qbegin(bgi::nearest(points[i], 1));
5686 if (leaf != b_tree.qend())
5687 check_all_points_within_box(*leaf);
5695 for (
unsigned int i = 0; i < np; ++i)
5696 if (found_points[i] ==
false)
5697 missing_points_out.emplace_back(i);
5704 unsigned int c = cells_out.size();
5705 unsigned int qps = 0;
5711 for (
unsigned int n = 0; n < c; ++n)
5714 qps += qpoints_out[n].size();
5717 Assert(qps + missing_points_out.size() == np,
5721 return std::make_tuple(std::move(cells_out),
5722 std::move(qpoints_out),
5723 std::move(maps_out),
5724 std::move(missing_points_out));
5729 template <
int dim,
int spacedim>
5732 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
5733 std::vector<std::vector<Point<dim>>>,
5734 std::vector<std::vector<unsigned int>>,
5735 std::vector<std::vector<Point<spacedim>>>,
5736 std::vector<std::vector<unsigned int>>>
5744 const double tolerance)
5748 cache, points, global_bboxes, {}, tolerance,
false,
true)
5753 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
5754 std::vector<std::vector<Point<dim>>>,
5755 std::vector<std::vector<unsigned int>>,
5756 std::vector<std::vector<Point<spacedim>>>,
5757 std::vector<std::vector<unsigned int>>>
5760 std::pair<int, int> dummy{-1, -1};
5762 for (
unsigned int i = 0; i < all.size(); ++i)
5764 if (dummy != std::get<0>(all[i]))
5766 std::get<0>(result).push_back(
5769 std::get<0>(all[i]).
first,
5770 std::get<0>(all[i]).
second});
5772 const unsigned int new_size = std::get<0>(result).size();
5774 std::get<1>(result).resize(new_size);
5775 std::get<2>(result).resize(new_size);
5776 std::get<3>(result).resize(new_size);
5777 std::get<4>(result).resize(new_size);
5779 dummy = std::get<0>(all[i]);
5782 std::get<1>(result).back().push_back(
5783 std::get<3>(all[i]));
5784 std::get<2>(result).back().push_back(std::get<2>(all[i]));
5785 std::get<3>(result).back().push_back(std::get<4>(all[i]));
5786 std::get<4>(result).back().push_back(std::get<1>(all[i]));
5796 template <
int spacedim>
5797 std::tuple<std::vector<unsigned int>,
5798 std::vector<unsigned int>,
5799 std::vector<unsigned int>>
5803 const double tolerance)
5805 std::vector<std::pair<unsigned int, unsigned int>> ranks_and_indices;
5806 ranks_and_indices.reserve(points.size());
5808 for (
unsigned int i = 0; i < points.size(); ++i)
5810 const auto &point = points[i];
5811 for (
unsigned rank = 0; rank < global_bboxes.size(); ++rank)
5812 for (
const auto &box : global_bboxes[rank])
5813 if (box.point_inside(point, tolerance))
5815 ranks_and_indices.emplace_back(rank, i);
5821 std::sort(ranks_and_indices.begin(), ranks_and_indices.end());
5823 std::vector<unsigned int> ranks;
5824 std::vector<unsigned int> ptr;
5825 std::vector<unsigned int> indices;
5829 for (
const auto &i : ranks_and_indices)
5831 if (dummy_rank != i.first)
5833 dummy_rank = i.first;
5834 ranks.push_back(dummy_rank);
5835 ptr.push_back(indices.size());
5838 indices.push_back(i.second);
5840 ptr.push_back(indices.size());
5842 return std::make_tuple(std::move(ranks),
5844 std::move(indices));
5849 template <
int dim,
int spacedim>
5851 std::pair<typename Triangulation<dim, spacedim>::active_cell_iterator,
5857 const std::vector<bool> &marked_vertices,
5858 const double tolerance,
5859 const bool enforce_unique_mapping)
5862 std::pair<typename Triangulation<dim, spacedim>::active_cell_iterator,
5864 locally_owned_active_cells_around_point;
5881 cell_hint = first_cell.first;
5884 const auto active_cells_around_point =
5892 if (enforce_unique_mapping)
5899 for (
const auto &cell : active_cells_around_point)
5900 lowes_rank =
std::min(lowes_rank, cell.first->subdomain_id());
5902 if (lowes_rank != my_rank)
5906 locally_owned_active_cells_around_point.reserve(
5907 active_cells_around_point.size());
5909 for (
const auto &cell : active_cells_around_point)
5910 if (cell.first->is_locally_owned())
5911 locally_owned_active_cells_around_point.push_back(cell);
5914 std::sort(locally_owned_active_cells_around_point.begin(),
5915 locally_owned_active_cells_around_point.end(),
5916 [](
const auto &a,
const auto &b) { return a.first < b.first; });
5918 if (enforce_unique_mapping &&
5919 locally_owned_active_cells_around_point.size() > 1)
5921 return {locally_owned_active_cells_around_point.front()};
5923 return locally_owned_active_cells_around_point;
5928 template <
int dim,
int spacedim>
5929 DistributedComputePointLocationsInternal<dim, spacedim>
5934 const std::vector<bool> & marked_vertices,
5935 const double tolerance,
5936 const bool perform_handshake,
5937 const bool enforce_unique_mapping)
5948 const auto potential_owners =
5951 const auto &potential_owners_ranks = std::get<0>(potential_owners);
5952 const auto &potential_owners_ptrs = std::get<1>(potential_owners);
5953 const auto &potential_owners_indices = std::get<2>(potential_owners);
5957 const auto translate = [&](
const unsigned int other_rank) {
5958 const auto ptr = std::find(potential_owners_ranks.begin(),
5959 potential_owners_ranks.end(),
5964 const auto other_rank_index =
5965 std::distance(potential_owners_ranks.begin(), ptr);
5967 return other_rank_index;
5971 (marked_vertices.size() == 0) ||
5974 "The marked_vertices vector has to be either empty or its size has "
5975 "to equal the number of vertices of the triangulation."));
5977 using RequestType = std::vector<std::pair<unsigned int, Point<spacedim>>>;
5978 using AnswerType = std::vector<unsigned int>;
5984 const bool has_relevant_vertices =
5985 (marked_vertices.size() == 0) ||
5986 (std::find(marked_vertices.begin(), marked_vertices.end(),
true) !=
5987 marked_vertices.end());
5989 const auto create_request = [&](
const unsigned int other_rank) {
5990 const auto other_rank_index = translate(other_rank);
5992 RequestType request;
5993 request.reserve(potential_owners_ptrs[other_rank_index + 1] -
5994 potential_owners_ptrs[other_rank_index]);
5996 for (
unsigned int i = potential_owners_ptrs[other_rank_index];
5997 i < potential_owners_ptrs[other_rank_index + 1];
5999 request.emplace_back(potential_owners_indices[i],
6000 points[potential_owners_indices[i]]);
6005 const auto answer_request =
6006 [&](
const unsigned int &other_rank,
6007 const RequestType & request) -> AnswerType {
6008 AnswerType answer(request.size(), 0);
6010 if (has_relevant_vertices)
6014 for (
unsigned int i = 0; i < request.size(); ++i)
6016 const auto &index_and_point = request[i];
6018 const auto cells_and_reference_positions =
6021 index_and_point.second,
6025 enforce_unique_mapping);
6027 for (
const auto &cell_and_reference_position :
6028 cells_and_reference_positions)
6030 send_components.emplace_back(
6031 std::pair<int, int>(
6032 cell_and_reference_position.first->level(),
6033 cell_and_reference_position.first->index()),
6035 index_and_point.first,
6036 cell_and_reference_position.second,
6037 index_and_point.second,
6041 answer[i] = cells_and_reference_positions.size();
6045 if (perform_handshake)
6051 const auto process_answer = [&](
const unsigned int other_rank,
6052 const AnswerType & answer) {
6053 if (perform_handshake)
6055 const auto other_rank_index = translate(other_rank);
6057 for (
unsigned int i = 0; i < answer.size(); ++i)
6058 for (
unsigned int j = 0; j < answer[i]; ++j)
6059 recv_components.emplace_back(
6061 potential_owners_indices
6062 [i + potential_owners_ptrs[other_rank_index]],
6067 Utilities::MPI::ConsensusAlgorithms::selector<RequestType, AnswerType>(
6068 potential_owners_ranks,
6078 std::sort(send_components.begin(),
6079 send_components.end(),
6080 [&](
const auto &a,
const auto &b) {
6081 if (std::get<1>(a) != std::get<1>(b))
6082 return std::get<1>(a) < std::get<1>(b);
6084 if (std::get<2>(a) != std::get<2>(b))
6085 return std::get<2>(a) < std::get<2>(b);
6087 return std::get<0>(a) < std::get<0>(b);
6092 i < send_components.size();
6095 std::get<5>(send_components[i]) = i;
6097 if (dummy != std::get<1>(send_components[i]))
6099 dummy = std::get<1>(send_components[i]);
6100 send_ranks.push_back(dummy);
6101 send_ptrs.push_back(i);
6104 send_ptrs.push_back(send_components.size());
6108 std::sort(send_components.begin(),
6109 send_components.end(),
6110 [&](
const auto &a,
const auto &b) {
6111 if (std::get<0>(a) != std::get<0>(b))
6112 return std::get<0>(a) < std::get<0>(b);
6114 if (std::get<1>(a) != std::get<1>(b))
6115 return std::get<1>(a) < std::get<1>(b);
6117 if (std::get<2>(a) != std::get<2>(b))
6118 return std::get<2>(a) < std::get<2>(b);
6120 return std::get<5>(a) < std::get<5>(b);
6124 if (perform_handshake)
6127 std::sort(recv_components.begin(),
6128 recv_components.end(),
6129 [&](
const auto &a,
const auto &b) {
6130 if (std::get<0>(a) != std::get<0>(b))
6131 return std::get<0>(a) < std::get<0>(b);
6133 return std::get<1>(a) < std::get<1>(b);
6138 i < recv_components.size();
6141 std::get<2>(recv_components[i]) = i;
6143 if (dummy != std::get<0>(recv_components[i]))
6145 dummy = std::get<0>(recv_components[i]);
6146 recv_ranks.push_back(dummy);
6147 recv_ptrs.push_back(i);
6150 recv_ptrs.push_back(recv_components.size());
6154 std::sort(recv_components.begin(),
6155 recv_components.end(),
6156 [&](
const auto &a,
const auto &b) {
6157 if (std::get<1>(a) != std::get<1>(b))
6158 return std::get<1>(a) < std::get<1>(b);
6160 if (std::get<0>(a) != std::get<0>(b))
6161 return std::get<0>(a) < std::get<0>(b);
6163 return std::get<2>(a) < std::get<2>(b);
6173 template <
int dim,
int spacedim>
6174 std::map<unsigned int, Point<spacedim>>
6178 std::map<unsigned int, Point<spacedim>> result;
6181 if (!cell->is_artificial())
6184 for (
unsigned int i = 0; i < vs.size(); ++i)
6185 result[cell->vertex_index(i)] = vs[i];
6192 template <
int spacedim>
6197 auto id_and_v = std::min_element(
6202 return p1.second.distance(p) < p2.second.distance(p);
6204 return id_and_v->first;
6208 template <
int dim,
int spacedim>
6209 std::pair<typename Triangulation<dim, spacedim>::active_cell_iterator,
6216 const std::vector<bool> &marked_vertices,
6217 const double tolerance)
6222 const auto &vertex_to_cell_centers =
6230 vertex_to_cell_centers,
6233 used_vertices_rtree,
6237 template <
int spacedim>
6238 std::vector<std::vector<BoundingBox<spacedim>>>
6243#ifndef DEAL_II_WITH_MPI
6245 (void)mpi_communicator;
6248 "GridTools::exchange_local_bounding_boxes() requires MPI."));
6252 unsigned int n_bboxes = local_bboxes.size();
6254 int n_local_data = 2 * spacedim * n_bboxes;
6256 std::vector<double> loc_data_array(n_local_data);
6257 for (
unsigned int i = 0; i < n_bboxes; ++i)
6258 for (
unsigned int d = 0; d < spacedim; ++d)
6261 loc_data_array[2 * i * spacedim + d] =
6262 local_bboxes[i].get_boundary_points().first[d];
6263 loc_data_array[2 * i * spacedim + spacedim + d] =
6264 local_bboxes[i].get_boundary_points().second[d];
6271 std::vector<int> size_all_data(n_procs);
6274 int ierr = MPI_Allgather(&n_local_data,
6277 size_all_data.data(),
6285 std::vector<int> rdispls(n_procs);
6287 for (
unsigned int i = 1; i < n_procs; ++i)
6288 rdispls[i] = rdispls[i - 1] + size_all_data[i - 1];
6292 std::vector<double> data_array(rdispls.back() + size_all_data.back());
6294 ierr = MPI_Allgatherv(loc_data_array.data(),
6298 size_all_data.data(),
6305 std::vector<std::vector<BoundingBox<spacedim>>> global_bboxes(n_procs);
6306 unsigned int begin_idx = 0;
6307 for (
unsigned int i = 0; i < n_procs; ++i)
6310 unsigned int n_bbox_i = size_all_data[i] / (spacedim * 2);
6311 global_bboxes[i].resize(n_bbox_i);
6312 for (
unsigned int bbox = 0; bbox < n_bbox_i; ++bbox)
6315 for (
unsigned int d = 0; d < spacedim; ++d)
6317 p1[d] = data_array[begin_idx + 2 * bbox * spacedim + d];
6319 data_array[begin_idx + 2 * bbox * spacedim + spacedim + d];
6322 global_bboxes[i][bbox] = loc_bbox;
6325 begin_idx += size_all_data[i];
6327 return global_bboxes;
6333 template <
int spacedim>
6339#ifndef DEAL_II_WITH_MPI
6340 (void)mpi_communicator;
6342 std::vector<std::pair<BoundingBox<spacedim>,
unsigned int>> boxes_index(
6343 local_description.size());
6345 for (
unsigned int i = 0; i < local_description.size(); ++i)
6346 boxes_index[i] = std::make_pair(local_description[i], 0u);
6350 const std::vector<std::vector<BoundingBox<spacedim>>> global_bboxes =
6354 const unsigned int n_procs =
6358 std::vector<unsigned int> bboxes_position(n_procs);
6360 unsigned int tot_bboxes = 0;
6361 for (
const auto &process_bboxes : global_bboxes)
6362 tot_bboxes += process_bboxes.size();
6365 std::vector<std::pair<BoundingBox<spacedim>,
unsigned int>>
6367 flat_global_bboxes.reserve(tot_bboxes);
6368 unsigned int process_index = 0;
6369 for (
const auto &process_bboxes : global_bboxes)
6372 std::vector<std::pair<BoundingBox<spacedim>,
unsigned int>>
6373 boxes_and_indices(process_bboxes.size());
6376 for (
unsigned int i = 0; i < process_bboxes.size(); ++i)
6377 boxes_and_indices[i] =
6378 std::make_pair(process_bboxes[i], process_index);
6380 flat_global_bboxes.insert(flat_global_bboxes.end(),
6381 boxes_and_indices.begin(),
6382 boxes_and_indices.end());
6390 flat_global_bboxes.begin(), flat_global_bboxes.end());
6396 template <
int dim,
int spacedim>
6406 static const int lookup_table_2d[2][2] =
6413 static const int lookup_table_3d[2][2][2][4] =
6435 if (pair.first.first->level() != pair.second.first.first->level())
6438 const auto face_a = pair.first.first->face(pair.first.second);
6440 pair.second.first.first->face(pair.second.first.second);
6441 const auto mask = pair.second.second;
6446 for (
unsigned int i = 0; i < face_a->n_vertices(); ++i)
6448 const bool face_orientation = mask[0];
6449 const bool face_flip = mask[1];
6450 const bool face_rotation = mask[2];
6460 j = lookup_table_2d[face_flip][i];
6463 j = lookup_table_3d[face_orientation][face_flip]
6471 const auto vertex_a = face_a->vertex_index(i);
6472 const auto vertex_b = face_b->vertex_index(j);
6473 unsigned int temp =
std::min(vertex_a, vertex_b);
6477 temp =
std::min(temp, it_a->second);
6481 temp =
std::min(temp, it_b->second);
6484 it_a->second = temp;
6489 it_b->second = temp;
6499 if (p.first == p.second)
6501 unsigned int temp = p.second;
6519 template <
int dim,
int spacedim>
6520 std::map<unsigned int, std::set<::types::subdomain_id>>
6539 for (
const auto &cell :
6541 for (
const unsigned int v : cell->vertex_indices())
6542 vertex_of_own_cell[cell->vertex_index(v)] =
true;
6546 std::map<unsigned int, std::set<types::subdomain_id>> result;
6550 if (cell->is_ghost())
6555 for (
const unsigned int v : cell->vertex_indices())
6558 if (vertex_of_own_cell[cell->vertex_index(v)])
6559 result[cell->vertex_index(v)].insert(owner);
6562 auto coinciding_vertex_group =
6564 if (coinciding_vertex_group !=
6566 for (
auto coinciding_vertex :
6568 if (vertex_of_own_cell[coinciding_vertex])
6569 result[coinciding_vertex].insert(owner);
6578 template <
int dim,
typename VectorType>
6582 const unsigned int n_subdivisions,
6583 const double tolerance)
6584 : n_subdivisions(n_subdivisions)
6585 , tolerance(tolerance)
6586 , fe_values(mapping,
6588 create_quadrature_rule(n_subdivisions),
6594 template <
int dim,
typename VectorType>
6597 const unsigned int n_subdivisions)
6599 std::vector<Point<dim>> quadrature_points;
6603 for (
unsigned int j = 0; j <= n_subdivisions; ++j)
6604 for (
unsigned int i = 0; i <= n_subdivisions; ++i)
6605 quadrature_points.emplace_back(1.0 / n_subdivisions * i,
6606 1.0 / n_subdivisions * j);
6610 for (
unsigned int k = 0; k <= n_subdivisions; ++k)
6611 for (
unsigned int j = 0; j <= n_subdivisions; ++j)
6612 for (
unsigned int i = 0; i <= n_subdivisions; ++i)
6613 quadrature_points.emplace_back(1.0 / n_subdivisions * i,
6614 1.0 / n_subdivisions * j,
6615 1.0 / n_subdivisions * k);
6619 return {quadrature_points};
6624 template <
int dim,
typename VectorType>
6628 const VectorType & ls_vector,
6629 const double iso_level,
6635 process_cell(cell, ls_vector, iso_level,
vertices, cells);
6640 template <
int dim,
typename VectorType>
6644 const VectorType & ls_vector,
6645 const double iso_level,
6649 std::vector<value_type> ls_values;
6651 fe_values.reinit(cell);
6652 ls_values.resize(fe_values.n_quadrature_points);
6653 fe_values.get_function_values(ls_vector, ls_values);
6655 ls_values, fe_values.get_quadrature_points(), iso_level,
vertices, cells);
6660 template <
int dim,
typename VectorType>
6663 std::vector<value_type> & ls_values,
6665 const double iso_level,
6669 const unsigned p = n_subdivisions + 1;
6673 for (
unsigned int j = 0; j < n_subdivisions; ++j)
6674 for (
unsigned int i = 0; i < n_subdivisions; ++i)
6676 std::vector<unsigned int> mask{p * (j + 0) + (i + 0),
6677 p * (j + 0) + (i + 1),
6678 p * (j + 1) + (i + 1),
6679 p * (j + 1) + (i + 0)};
6682 ls_values, points, mask, iso_level,
vertices, cells);
6687 for (
unsigned int k = 0; k < n_subdivisions; ++k)
6688 for (
unsigned int j = 0; j < n_subdivisions; ++j)
6689 for (
unsigned int i = 0; i < n_subdivisions; ++i)
6691 std::vector<unsigned int> mask{
6692 p * p * (k + 0) + p * (j + 0) + (i + 0),
6693 p * p * (k + 0) + p * (j + 0) + (i + 1),
6694 p * p * (k + 0) + p * (j + 1) + (i + 1),
6695 p * p * (k + 0) + p * (j + 1) + (i + 0),
6696 p * p * (k + 1) + p * (j + 0) + (i + 0),
6697 p * p * (k + 1) + p * (j + 0) + (i + 1),
6698 p * p * (k + 1) + p * (j + 1) + (i + 1),
6699 p * p * (k + 1) + p * (j + 1) + (i + 0)};
6702 ls_values, points, mask, iso_level,
vertices, cells);
6712 unsigned int n_vertices,
6713 unsigned int n_sub_vertices,
6714 unsigned int n_configurations,
6715 unsigned int n_lines,
6716 unsigned int n_cols,
6717 typename value_type>
6720 const std::array<unsigned int, n_configurations> & cut_line_table,
6723 const std::vector<value_type> & ls_values,
6725 const std::vector<unsigned int> & mask,
6726 const double iso_level,
6727 const double tolerance,
6733 constexpr unsigned int X =
static_cast<unsigned int>(-1);
6736 unsigned int configuration = 0;
6737 for (
unsigned int v = 0; v < n_vertices; ++v)
6738 if (ls_values[mask[v]] < iso_level)
6739 configuration |= (1 << v);
6742 if (cut_line_table[configuration] == 0)
6747 const auto interpolate = [&](
const unsigned int i,
const unsigned int j) {
6748 if (
std::abs(iso_level - ls_values[mask[i]]) < tolerance)
6749 return points[mask[i]];
6750 if (
std::abs(iso_level - ls_values[mask[j]]) < tolerance)
6751 return points[mask[j]];
6752 if (
std::abs(ls_values[mask[i]] - ls_values[mask[j]]) < tolerance)
6753 return points[mask[i]];
6755 const double mu = (iso_level - ls_values[mask[i]]) /
6756 (ls_values[mask[j]] - ls_values[mask[i]]);
6759 mu * (points[mask[j]] - points[mask[i]]));
6763 std::array<Point<dim>, n_lines> vertex_list_all;
6764 for (
unsigned int l = 0; l < n_lines; ++l)
6765 if (cut_line_table[configuration] & (1 << l))
6766 vertex_list_all[l] =
6767 interpolate(line_to_vertex_table[l][0], line_to_vertex_table[l][1]);
6770 unsigned int local_vertex_count = 0;
6771 std::array<Point<dim>, n_lines> vertex_list_reduced;
6772 std::array<unsigned int, n_lines> local_remap;
6773 std::fill(local_remap.begin(), local_remap.end(), X);
6774 for (
int i = 0; new_line_table[configuration][i] != X; ++i)
6775 if (local_remap[new_line_table[configuration][i]] == X)
6777 vertex_list_reduced[local_vertex_count] =
6778 vertex_list_all[new_line_table[configuration][i]];
6779 local_remap[new_line_table[configuration][i]] = local_vertex_count;
6780 local_vertex_count++;
6784 const unsigned int n_vertices_old =
vertices.size();
6785 for (
unsigned int i = 0; i < local_vertex_count; ++i)
6786 vertices.push_back(vertex_list_reduced[i]);
6789 for (
unsigned int i = 0; new_line_table[configuration][i] != X;
6790 i += n_sub_vertices)
6792 cells.resize(cells.size() + 1);
6793 cells.back().vertices.resize(n_sub_vertices);
6795 for (
unsigned int v = 0; v < n_sub_vertices; ++v)
6796 cells.back().vertices[v] =
6797 local_remap[new_line_table[configuration][i + v]] +
6805 template <
int dim,
typename VectorType>
6808 const std::vector<value_type> & ls_values,
6809 const std::vector<
Point<2>> & points,
6810 const std::vector<unsigned int> mask,
6811 const double iso_level,
6816 constexpr unsigned int n_vertices = 4;
6817 constexpr unsigned int n_sub_vertices = 2;
6818 constexpr unsigned int n_lines = 4;
6819 constexpr unsigned int n_configurations =
Utilities::pow(2, n_vertices);
6820 constexpr unsigned int X =
static_cast<unsigned int>(-1);
6824 constexpr std::array<unsigned int, n_configurations> cut_line_table = {
6860 {{X, X, X, X, X}}}};
6864 {{{0, 3}}, {{1, 2}}, {{0, 1}}, {{3, 2}}}};
6874 line_to_vertex_table,
6886 template <
int dim,
typename VectorType>
6889 const std::vector<value_type> & ls_values,
6890 const std::vector<
Point<3>> & points,
6891 const std::vector<unsigned int> mask,
6892 const double iso_level,
6897 constexpr unsigned int n_vertices = 8;
6898 constexpr unsigned int n_sub_vertices = 3;
6899 constexpr unsigned int n_lines = 12;
6900 constexpr unsigned int n_configurations =
Utilities::pow(2, n_vertices);
6901 constexpr unsigned int X =
static_cast<unsigned int>(-1);
6906 constexpr std::array<unsigned int, n_configurations> cut_line_table = {{
6907 0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905,
6908 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x99, 0x393, 0x29a,
6909 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93,
6910 0xf99, 0xe90, 0x230, 0x339, 0x33, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
6911 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 0x3a0, 0x2a9,
6912 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6,
6913 0xfaa, 0xea3, 0xda9, 0xca0, 0x460, 0x569, 0x663, 0x76a, 0x66, 0x16f,
6914 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
6915 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff, 0x3f5, 0x2fc, 0xdfc, 0xcf5,
6916 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 0x650, 0x759, 0x453, 0x55a,
6917 0x256, 0x35f, 0x55, 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53,
6918 0x859, 0x950, 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc,
6919 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 0x8c0, 0x9c9,
6920 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc, 0x1c5, 0x2cf, 0x3c6,
6921 0x4ca, 0x5c3, 0x6c9, 0x7c0, 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f,
6922 0xf55, 0xe5c, 0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
6923 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5,
6924 0xff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 0xb60, 0xa69, 0x963, 0x86a,
6925 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663,
6926 0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
6927 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0, 0xd30, 0xc39,
6928 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636,
6929 0x13a, 0x33, 0x339, 0x230, 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f,
6930 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99, 0x190,
6931 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605,
6932 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0}};
6938 {{{X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6939 {{0, 8, 3, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6940 {{0, 1, 9, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6941 {{1, 8, 3, 9, 8, 1, X, X, X, X, X, X, X, X, X, X}},
6942 {{1, 2, 10, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6943 {{0, 8, 3, 1, 2, 10, X, X, X, X, X, X, X, X, X, X}},
6944 {{9, 2, 10, 0, 2, 9, X, X, X, X, X, X, X, X, X, X}},
6945 {{2, 8, 3, 2, 10, 8, 10, 9, 8, X, X, X, X, X, X, X}},
6946 {{3, 11, 2, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6947 {{0, 11, 2, 8, 11, 0, X, X, X, X, X, X, X, X, X, X}},
6948 {{1, 9, 0, 2, 3, 11, X, X, X, X, X, X, X, X, X, X}},
6949 {{1, 11, 2, 1, 9, 11, 9, 8, 11, X, X, X, X, X, X, X}},
6950 {{3, 10, 1, 11, 10, 3, X, X, X, X, X, X, X, X, X, X}},
6951 {{0, 10, 1, 0, 8, 10, 8, 11, 10, X, X, X, X, X, X, X}},
6952 {{3, 9, 0, 3, 11, 9, 11, 10, 9, X, X, X, X, X, X, X}},
6953 {{9, 8, 10, 10, 8, 11, X, X, X, X, X, X, X, X, X, X}},
6954 {{4, 7, 8, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6955 {{4, 3, 0, 7, 3, 4, X, X, X, X, X, X, X, X, X, X}},
6956 {{0, 1, 9, 8, 4, 7, X, X, X, X, X, X, X, X, X, X}},
6957 {{4, 1, 9, 4, 7, 1, 7, 3, 1, X, X, X, X, X, X, X}},
6958 {{1, 2, 10, 8, 4, 7, X, X, X, X, X, X, X, X, X, X}},
6959 {{3, 4, 7, 3, 0, 4, 1, 2, 10, X, X, X, X, X, X, X}},
6960 {{9, 2, 10, 9, 0, 2, 8, 4, 7, X, X, X, X, X, X, X}},
6961 {{2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, X, X, X, X}},
6962 {{8, 4, 7, 3, 11, 2, X, X, X, X, X, X, X, X, X, X}},
6963 {{11, 4, 7, 11, 2, 4, 2, 0, 4, X, X, X, X, X, X, X}},
6964 {{9, 0, 1, 8, 4, 7, 2, 3, 11, X, X, X, X, X, X, X}},
6965 {{4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, X, X, X, X}},
6966 {{3, 10, 1, 3, 11, 10, 7, 8, 4, X, X, X, X, X, X, X}},
6967 {{1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, X, X, X, X}},
6968 {{4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, X, X, X, X}},
6969 {{4, 7, 11, 4, 11, 9, 9, 11, 10, X, X, X, X, X, X, X}},
6970 {{9, 5, 4, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6971 {{9, 5, 4, 0, 8, 3, X, X, X, X, X, X, X, X, X, X}},
6972 {{0, 5, 4, 1, 5, 0, X, X, X, X, X, X, X, X, X, X}},
6973 {{8, 5, 4, 8, 3, 5, 3, 1, 5, X, X, X, X, X, X, X}},
6974 {{1, 2, 10, 9, 5, 4, X, X, X, X, X, X, X, X, X, X}},
6975 {{3, 0, 8, 1, 2, 10, 4, 9, 5, X, X, X, X, X, X, X}},
6976 {{5, 2, 10, 5, 4, 2, 4, 0, 2, X, X, X, X, X, X, X}},
6977 {{2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, X, X, X, X}},
6978 {{9, 5, 4, 2, 3, 11, X, X, X, X, X, X, X, X, X, X}},
6979 {{0, 11, 2, 0, 8, 11, 4, 9, 5, X, X, X, X, X, X, X}},
6980 {{0, 5, 4, 0, 1, 5, 2, 3, 11, X, X, X, X, X, X, X}},
6981 {{2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, X, X, X, X}},
6982 {{10, 3, 11, 10, 1, 3, 9, 5, 4, X, X, X, X, X, X, X}},
6983 {{4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, X, X, X, X}},
6984 {{5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, X, X, X, X}},
6985 {{5, 4, 8, 5, 8, 10, 10, 8, 11, X, X, X, X, X, X, X}},
6986 {{9, 7, 8, 5, 7, 9, X, X, X, X, X, X, X, X, X, X}},
6987 {{9, 3, 0, 9, 5, 3, 5, 7, 3, X, X, X, X, X, X, X}},
6988 {{0, 7, 8, 0, 1, 7, 1, 5, 7, X, X, X, X, X, X, X}},
6989 {{1, 5, 3, 3, 5, 7, X, X, X, X, X, X, X, X, X, X}},
6990 {{9, 7, 8, 9, 5, 7, 10, 1, 2, X, X, X, X, X, X, X}},
6991 {{10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, X, X, X, X}},
6992 {{8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, X, X, X, X}},
6993 {{2, 10, 5, 2, 5, 3, 3, 5, 7, X, X, X, X, X, X, X}},
6994 {{7, 9, 5, 7, 8, 9, 3, 11, 2, X, X, X, X, X, X, X}},
6995 {{9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, X, X, X, X}},
6996 {{2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, X, X, X, X}},
6997 {{11, 2, 1, 11, 1, 7, 7, 1, 5, X, X, X, X, X, X, X}},
6998 {{9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, X, X, X, X}},
6999 {{5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, X}},
7000 {{11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, X}},
7001 {{11, 10, 5, 7, 11, 5, X, X, X, X, X, X, X, X, X, X}},
7002 {{10, 6, 5, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7003 {{0, 8, 3, 5, 10, 6, X, X, X, X, X, X, X, X, X, X}},
7004 {{9, 0, 1, 5, 10, 6, X, X, X, X, X, X, X, X, X, X}},
7005 {{1, 8, 3, 1, 9, 8, 5, 10, 6, X, X, X, X, X, X, X}},
7006 {{1, 6, 5, 2, 6, 1, X, X, X, X, X, X, X, X, X, X}},
7007 {{1, 6, 5, 1, 2, 6, 3, 0, 8, X, X, X, X, X, X, X}},
7008 {{9, 6, 5, 9, 0, 6, 0, 2, 6, X, X, X, X, X, X, X}},
7009 {{5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, X, X, X, X}},
7010 {{2, 3, 11, 10, 6, 5, X, X, X, X, X, X, X, X, X, X}},
7011 {{11, 0, 8, 11, 2, 0, 10, 6, 5, X, X, X, X, X, X, X}},
7012 {{0, 1, 9, 2, 3, 11, 5, 10, 6, X, X, X, X, X, X, X}},
7013 {{5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, X, X, X, X}},
7014 {{6, 3, 11, 6, 5, 3, 5, 1, 3, X, X, X, X, X, X, X}},
7015 {{0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, X, X, X, X}},
7016 {{3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, X, X, X, X}},
7017 {{6, 5, 9, 6, 9, 11, 11, 9, 8, X, X, X, X, X, X, X}},
7018 {{5, 10, 6, 4, 7, 8, X, X, X, X, X, X, X, X, X, X}},
7019 {{4, 3, 0, 4, 7, 3, 6, 5, 10, X, X, X, X, X, X, X}},
7020 {{1, 9, 0, 5, 10, 6, 8, 4, 7, X, X, X, X, X, X, X}},
7021 {{10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, X, X, X, X}},
7022 {{6, 1, 2, 6, 5, 1, 4, 7, 8, X, X, X, X, X, X, X}},
7023 {{1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, X, X, X, X}},
7024 {{8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, X, X, X, X}},
7025 {{7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, X}},
7026 {{3, 11, 2, 7, 8, 4, 10, 6, 5, X, X, X, X, X, X, X}},
7027 {{5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, X, X, X, X}},
7028 {{0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, X, X, X, X}},
7029 {{9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, X}},
7030 {{8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, X, X, X, X}},
7031 {{5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, X}},
7032 {{0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, X}},
7033 {{6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, X, X, X, X}},
7034 {{10, 4, 9, 6, 4, 10, X, X, X, X, X, X, X, X, X, X}},
7035 {{4, 10, 6, 4, 9, 10, 0, 8, 3, X, X, X, X, X, X, X}},
7036 {{10, 0, 1, 10, 6, 0, 6, 4, 0, X, X, X, X, X, X, X}},
7037 {{8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, X, X, X, X}},
7038 {{1, 4, 9, 1, 2, 4, 2, 6, 4, X, X, X, X, X, X, X}},
7039 {{3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, X, X, X, X}},
7040 {{0, 2, 4, 4, 2, 6, X, X, X, X, X, X, X, X, X, X}},
7041 {{8, 3, 2, 8, 2, 4, 4, 2, 6, X, X, X, X, X, X, X}},
7042 {{10, 4, 9, 10, 6, 4, 11, 2, 3, X, X, X, X, X, X, X}},
7043 {{0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, X, X, X, X}},
7044 {{3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, X, X, X, X}},
7045 {{6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, X}},
7046 {{9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, X, X, X, X}},
7047 {{8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, X}},
7048 {{3, 11, 6, 3, 6, 0, 0, 6, 4, X, X, X, X, X, X, X}},
7049 {{6, 4, 8, 11, 6, 8, X, X, X, X, X, X, X, X, X, X}},
7050 {{7, 10, 6, 7, 8, 10, 8, 9, 10, X, X, X, X, X, X, X}},
7051 {{0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, X, X, X, X}},
7052 {{10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, X, X, X, X}},
7053 {{10, 6, 7, 10, 7, 1, 1, 7, 3, X, X, X, X, X, X, X}},
7054 {{1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, X, X, X, X}},
7055 {{2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, X}},
7056 {{7, 8, 0, 7, 0, 6, 6, 0, 2, X, X, X, X, X, X, X}},
7057 {{7, 3, 2, 6, 7, 2, X, X, X, X, X, X, X, X, X, X}},
7058 {{2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, X, X, X, X}},
7059 {{2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, X}},
7060 {{1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, X}},
7061 {{11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, X, X, X, X}},
7062 {{8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, X}},
7063 {{0, 9, 1, 11, 6, 7, X, X, X, X, X, X, X, X, X, X}},
7064 {{7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, X, X, X, X}},
7065 {{7, 11, 6, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7066 {{7, 6, 11, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7067 {{3, 0, 8, 11, 7, 6, X, X, X, X, X, X, X, X, X, X}},
7068 {{0, 1, 9, 11, 7, 6, X, X, X, X, X, X, X, X, X, X}},
7069 {{8, 1, 9, 8, 3, 1, 11, 7, 6, X, X, X, X, X, X, X}},
7070 {{10, 1, 2, 6, 11, 7, X, X, X, X, X, X, X, X, X, X}},
7071 {{1, 2, 10, 3, 0, 8, 6, 11, 7, X, X, X, X, X, X, X}},
7072 {{2, 9, 0, 2, 10, 9, 6, 11, 7, X, X, X, X, X, X, X}},
7073 {{6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, X, X, X, X}},
7074 {{7, 2, 3, 6, 2, 7, X, X, X, X, X, X, X, X, X, X}},
7075 {{7, 0, 8, 7, 6, 0, 6, 2, 0, X, X, X, X, X, X, X}},
7076 {{2, 7, 6, 2, 3, 7, 0, 1, 9, X, X, X, X, X, X, X}},
7077 {{1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, X, X, X, X}},
7078 {{10, 7, 6, 10, 1, 7, 1, 3, 7, X, X, X, X, X, X, X}},
7079 {{10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, X, X, X, X}},
7080 {{0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, X, X, X, X}},
7081 {{7, 6, 10, 7, 10, 8, 8, 10, 9, X, X, X, X, X, X, X}},
7082 {{6, 8, 4, 11, 8, 6, X, X, X, X, X, X, X, X, X, X}},
7083 {{3, 6, 11, 3, 0, 6, 0, 4, 6, X, X, X, X, X, X, X}},
7084 {{8, 6, 11, 8, 4, 6, 9, 0, 1, X, X, X, X, X, X, X}},
7085 {{9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, X, X, X, X}},
7086 {{6, 8, 4, 6, 11, 8, 2, 10, 1, X, X, X, X, X, X, X}},
7087 {{1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, X, X, X, X}},
7088 {{4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, X, X, X, X}},
7089 {{10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, X}},
7090 {{8, 2, 3, 8, 4, 2, 4, 6, 2, X, X, X, X, X, X, X}},
7091 {{0, 4, 2, 4, 6, 2, X, X, X, X, X, X, X, X, X, X}},
7092 {{1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, X, X, X, X}},
7093 {{1, 9, 4, 1, 4, 2, 2, 4, 6, X, X, X, X, X, X, X}},
7094 {{8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, X, X, X, X}},
7095 {{10, 1, 0, 10, 0, 6, 6, 0, 4, X, X, X, X, X, X, X}},
7096 {{4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, X}},
7097 {{10, 9, 4, 6, 10, 4, X, X, X, X, X, X, X, X, X, X}},
7098 {{4, 9, 5, 7, 6, 11, X, X, X, X, X, X, X, X, X, X}},
7099 {{0, 8, 3, 4, 9, 5, 11, 7, 6, X, X, X, X, X, X, X}},
7100 {{5, 0, 1, 5, 4, 0, 7, 6, 11, X, X, X, X, X, X, X}},
7101 {{11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, X, X, X, X}},
7102 {{9, 5, 4, 10, 1, 2, 7, 6, 11, X, X, X, X, X, X, X}},
7103 {{6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, X, X, X, X}},
7104 {{7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, X, X, X, X}},
7105 {{3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, X}},
7106 {{7, 2, 3, 7, 6, 2, 5, 4, 9, X, X, X, X, X, X, X}},
7107 {{9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, X, X, X, X}},
7108 {{3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, X, X, X, X}},
7109 {{6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, X}},
7110 {{9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, X, X, X, X}},
7111 {{1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, X}},
7112 {{4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, X}},
7113 {{7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, X, X, X, X}},
7114 {{6, 9, 5, 6, 11, 9, 11, 8, 9, X, X, X, X, X, X, X}},
7115 {{3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, X, X, X, X}},
7116 {{0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, X, X, X, X}},
7117 {{6, 11, 3, 6, 3, 5, 5, 3, 1, X, X, X, X, X, X, X}},
7118 {{1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, X, X, X, X}},
7119 {{0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, X}},
7120 {{11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, X}},
7121 {{6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, X, X, X, X}},
7122 {{5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, X, X, X, X}},
7123 {{9, 5, 6, 9, 6, 0, 0, 6, 2, X, X, X, X, X, X, X}},
7124 {{1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, X}},
7125 {{1, 5, 6, 2, 1, 6, X, X, X, X, X, X, X, X, X, X}},
7126 {{1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, X}},
7127 {{10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, X, X, X, X}},
7128 {{0, 3, 8, 5, 6, 10, X, X, X, X, X, X, X, X, X, X}},
7129 {{10, 5, 6, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7130 {{11, 5, 10, 7, 5, 11, X, X, X, X, X, X, X, X, X, X}},
7131 {{11, 5, 10, 11, 7, 5, 8, 3, 0, X, X, X, X, X, X, X}},
7132 {{5, 11, 7, 5, 10, 11, 1, 9, 0, X, X, X, X, X, X, X}},
7133 {{10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, X, X, X, X}},
7134 {{11, 1, 2, 11, 7, 1, 7, 5, 1, X, X, X, X, X, X, X}},
7135 {{0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, X, X, X, X}},
7136 {{9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, X, X, X, X}},
7137 {{7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, X}},
7138 {{2, 5, 10, 2, 3, 5, 3, 7, 5, X, X, X, X, X, X, X}},
7139 {{8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, X, X, X, X}},
7140 {{9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, X, X, X, X}},
7141 {{9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, X}},
7142 {{1, 3, 5, 3, 7, 5, X, X, X, X, X, X, X, X, X, X}},
7143 {{0, 8, 7, 0, 7, 1, 1, 7, 5, X, X, X, X, X, X, X}},
7144 {{9, 0, 3, 9, 3, 5, 5, 3, 7, X, X, X, X, X, X, X}},
7145 {{9, 8, 7, 5, 9, 7, X, X, X, X, X, X, X, X, X, X}},
7146 {{5, 8, 4, 5, 10, 8, 10, 11, 8, X, X, X, X, X, X, X}},
7147 {{5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, X, X, X, X}},
7148 {{0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, X, X, X, X}},
7149 {{10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, X}},
7150 {{2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, X, X, X, X}},
7151 {{0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, X}},
7152 {{0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, X}},
7153 {{9, 4, 5, 2, 11, 3, X, X, X, X, X, X, X, X, X, X}},
7154 {{2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, X, X, X, X}},
7155 {{5, 10, 2, 5, 2, 4, 4, 2, 0, X, X, X, X, X, X, X}},
7156 {{3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, X}},
7157 {{5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, X, X, X, X}},
7158 {{8, 4, 5, 8, 5, 3, 3, 5, 1, X, X, X, X, X, X, X}},
7159 {{0, 4, 5, 1, 0, 5, X, X, X, X, X, X, X, X, X, X}},
7160 {{8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, X, X, X, X}},
7161 {{9, 4, 5, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7162 {{4, 11, 7, 4, 9, 11, 9, 10, 11, X, X, X, X, X, X, X}},
7163 {{0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, X, X, X, X}},
7164 {{1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, X, X, X, X}},
7165 {{3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, X}},
7166 {{4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, X, X, X, X}},
7167 {{9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, X}},
7168 {{11, 7, 4, 11, 4, 2, 2, 4, 0, X, X, X, X, X, X, X}},
7169 {{11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, X, X, X, X}},
7170 {{2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, X, X, X, X}},
7171 {{9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, X}},
7172 {{3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, X}},
7173 {{1, 10, 2, 8, 7, 4, X, X, X, X, X, X, X, X, X, X}},
7174 {{4, 9, 1, 4, 1, 7, 7, 1, 3, X, X, X, X, X, X, X}},
7175 {{4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, X, X, X, X}},
7176 {{4, 0, 3, 7, 4, 3, X, X, X, X, X, X, X, X, X, X}},
7177 {{4, 8, 7, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7178 {{9, 10, 8, 10, 11, 8, X, X, X, X, X, X, X, X, X, X}},
7179 {{3, 0, 9, 3, 9, 11, 11, 9, 10, X, X, X, X, X, X, X}},
7180 {{0, 1, 10, 0, 10, 8, 8, 10, 11, X, X, X, X, X, X, X}},
7181 {{3, 1, 10, 11, 3, 10, X, X, X, X, X, X, X, X, X, X}},
7182 {{1, 2, 11, 1, 11, 9, 9, 11, 8, X, X, X, X, X, X, X}},
7183 {{3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, X, X, X, X}},
7184 {{0, 2, 11, 8, 0, 11, X, X, X, X, X, X, X, X, X, X}},
7185 {{3, 2, 11, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7186 {{2, 3, 8, 2, 8, 10, 10, 8, 9, X, X, X, X, X, X, X}},
7187 {{9, 10, 2, 0, 9, 2, X, X, X, X, X, X, X, X, X, X}},
7188 {{2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, X, X, X, X}},
7189 {{1, 10, 2, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7190 {{1, 3, 8, 9, 1, 8, X, X, X, X, X, X, X, X, X, X}},
7191 {{0, 9, 1, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7192 {{0, 3, 8, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7193 {{X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X}}}};
7218 line_to_vertex_table,
7232#include "grid_tools.inst"
bool operator==(const AlignedVector< T > &lhs, const AlignedVector< T > &rhs)
void distribute(VectorType &vec) const
Number side_length(const unsigned int direction) const
void distribute_dofs(const FiniteElement< dim, spacedim > &fe)
types::global_dof_index n_dofs() const
const DerivativeForm< 1, dim, spacedim > & jacobian(const unsigned int quadrature_point) const
double JxW(const unsigned int quadrature_point) const
void reinit(const TriaIterator< DoFCellAccessor< dim, spacedim, level_dof_access > > &cell)
number singular_value(const size_type i) const
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const =0
Abstract base class for mapping classes.
virtual Point< dim > transform_real_to_unit_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< spacedim > &p) const =0
virtual bool preserves_vertex_locations() const =0
virtual boost::container::small_vector< Point< spacedim >, GeometryInfo< dim >::vertices_per_cell > get_vertices(const typename Triangulation< dim, spacedim >::cell_iterator &cell) const
numbers::NumberTraits< Number >::real_type square() const
numbers::NumberTraits< Number >::real_type distance_square(const Point< dim, Number > &p) const
unsigned int size() const
static ReferenceCell n_vertices_to_type(const int dim, const unsigned int n_vertices)
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner)
void copy_from(const size_type n_rows, const size_type n_cols, const ForwardIterator begin, const ForwardIterator end)
numbers::NumberTraits< Number >::real_type norm() const
IteratorState::IteratorStates state() const
virtual MPI_Comm get_communicator() const
unsigned int n_quads() const
void load_user_indices(const std::vector< unsigned int > &v)
bool all_reference_cells_are_hyper_cube() const
face_iterator end_face() const
const std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, std::bitset< 3 > > > & get_periodic_face_map() const
unsigned int n_lines() const
unsigned int n_raw_faces() const
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
unsigned int n_active_cells() const
void refine_global(const unsigned int times=1)
const std::vector< Point< spacedim > > & get_vertices() const
unsigned int n_levels() const
cell_iterator end() const
virtual bool has_hanging_nodes() const
bool vertex_used(const unsigned int index) const
virtual void execute_coarsening_and_refinement()
unsigned int n_cells() const
const std::vector< bool > & get_used_vertices() const
Triangulation< dim, spacedim > & get_triangulation()
unsigned int n_vertices() const
void save_user_indices(std::vector< unsigned int > &v) const
virtual std::vector< types::boundary_id > get_boundary_ids() const
active_face_iterator begin_active_face() const
active_cell_iterator begin_active(const unsigned int level=0) const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
@ update_values
Shape function values.
@ update_JxW_values
Transformed quadrature weights.
@ update_jacobians
Volume element.
@ update_quadrature_points
Transformed quadrature points.
IteratorRange< active_cell_iterator > active_cell_iterators() const
IteratorRange< active_cell_iterator > active_cell_iterators() const
IteratorRange< cell_iterator > cell_iterators_on_level(const unsigned int level) const
static ::ExceptionBase & ExcMeshNotOrientable()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcVertexNotUsed(unsigned int arg1)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcInvalidNumberOfPartitions(int arg1)
static ::ExceptionBase & ExcMessage(std::string arg1)
static ::ExceptionBase & ExcScalingFactorNotPositive(double arg1)
#define AssertThrow(cond, exc)
typename ActiveSelector::active_cell_iterator active_cell_iterator
typename IteratorSelector::line_iterator line_iterator
LinearOperator< Range, Domain, Payload > linear_operator(const OperatorExemplar &, const Matrix &)
void initialize(const MatrixType &A, const AdditionalData ¶meters=AdditionalData())
void reinit(const size_type m, const size_type n, const IndexSet &rowset=IndexSet())
void add(const size_type i, const size_type j)
PackagedOperation< Range > constrained_right_hand_side(const AffineConstraints< typename Range::value_type > &constraints, const LinearOperator< Range, Domain, Payload > &linop, const Range &right_hand_side)
LinearOperator< Range, Domain, Payload > constrained_linear_operator(const AffineConstraints< typename Range::value_type > &constraints, const LinearOperator< Range, Domain, Payload > &linop)
void make_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternType &sparsity_pattern, const AffineConstraints< number > &constraints=AffineConstraints< number >(), const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
RTree< std::pair< BoundingBox< spacedim >, unsigned int > > build_global_description_tree(const std::vector< BoundingBox< spacedim > > &local_description, const MPI_Comm &mpi_communicator)
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
void copy_boundary_to_manifold_id(Triangulation< dim, spacedim > &tria, const bool reset_boundary_ids=false)
void copy_material_to_manifold_id(Triangulation< dim, spacedim > &tria, const bool compute_face_ids=false)
void map_boundary_to_manifold_ids(const std::vector< types::boundary_id > &src_boundary_ids, const std::vector< types::manifold_id > &dst_manifold_ids, Triangulation< dim, spacedim > &tria, const std::vector< types::boundary_id > &reset_boundary_ids={})
virtual std::vector< types::manifold_id > get_manifold_ids() const
std::vector< std::vector< BoundingBox< spacedim > > > exchange_local_bounding_boxes(const std::vector< BoundingBox< spacedim > > &local_bboxes, const MPI_Comm &mpi_communicator)
std::map< unsigned int, std::set<::types::subdomain_id > > compute_vertices_with_ghost_neighbors(const Triangulation< dim, spacedim > &tria)
void collect_coinciding_vertices(const Triangulation< dim, spacedim > &tria, std::map< unsigned int, std::vector< unsigned int > > &coinciding_vertex_groups, std::map< unsigned int, unsigned int > &vertex_to_coinciding_vertex_group)
void set_manifold(const types::manifold_id number, const Manifold< dim, spacedim > &manifold_object)
void assign_co_dimensional_manifold_indicators(Triangulation< dim, spacedim > &tria, const std::function< types::manifold_id(const std::set< types::manifold_id > &)> &disambiguation_function=[](const std::set< types::manifold_id > &manifold_ids) { if(manifold_ids.size()==1) return *manifold_ids.begin();else return numbers::flat_manifold_id;}, bool overwrite_only_flat_manifold_ids=true)
Task< RT > new_task(const std::function< RT()> &function)
@ valid
Iterator points to a valid object.
void create_laplace_matrix(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const Quadrature< dim > &q, SparseMatrixType &matrix, const Function< spacedim, typename SparseMatrixType::value_type > *const a=nullptr, const AffineConstraints< typename SparseMatrixType::value_type > &constraints=AffineConstraints< typename SparseMatrixType::value_type >())
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)
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
std::vector< T > all_gather(const MPI_Comm &comm, const T &object_to_send)
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
T min(const T &t, const MPI_Comm &mpi_communicator)
T sum(const T &t, const MPI_Comm &mpi_communicator)
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
T max(const T &t, const MPI_Comm &mpi_communicator)
constexpr T pow(const T base, const int iexp)
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
static constexpr double PI
const types::boundary_id internal_face_boundary_id
const types::subdomain_id artificial_subdomain_id
static const unsigned int invalid_unsigned_int
const types::manifold_id flat_manifold_id
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
std::uint64_t global_vertex_index
unsigned int subdomain_id
typename internal::ndarray::HelperArray< T, Ns... >::type ndarray
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
boost::geometry::index::rtree< LeafType, IndexType, IndexableGetter > RTree
RTree< typename LeafTypeIterator::value_type, IndexType, IndexableGetter > pack_rtree(const LeafTypeIterator &begin, const LeafTypeIterator &end)
void swap(SmartPointer< T, P > &t1, SmartPointer< T, Q > &t2)
std::vector< unsigned int > vertices
types::manifold_id manifold_id
types::material_id material_id
types::boundary_id boundary_id
static double distance_to_unit_cell(const Point< dim > &p)
static unsigned int line_to_cell_vertices(const unsigned int line, const unsigned int vertex)
static void alternating_form_at_vertices(const Point< spacedim >(&vertices)[vertices_per_cell], Tensor< spacedim - dim, spacedim >(&forms)[vertices_per_cell])
std::vector< CellData< 2 > > boundary_quads
bool check_consistency(const unsigned int dim) const
std::vector< CellData< 1 > > boundary_lines
std::list< typename Triangulation< dim, spacedim >::cell_iterator > distorted_cells
constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
bool operator<(const SynchronousIterators< Iterators > &a, const SynchronousIterators< Iterators > &b)
std::map< unsigned int, unsigned int > vertex_to_coinciding_vertex_group
std::map< unsigned int, std::vector< unsigned int > > coinciding_vertex_groups
const ::Triangulation< dim, spacedim > & tria
#define DEAL_II_VERTEX_INDEX_MPI_TYPE