17#include <deal.II/base/mpi.templates.h>
61#include <boost/random/mersenne_twister.hpp>
62#include <boost/random/uniform_real_distribution.hpp>
72#include <unordered_map>
79 template <
int dim,
int spacedim>
89#if defined(DEAL_II_WITH_P4EST) && defined(DEBUG)
104 std::vector<bool> boundary_vertices(
vertices.size(),
false);
110 for (; cell != endc; ++cell)
111 for (
const unsigned int face : cell->face_indices())
112 if (cell->face(face)->at_boundary())
113 for (
unsigned int i = 0; i < cell->face(face)->n_vertices(); ++i)
114 boundary_vertices[cell->face(face)->vertex_index(i)] =
true;
118 double max_distance_sqr = 0;
119 std::vector<bool>::const_iterator pi = boundary_vertices.begin();
120 const unsigned int N = boundary_vertices.size();
121 for (
unsigned int i = 0; i <
N; ++i, ++pi)
123 std::vector<bool>::const_iterator pj = pi + 1;
124 for (
unsigned int j = i + 1; j <
N; ++j, ++pj)
125 if ((*pi ==
true) && (*pj ==
true) &&
135 template <
int dim,
int spacedim>
141 unsigned int mapping_degree = 1;
144 mapping_degree = p->get_degree();
145 else if (
const auto *p =
147 mapping_degree = p->get_degree();
150 const QGauss<dim> quadrature_formula(mapping_degree + 1);
151 const unsigned int n_q_points = quadrature_formula.
size();
166 double local_volume = 0;
169 for (; cell != endc; ++cell)
170 if (cell->is_locally_owned())
173 for (
unsigned int q = 0; q < n_q_points; ++q)
174 local_volume += fe_values.
JxW(q);
177 double global_volume = 0;
179#ifdef DEAL_II_WITH_MPI
187 global_volume = local_volume;
189 return global_volume;
211 struct TransformR2UAffine
226 [1] = {{-1.000000}, {1.000000}};
230 {1.000000, 0.000000};
241 [2] = {{-0.500000, -0.500000},
242 {0.500000, -0.500000},
243 {-0.500000, 0.500000},
244 {0.500000, 0.500000}};
254 {0.750000, 0.250000, 0.250000, -0.250000};
260 {-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}
286 template <
int dim,
int spacedim>
295 for (
unsigned int d = 0;
d < spacedim; ++
d)
296 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
297 for (
unsigned int e = 0;
e < dim; ++
e)
302 for (
unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
305 return std::make_pair(
A,
b);
322 for (
const auto &cell :
triangulation.active_cell_iterators())
324 if (cell->is_locally_owned())
326 double aspect_ratio_cell = 0.0;
328 fe_values.reinit(cell);
331 for (
unsigned int q = 0; q < quadrature.
size(); ++q)
342 aspect_ratio_cell = std::numeric_limits<double>::infinity();
347 for (
unsigned int i = 0; i < dim; i++)
348 for (
unsigned int j = 0; j < dim; j++)
349 J(i, j) = jacobian[i][j];
355 double const ar = max_sv / min_sv;
362 aspect_ratio_cell =
std::max(aspect_ratio_cell, ar);
367 aspect_ratio_vector(cell->active_cell_index()) = aspect_ratio_cell;
371 return aspect_ratio_vector;
392 template <
int dim,
int spacedim>
398 const auto predicate = [](
const iterator &) {
return true; };
401 tria, std::function<
bool(
const iterator &)>(predicate));
427 template <
int structdim>
451 "Two CellData objects with equal vertices must "
452 "have the same material/boundary ids and manifold "
477 template <
class FaceIteratorType>
482 for (
unsigned int vertex_n = 0; vertex_n < face->n_vertices();
484 face_cell_data.
vertices[vertex_n] = face->vertex_index(vertex_n);
485 face_cell_data.boundary_id = face->boundary_id();
486 face_cell_data.manifold_id = face->manifold_id();
516 template <
class FaceIteratorType>
531 template <
int dim,
int spacedim>
533 tuple<std::vector<Point<spacedim>>, std::vector<CellData<dim>>,
SubCellData>
537 ExcMessage(
"The input triangulation must be non-empty."));
539 std::vector<Point<spacedim>>
vertices;
540 std::vector<CellData<dim>> cells;
542 unsigned int max_level_0_vertex_n = 0;
544 for (
const unsigned int cell_vertex_n : cell->vertex_indices())
545 max_level_0_vertex_n =
546 std::max(cell->vertex_index(cell_vertex_n), max_level_0_vertex_n);
547 vertices.resize(max_level_0_vertex_n + 1);
557 for (
const unsigned int cell_vertex_n : cell->vertex_indices())
561 vertices[cell->vertex_index(cell_vertex_n)] =
562 cell->vertex(cell_vertex_n);
564 cell->vertex_index(cell_vertex_n);
568 cells.push_back(cell_data);
573 for (
const unsigned int face_n : cell->face_indices())
579 for (
unsigned int line_n = 0; line_n < cell->n_lines(); ++line_n)
581 const auto line = cell->line(line_n);
583 for (
unsigned int vertex_n = 0; vertex_n < line->n_vertices();
586 line->vertex_index(vertex_n);
590 line_data.insert(line_cell_data);
598 std::vector<bool> used_vertices(
vertices.size());
600 for (
const auto v : cell_data.vertices)
601 used_vertices[v] =
true;
602 Assert(std::find(used_vertices.begin(), used_vertices.end(),
false) ==
604 ExcMessage(
"The level zero vertices should form a contiguous "
612 for (
const CellData<1> &face_line_data : line_data)
615 return std::tuple<std::vector<Point<spacedim>>,
616 std::vector<CellData<dim>>,
619 std::move(subcell_data));
624 template <
int dim,
int spacedim>
633 "Invalid SubCellData supplied according to ::check_consistency(). "
634 "This is caused by data containing objects for the wrong dimension."));
637 std::vector<bool> vertex_used(
vertices.size(),
false);
638 for (
unsigned int c = 0; c < cells.size(); ++c)
639 for (
unsigned int v = 0; v < cells[c].vertices.size(); ++v)
642 ExcMessage(
"Invalid vertex index encountered! cells[" +
646 " is invalid, because only " +
648 " vertices were supplied."));
649 vertex_used[cells[c].vertices[v]] =
true;
656 std::vector<unsigned int> new_vertex_numbers(
vertices.size(),
658 unsigned int next_free_number = 0;
659 for (
unsigned int i = 0; i <
vertices.size(); ++i)
660 if (vertex_used[i] ==
true)
662 new_vertex_numbers[i] = next_free_number;
667 for (
unsigned int c = 0; c < cells.size(); ++c)
669 v = new_vertex_numbers[v];
674 for (
unsigned int v = 0;
679 new_vertex_numbers.size(),
681 "Invalid vertex index in subcelldata.boundary_lines. "
682 "subcelldata.boundary_lines[" +
687 " is invalid, because only " +
689 " vertices were supplied."));
696 for (
unsigned int v = 0;
701 new_vertex_numbers.size(),
703 "Invalid vertex index in subcelldata.boundary_quads. "
704 "subcelldata.boundary_quads[" +
709 " is invalid, because only " +
711 " vertices were supplied."));
719 std::vector<Point<spacedim>> tmp;
720 tmp.reserve(std::count(vertex_used.begin(), vertex_used.end(),
true));
721 for (
unsigned int v = 0; v <
vertices.size(); ++v)
722 if (vertex_used[v] ==
true)
729 template <
int dim,
int spacedim>
734 std::vector<unsigned int> & considered_vertices,
740 std::vector<unsigned int> new_vertex_numbers(
vertices.size());
741 std::iota(new_vertex_numbers.begin(), new_vertex_numbers.end(), 0);
744 if (considered_vertices.size() == 0)
745 considered_vertices = new_vertex_numbers;
762 unsigned int longest_coordinate_direction = 0;
763 double longest_coordinate_length =
max[0] -
min[0];
764 for (
unsigned int d = 1;
d < spacedim; ++
d)
766 const double coordinate_length =
max[
d] -
min[
d];
767 if (longest_coordinate_length < coordinate_length)
769 longest_coordinate_length = coordinate_length;
770 longest_coordinate_direction =
d;
776 std::vector<std::pair<unsigned int, Point<spacedim>>> sorted_vertices;
777 sorted_vertices.reserve(
vertices.size());
778 for (
const unsigned int vertex_n : considered_vertices)
781 sorted_vertices.emplace_back(vertex_n,
vertices[vertex_n]);
783 std::sort(sorted_vertices.begin(),
784 sorted_vertices.end(),
787 return a.second[longest_coordinate_direction] <
788 b.second[longest_coordinate_direction];
793 for (
unsigned int d = 0;
d < spacedim; ++
d)
801 auto range_start = sorted_vertices.begin();
802 while (range_start != sorted_vertices.end())
804 auto range_end = range_start + 1;
805 while (range_end != sorted_vertices.end() &&
806 std::abs(range_end->second[longest_coordinate_direction] -
807 range_start->second[longest_coordinate_direction]) <
813 std::sort(range_start,
817 return a.first <
b.first;
826 for (
auto reference = range_start; reference != range_end; ++reference)
829 for (
auto it = reference + 1; it != range_end; ++it)
831 if (within_tolerance(reference->second, it->second))
833 new_vertex_numbers[it->first] = reference->first;
839 range_start = range_end;
846 for (
auto &cell : cells)
847 for (
auto &vertex_index : cell.vertices)
848 vertex_index = new_vertex_numbers[vertex_index];
850 for (
auto &vertex_index : quad.vertices)
851 vertex_index = new_vertex_numbers[vertex_index];
853 for (
auto &vertex_index : line.vertices)
854 vertex_index = new_vertex_numbers[vertex_index];
861 template <
int dim,
int spacedim>
869 if (dim == 2 && spacedim == 3)
872 std::size_t n_negative_cells = 0;
873 for (
auto &cell : cells)
875 Assert(cell.vertices.size() ==
876 ReferenceCells::get_hypercube<dim>().n_vertices(),
887 std::swap(cell.vertices[1], cell.vertices[2]);
892 std::swap(cell.vertices[0], cell.vertices[2]);
893 std::swap(cell.vertices[1], cell.vertices[3]);
894 std::swap(cell.vertices[4], cell.vertices[6]);
895 std::swap(cell.vertices[5], cell.vertices[7]);
912 AssertThrow(n_negative_cells == 0 || n_negative_cells == cells.size(),
915 "This function assumes that either all cells have positive "
916 "volume, or that all cells have been specified in an "
917 "inverted vertex order so that their volume is negative. "
918 "(In the latter case, this class automatically inverts "
919 "every cell.) However, the mesh you have specified "
920 "appears to have both cells with positive and cells with "
921 "negative volume. You need to check your mesh which "
922 "cells these are and how they got there.\n"
923 "As a hint, of the total ") +
926 " appear to have a negative volume."));
944 CheapEdge(
const unsigned int v0,
const unsigned int v1)
956 return ((
v0 <
e.v0) || ((
v0 ==
e.v0) && (
v1 <
e.v1)));
979 std::set<CheapEdge> edges;
991 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
993 const CheapEdge reverse_edge(
996 if (edges.find(reverse_edge) != edges.end())
1001 const CheapEdge correct_edge(
1004 edges.insert(correct_edge);
1020 struct ParallelEdges
1034 static const unsigned int
1099 class AdjacentCells;
1107 class AdjacentCells<2>
1114 using const_iterator =
const AdjacentCell *;
1125 push_back(
const AdjacentCell &adjacent_cell)
1189 class AdjacentCells<3> :
public std::vector<AdjacentCell>
1211 Edge(
const CellData<dim> &cell,
const unsigned int edge_number)
1262 enum OrientationStatus
1292 Cell(
const CellData<dim> &c,
const std::vector<Edge<dim>> &edge_list)
1299 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
1301 const Edge<dim>
e(c,
l);
1337 class EdgeDeltaSet<2>
1343 using const_iterator =
const unsigned int *;
1369 insert(
const unsigned int edge_index)
1430 class EdgeDeltaSet<3> :
public std::set<unsigned int>
1440 std::vector<Edge<dim>>
1447 std::vector<Edge<dim>> edge_list;
1449 for (
unsigned int i = 0; i < cells.size(); ++i)
1450 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
1451 edge_list.emplace_back(cells[i],
l);
1454 std::sort(edge_list.begin(), edge_list.end());
1455 edge_list.erase(std::unique(edge_list.begin(), edge_list.end()),
1468 std::vector<Cell<dim>>
1469 build_cells_and_connect_edges(
const std::vector<
CellData<dim>> &cells,
1470 std::vector<Edge<dim>> & edges)
1472 std::vector<Cell<dim>> cell_list;
1473 cell_list.reserve(cells.size());
1474 for (
unsigned int i = 0; i < cells.size(); ++i)
1478 cell_list.emplace_back(cells[i], edges);
1482 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
1483 edges[cell_list.back().edge_indices[
l]].adjacent_cells.push_back(
1484 AdjacentCell(i,
l));
1499 get_next_unoriented_cell(
const std::vector<Cell<dim>> &cells,
1500 const std::vector<Edge<dim>> &edges,
1501 const unsigned int current_cell)
1503 for (
unsigned int c = current_cell; c < cells.size(); ++c)
1504 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
1506 Edge<dim>::not_oriented)
1521 orient_one_set_of_parallel_edges(
const std::vector<Cell<dim>> &cells,
1522 std::vector<Edge<dim>> & edges,
1523 const unsigned int cell,
1524 const unsigned int local_edge)
1551 edges[cells[cell].edge_indices[local_edge]].orientation_status =
1552 (dim == 2 ? Edge<dim>::backward : Edge<dim>::forward);
1568 edges[cells[cell].edge_indices[local_edge]].orientation_status =
1569 (dim == 2 ? Edge<dim>::forward : Edge<dim>::backward);
1578 EdgeDeltaSet<dim> Delta_k;
1579 EdgeDeltaSet<dim> Delta_k_minus_1;
1580 Delta_k_minus_1.insert(cells[cell].
edge_indices[local_edge]);
1582 while (Delta_k_minus_1.begin() !=
1583 Delta_k_minus_1.end())
1587 for (
typename EdgeDeltaSet<dim>::const_iterator delta =
1588 Delta_k_minus_1.begin();
1589 delta != Delta_k_minus_1.end();
1593 Edge<dim>::not_oriented,
1597 for (
typename AdjacentCells<dim>::const_iterator adjacent_cell =
1599 adjacent_cell != edges[*delta].adjacent_cells.end();
1602 const unsigned int K = adjacent_cell->cell_index;
1603 const unsigned int delta_is_edge_in_K =
1604 adjacent_cell->edge_within_cell;
1608 const unsigned int first_edge_vertex =
1609 (edges[*delta].orientation_status == Edge<dim>::forward ?
1610 edges[*delta].vertex_indices[0] :
1611 edges[*delta].vertex_indices[1]);
1612 const unsigned int first_edge_vertex_in_K =
1615 delta_is_edge_in_K, 0)];
1617 first_edge_vertex == first_edge_vertex_in_K ||
1618 first_edge_vertex ==
1620 dim>::line_to_cell_vertices(delta_is_edge_in_K, 1)],
1625 for (
unsigned int o_e = 0;
1632 const unsigned int opposite_edge =
1633 cells[K].edge_indices[ParallelEdges<
1635 const unsigned int first_opposite_edge_vertex =
1636 cells[K].vertex_indices
1640 (first_edge_vertex == first_edge_vertex_in_K ? 0 :
1647 const typename Edge<dim>::OrientationStatus
1648 opposite_edge_orientation =
1649 (edges[opposite_edge].vertex_indices[0] ==
1650 first_opposite_edge_vertex ?
1651 Edge<dim>::forward :
1652 Edge<dim>::backward);
1657 Edge<dim>::not_oriented)
1661 edges[opposite_edge].orientation_status =
1662 opposite_edge_orientation;
1663 Delta_k.insert(opposite_edge);
1679 opposite_edge_orientation,
1685 opposite_edge_orientation)
1698 Delta_k_minus_1 = Delta_k;
1712 rotate_cell(
const std::vector<Cell<dim>> &cell_list,
1713 const std::vector<Edge<dim>> &edge_list,
1720 for (
unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++
e)
1727 starting_vertex_of_edge[
e] =
1731 starting_vertex_of_edge[
e] =
1747 if ((starting_vertex_of_edge[0] == starting_vertex_of_edge[2]) ||
1748 (starting_vertex_of_edge[0] == starting_vertex_of_edge[3]))
1749 origin_vertex_of_cell = starting_vertex_of_edge[0];
1750 else if ((starting_vertex_of_edge[1] ==
1751 starting_vertex_of_edge[2]) ||
1752 (starting_vertex_of_edge[1] ==
1753 starting_vertex_of_edge[3]))
1754 origin_vertex_of_cell = starting_vertex_of_edge[1];
1766 for (origin_vertex_of_cell = 0;
1767 origin_vertex_of_cell < GeometryInfo<dim>::vertices_per_cell;
1768 ++origin_vertex_of_cell)
1769 if (std::count(starting_vertex_of_edge,
1770 starting_vertex_of_edge +
1775 Assert(origin_vertex_of_cell <
1800 const unsigned int tmp = raw_cells[
cell_index].vertices[0];
1823 static const unsigned int cube_permutations[8][8] = {
1824 {0, 1, 2, 3, 4, 5, 6, 7},
1825 {1, 5, 3, 7, 0, 4, 2, 6},
1826 {2, 6, 0, 4, 3, 7, 1, 5},
1827 {3, 2, 1, 0, 7, 6, 5, 4},
1828 {4, 0, 6, 2, 5, 1, 7, 3},
1829 {5, 4, 7, 6, 1, 0, 3, 2},
1830 {6, 7, 4, 5, 2, 3, 0, 1},
1831 {7, 3, 5, 1, 6, 2, 4, 0}};
1836 temp_vertex_indices[v] =
1838 .vertices[cube_permutations[origin_vertex_of_cell][v]];
1840 raw_cells[
cell_index].vertices[v] = temp_vertex_indices[v];
1864 std::vector<Edge<dim>> edge_list = build_edges(cells);
1865 std::vector<Cell<dim>> cell_list =
1866 build_cells_and_connect_edges(cells, edge_list);
1870 unsigned int next_cell_with_unoriented_edge = 0;
1871 while ((next_cell_with_unoriented_edge = get_next_unoriented_cell(
1872 cell_list, edge_list, next_cell_with_unoriented_edge)) !=
1886 for (
unsigned int l = 0;
l < dim; ++
l)
1887 if (edge_list[cell_list[next_cell_with_unoriented_edge]
1890 orient_one_set_of_parallel_edges(
1893 next_cell_with_unoriented_edge,
1898 for (
unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++
l)
1899 Assert(edge_list[cell_list[next_cell_with_unoriented_edge]
1908 for (
unsigned int c = 0; c < cells.size(); ++c)
1909 rotate_cell(cell_list, edge_list, c, cells);
1923 Assert(cells.size() != 0,
1925 "List of elements to orient must have at least one cell"));
1933 if (!is_consistent(cells))
1952 template <
int spacedim>
2001 template <
int spacedim>
2020 template <
int dim,
int spacedim>
2032 const unsigned int axis,
2040 template <
int dim,
int spacedim>
2062 const unsigned int n_dofs = S.
n();
2074 const auto constrained_rhs =
2076 solver.
solve(SF, u, constrained_rhs, prec);
2089 const bool solve_for_absolute_positions)
2117 std::array<AffineConstraints<double>, dim> constraints;
2118 typename std::map<unsigned int, Point<dim>>::const_iterator map_end =
2126 for (
const unsigned int vertex_no : cell->vertex_indices())
2128 const unsigned int vertex_index = cell->vertex_index(vertex_no);
2129 const Point<dim> & vertex_point = cell->vertex(vertex_no);
2131 const typename std::map<unsigned int, Point<dim>>::const_iterator
2132 map_iter = new_points.find(vertex_index);
2134 if (map_iter != map_end)
2135 for (
unsigned int i = 0; i < dim; ++i)
2137 constraints[i].add_line(cell->vertex_dof_index(vertex_no, 0));
2138 constraints[i].set_inhomogeneity(
2139 cell->vertex_dof_index(vertex_no, 0),
2140 (solve_for_absolute_positions ?
2141 map_iter->second(i) :
2142 map_iter->second(i) - vertex_point[i]));
2147 for (
unsigned int i = 0; i < dim; ++i)
2148 constraints[i].close();
2152 for (
unsigned int i = 0; i < dim; ++i)
2157 for (
unsigned int i = 0; i < dim; ++i)
2164 std::vector<bool> vertex_touched(
triangulation.n_vertices(),
false);
2166 for (
const unsigned int vertex_no : cell->vertex_indices())
2167 if (vertex_touched[cell->vertex_index(vertex_no)] ==
false)
2172 cell->vertex_dof_index(vertex_no, 0);
2173 for (
unsigned int i = 0; i < dim; ++i)
2174 if (solve_for_absolute_positions)
2175 v(i) = us[i](dof_index);
2177 v(i) += us[i](dof_index);
2179 vertex_touched[cell->vertex_index(vertex_no)] =
true;
2183 template <
int dim,
int spacedim>
2184 std::map<unsigned int, Point<spacedim>>
2187 std::map<unsigned int, Point<spacedim>> vertex_map;
2191 for (; cell != endc; ++cell)
2193 for (
unsigned int i : cell->face_indices())
2197 if (face->at_boundary())
2199 for (
unsigned j = 0; j < face->
n_vertices(); ++j)
2202 const unsigned int vertex_index = face->vertex_index(j);
2203 vertex_map[vertex_index] = vertex;
2215 template <
int dim,
int spacedim>
2219 const bool keep_boundary,
2220 const unsigned int seed)
2237 double almost_infinite_length = 0;
2242 almost_infinite_length += cell->diameter();
2244 std::vector<double> minimal_length(
triangulation.n_vertices(),
2245 almost_infinite_length);
2248 std::vector<bool> at_boundary(keep_boundary ?
triangulation.n_vertices() :
2253 const bool is_parallel_shared =
2256 for (
const auto &cell :
triangulation.active_cell_iterators())
2257 if (is_parallel_shared || cell->is_locally_owned())
2261 for (
unsigned int i = 0; i < cell->n_lines(); ++i)
2264 line = cell->line(i);
2266 if (keep_boundary && line->at_boundary())
2268 at_boundary[line->vertex_index(0)] =
true;
2269 at_boundary[line->vertex_index(1)] =
true;
2272 minimal_length[line->vertex_index(0)] =
2274 minimal_length[line->vertex_index(0)]);
2275 minimal_length[line->vertex_index(1)] =
2277 minimal_length[line->vertex_index(1)]);
2283 for (
unsigned int vertex = 0; vertex < 2; ++vertex)
2284 if (cell->at_boundary(vertex) ==
true)
2285 at_boundary[cell->vertex_index(vertex)] =
true;
2287 minimal_length[cell->vertex_index(0)] =
2289 minimal_length[cell->vertex_index(0)]);
2290 minimal_length[cell->vertex_index(1)] =
2292 minimal_length[cell->vertex_index(1)]);
2297 boost::random::mt19937 rng(seed);
2298 boost::random::uniform_real_distribution<> uniform_distribution(-1, 1);
2302 if (
auto distributed_triangulation =
2306 const std::vector<bool> locally_owned_vertices =
2308 std::vector<bool> vertex_moved(
triangulation.n_vertices(),
false);
2311 for (
const auto &cell :
triangulation.active_cell_iterators())
2312 if (cell->is_locally_owned())
2314 for (
const unsigned int vertex_no : cell->vertex_indices())
2316 const unsigned global_vertex_no =
2317 cell->vertex_index(vertex_no);
2322 if ((keep_boundary && at_boundary[global_vertex_no]) ||
2323 vertex_moved[global_vertex_no] ||
2324 !locally_owned_vertices[global_vertex_no])
2329 for (
unsigned int d = 0;
d < spacedim; ++
d)
2330 shift_vector(
d) = uniform_distribution(rng);
2332 shift_vector *= factor * minimal_length[global_vertex_no] /
2336 cell->vertex(vertex_no) += shift_vector;
2337 vertex_moved[global_vertex_no] =
true;
2341 distributed_triangulation->communicate_locally_moved_vertices(
2342 locally_owned_vertices);
2352 std::vector<Point<spacedim>> new_vertex_locations(n_vertices);
2353 const std::vector<Point<spacedim>> &old_vertex_locations =
2356 for (
unsigned int vertex = 0; vertex < n_vertices; ++vertex)
2360 if (keep_boundary && at_boundary[vertex])
2361 new_vertex_locations[vertex] = old_vertex_locations[vertex];
2366 for (
unsigned int d = 0;
d < spacedim; ++
d)
2367 shift_vector(
d) = uniform_distribution(rng);
2369 shift_vector *= factor * minimal_length[vertex] /
2373 new_vertex_locations[vertex] =
2374 old_vertex_locations[vertex] + shift_vector;
2379 for (
const auto &cell :
triangulation.active_cell_iterators())
2380 for (
const unsigned int vertex_no : cell->vertex_indices())
2381 cell->vertex(vertex_no) =
2382 new_vertex_locations[cell->vertex_index(vertex_no)];
2398 for (; cell != endc; ++cell)
2399 if (!cell->is_artificial())
2400 for (
const unsigned int face : cell->face_indices())
2401 if (cell->face(face)->has_children() &&
2402 !cell->face(face)->at_boundary())
2406 cell->face(face)->child(0)->vertex(1) =
2407 (cell->face(face)->vertex(0) +
2408 cell->face(face)->vertex(1)) /
2412 cell->face(face)->child(0)->vertex(1) =
2413 .5 * (cell->face(face)->vertex(0) +
2414 cell->face(face)->vertex(1));
2415 cell->face(face)->child(0)->vertex(2) =
2416 .5 * (cell->face(face)->vertex(0) +
2417 cell->face(face)->vertex(2));
2418 cell->face(face)->child(1)->vertex(3) =
2419 .5 * (cell->face(face)->vertex(1) +
2420 cell->face(face)->vertex(3));
2421 cell->face(face)->child(2)->vertex(3) =
2422 .5 * (cell->face(face)->vertex(2) +
2423 cell->face(face)->vertex(3));
2426 cell->face(face)->child(0)->vertex(3) =
2427 .25 * (cell->face(face)->vertex(0) +
2428 cell->face(face)->vertex(1) +
2429 cell->face(face)->vertex(2) +
2430 cell->face(face)->vertex(3));
2438 template <
int dim,
template <
int,
int>
class MeshType,
int spacedim>
2442 const std::vector<bool> & marked_vertices)
2451 marked_vertices.size() == 0,
2453 marked_vertices.size()));
2460 marked_vertices.size() == 0 ||
2461 std::equal(marked_vertices.begin(),
2462 marked_vertices.end(),
2464 [](
bool p,
bool q) { return !p || q; }),
2466 "marked_vertices should be a subset of used vertices in the triangulation "
2467 "but marked_vertices contains one or more vertices that are not used vertices!"));
2471 const std::vector<bool> &vertices_to_use = (marked_vertices.size() == 0) ?
2477 std::vector<bool>::const_iterator
first =
2478 std::find(vertices_to_use.begin(), vertices_to_use.end(),
true);
2483 unsigned int best_vertex = std::distance(vertices_to_use.begin(),
first);
2484 double best_dist = (p -
vertices[best_vertex]).norm_square();
2488 for (
unsigned int j = best_vertex + 1; j <
vertices.size(); j++)
2489 if (vertices_to_use[j])
2491 const double dist = (p -
vertices[j]).norm_square();
2492 if (dist < best_dist)
2504 template <
int dim,
template <
int,
int>
class MeshType,
int spacedim>
2507 const MeshType<dim, spacedim> &mesh,
2509 const std::vector<bool> & marked_vertices)
2522 marked_vertices.size() == 0,
2524 marked_vertices.size()));
2532 marked_vertices.size() == 0 ||
2533 std::equal(marked_vertices.begin(),
2534 marked_vertices.end(),
2536 [](
bool p,
bool q) { return !p || q; }),
2538 "marked_vertices should be a subset of used vertices in the triangulation "
2539 "but marked_vertices contains one or more vertices that are not used vertices!"));
2542 if (marked_vertices.size() != 0)
2545 if (marked_vertices[it->first] ==
false)
2560 template <
int dim,
template <
int,
int>
class MeshType,
int spacedim>
2562 std::vector<typename MeshType<dim, spacedim>::active_cell_iterator>
2565 typename ::internal::
2566 ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>
2569 const unsigned int vertex)
2575 Assert(mesh.get_triangulation().get_used_vertices()[vertex],
2582 ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>
2618 for (
const auto &cell : mesh.active_cell_iterators())
2620 for (
const unsigned int v : cell->vertex_indices())
2621 if (cell->vertex_index(v) == vertex)
2633 for (
const auto face :
2634 cell->reference_cell().faces_for_given_vertex(v))
2635 if (!cell->at_boundary(face) &&
2636 cell->neighbor(face)->is_active())
2658 for (
unsigned int e = 0;
e < cell->n_lines(); ++
e)
2659 if (cell->line(
e)->has_children())
2663 if (cell->line(
e)->child(0)->vertex_index(1) == vertex)
2687 typename ::internal::
2688 ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>(
2694 template <
int dim,
int spacedim>
2695 std::vector<std::vector<Tensor<1, spacedim>>>
2703 const unsigned int n_vertices = vertex_to_cells.size();
2708 std::vector<std::vector<Tensor<1, spacedim>>> vertex_to_cell_centers(
2710 for (
unsigned int vertex = 0; vertex < n_vertices; ++vertex)
2713 const unsigned int n_neighbor_cells = vertex_to_cells[vertex].size();
2714 vertex_to_cell_centers[vertex].resize(n_neighbor_cells);
2716 typename std::set<typename Triangulation<dim, spacedim>::
2717 active_cell_iterator>::iterator it =
2718 vertex_to_cells[vertex].begin();
2719 for (
unsigned int cell = 0; cell < n_neighbor_cells; ++cell, ++it)
2721 vertex_to_cell_centers[vertex][cell] =
2722 (*it)->center() -
vertices[vertex];
2723 vertex_to_cell_centers[vertex][cell] /=
2724 vertex_to_cell_centers[vertex][cell].
norm();
2727 return vertex_to_cell_centers;
2733 template <
int spacedim>
2736 const unsigned int a,
2737 const unsigned int b,
2741 const double scalar_product_a = center_directions[a] * point_direction;
2742 const double scalar_product_b = center_directions[
b] * point_direction;
2747 return (scalar_product_a > scalar_product_b);
2751 template <
int dim,
template <
int,
int>
class MeshType,
int spacedim>
2753 std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
Point<dim>>
2755 std::pair<typename ::internal::
2756 ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type,
2761 const MeshType<dim, spacedim> &mesh,
2764 std::set<
typename MeshType<dim, spacedim>::active_cell_iterator>>
2767 const typename MeshType<dim, spacedim>::active_cell_iterator &cell_hint,
2768 const std::vector<bool> & marked_vertices,
2770 const double tolerance)
2772 std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
2777 std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
2779 cell_and_position_approx;
2781 bool found_cell =
false;
2782 bool approx_cell =
false;
2784 unsigned int closest_vertex_index = 0;
2786 auto current_cell = cell_hint;
2788 while (found_cell ==
false)
2794 const auto cell_vertices = mapping.
get_vertices(current_cell);
2795 const unsigned int closest_vertex =
2796 find_closest_vertex_of_cell<dim, spacedim>(current_cell,
2799 vertex_to_point = p - cell_vertices[closest_vertex];
2800 closest_vertex_index = current_cell->vertex_index(closest_vertex);
2804 if (!used_vertices_rtree.empty())
2807 using ValueType = std::pair<Point<spacedim>,
unsigned int>;
2808 std::function<
bool(
const ValueType &)> marked;
2809 if (marked_vertices.size() == mesh.n_vertices())
2810 marked = [&marked_vertices](
const ValueType &value) ->
bool {
2811 return marked_vertices[value.second];
2814 marked = [](
const ValueType &) ->
bool {
return true; };
2816 std::vector<std::pair<Point<spacedim>,
unsigned int>> res;
2817 used_vertices_rtree.query(
2818 boost::geometry::index::nearest(p, 1) &&
2819 boost::geometry::index::satisfies(marked),
2820 std::back_inserter(res));
2824 closest_vertex_index = res[0].second;
2829 mapping, mesh, p, marked_vertices);
2831 vertex_to_point = p - mesh.get_vertices()[closest_vertex_index];
2834 const double vertex_point_norm = vertex_to_point.
norm();
2835 if (vertex_point_norm > 0)
2836 vertex_to_point /= vertex_point_norm;
2838 const unsigned int n_neighbor_cells =
2839 vertex_to_cells[closest_vertex_index].size();
2842 std::vector<unsigned int> neighbor_permutation(n_neighbor_cells);
2844 for (
unsigned int i = 0; i < n_neighbor_cells; ++i)
2845 neighbor_permutation[i] = i;
2847 auto comp = [&](
const unsigned int a,
const unsigned int b) ->
bool {
2848 return internal::compare_point_association<spacedim>(
2852 vertex_to_cell_centers[closest_vertex_index]);
2855 std::sort(neighbor_permutation.begin(),
2856 neighbor_permutation.end(),
2861 double best_distance = tolerance;
2865 for (
unsigned int i = 0; i < n_neighbor_cells; ++i)
2869 auto cell = vertex_to_cells[closest_vertex_index].begin();
2872 if (!(*cell)->is_artificial())
2879 cell_and_position.first = *cell;
2880 cell_and_position.second = p_unit;
2882 approx_cell =
false;
2891 if (dist < best_distance)
2893 best_distance = dist;
2894 cell_and_position_approx.first = *cell;
2895 cell_and_position_approx.second = p_unit;
2904 if (found_cell ==
true)
2905 return cell_and_position;
2906 else if (approx_cell ==
true)
2907 return cell_and_position_approx;
2923 mapping, mesh, p, marked_vertices, tolerance);
2925 current_cell =
typename MeshType<dim, spacedim>::active_cell_iterator();
2927 return cell_and_position;
2932 template <
int dim,
int spacedim>
2941 unsigned int closest_vertex = 0;
2943 for (
unsigned int v = 1; v < cell->
n_vertices(); ++v)
2946 if (vertex_distance < minimum_distance)
2949 minimum_distance = vertex_distance;
2952 return closest_vertex;
2959 namespace BoundingBoxPredicate
2961 template <
class MeshType>
2962 std::tuple<BoundingBox<MeshType::space_dimension>,
bool>
2964 const typename MeshType::cell_iterator &parent_cell,
2965 const std::function<
2966 bool(
const typename MeshType::active_cell_iterator &)> &predicate)
2968 bool has_predicate =
2970 std::vector<typename MeshType::active_cell_iterator> active_cells;
2971 if (parent_cell->is_active())
2972 active_cells = {parent_cell};
2976 active_cells = get_active_child_cells<MeshType>(parent_cell);
2978 const unsigned int spacedim = MeshType::space_dimension;
2982 while (i < active_cells.size() && !predicate(active_cells[i]))
2986 if (active_cells.size() == 0 || i == active_cells.size())
2989 return std::make_tuple(bbox, has_predicate);
2996 for (; i < active_cells.size(); ++i)
2997 if (predicate(active_cells[i]))
2999 for (
unsigned int d = 0;
d < spacedim; ++
d)
3001 minp[
d] =
std::min(minp[
d], active_cells[i]->vertex(v)[
d]);
3002 maxp[
d] =
std::max(maxp[
d], active_cells[i]->vertex(v)[
d]);
3005 has_predicate =
true;
3007 return std::make_tuple(bbox, has_predicate);
3014 template <
class MeshType>
3015 std::vector<BoundingBox<MeshType::space_dimension>>
3017 const MeshType &mesh,
3018 const std::function<
bool(
const typename MeshType::active_cell_iterator &)>
3020 const unsigned int refinement_level,
3021 const bool allow_merge,
3022 const unsigned int max_boxes)
3029 refinement_level <= mesh.n_levels(),
3031 "Error: refinement level is higher then total levels in the triangulation!"));
3033 const unsigned int spacedim = MeshType::space_dimension;
3034 std::vector<BoundingBox<spacedim>> bounding_boxes;
3038 for (
unsigned int i = 0; i < refinement_level; ++i)
3039 for (
const typename MeshType::cell_iterator &cell :
3040 mesh.active_cell_iterators_on_level(i))
3042 bool has_predicate =
false;
3044 std::tie(bbox, has_predicate) =
3046 MeshType>(cell, predicate);
3048 bounding_boxes.push_back(bbox);
3052 for (
const typename MeshType::cell_iterator &cell :
3053 mesh.cell_iterators_on_level(refinement_level))
3055 bool has_predicate =
false;
3057 std::tie(bbox, has_predicate) =
3059 MeshType>(cell, predicate);
3061 bounding_boxes.push_back(bbox);
3066 return bounding_boxes;
3072 std::vector<unsigned int> merged_boxes_idx;
3073 bool found_neighbors =
true;
3078 while (found_neighbors)
3080 found_neighbors =
false;
3081 for (
unsigned int i = 0; i < bounding_boxes.size() - 1; ++i)
3083 if (std::find(merged_boxes_idx.begin(),
3084 merged_boxes_idx.end(),
3085 i) == merged_boxes_idx.end())
3086 for (
unsigned int j = i + 1; j < bounding_boxes.size(); ++j)
3087 if (std::find(merged_boxes_idx.begin(),
3088 merged_boxes_idx.end(),
3089 j) == merged_boxes_idx.end() &&
3090 bounding_boxes[i].get_neighbor_type(
3091 bounding_boxes[j]) ==
3094 bounding_boxes[i].merge_with(bounding_boxes[j]);
3095 merged_boxes_idx.push_back(j);
3096 found_neighbors =
true;
3102 std::vector<BoundingBox<spacedim>> merged_b_boxes;
3103 for (
unsigned int i = 0; i < bounding_boxes.size(); ++i)
3104 if (std::find(merged_boxes_idx.begin(), merged_boxes_idx.end(), i) ==
3105 merged_boxes_idx.end())
3106 merged_b_boxes.push_back(bounding_boxes[i]);
3111 if ((merged_b_boxes.size() > max_boxes) && (spacedim > 1))
3113 std::vector<double> volumes;
3114 for (
unsigned int i = 0; i < merged_b_boxes.size(); ++i)
3115 volumes.push_back(merged_b_boxes[i].volume());
3117 while (merged_b_boxes.size() > max_boxes)
3119 unsigned int min_idx =
3120 std::min_element(volumes.begin(), volumes.end()) -
3122 volumes.erase(volumes.begin() + min_idx);
3124 bool not_removed =
true;
3125 for (
unsigned int i = 0;
3126 i < merged_b_boxes.size() && not_removed;
3131 if (i != min_idx && (merged_b_boxes[i].get_neighbor_type(
3132 merged_b_boxes[min_idx]) ==
3134 merged_b_boxes[i].get_neighbor_type(
3135 merged_b_boxes[min_idx]) ==
3138 merged_b_boxes[i].merge_with(merged_b_boxes[min_idx]);
3139 merged_b_boxes.erase(merged_b_boxes.begin() + min_idx);
3140 not_removed =
false;
3143 ExcMessage(
"Error: couldn't merge bounding boxes!"));
3146 Assert(merged_b_boxes.size() <= max_boxes,
3148 "Error: couldn't reach target number of bounding boxes!"));
3149 return merged_b_boxes;
3155 template <
int spacedim>
3157 std::tuple<std::vector<std::vector<unsigned int>>,
3158 std::map<unsigned int, unsigned int>,
3159 std::map<unsigned int, std::vector<unsigned int>>>
3167 unsigned int n_procs = global_bboxes.size();
3168 std::vector<std::vector<unsigned int>> point_owners(n_procs);
3169 std::map<unsigned int, unsigned int> map_owners_found;
3170 std::map<unsigned int, std::vector<unsigned int>> map_owners_guessed;
3172 unsigned int n_points = points.size();
3173 for (
unsigned int pt = 0; pt < n_points; ++pt)
3176 std::vector<unsigned int> owners_found;
3178 for (
unsigned int rk = 0; rk < n_procs; ++rk)
3181 if (bbox.point_inside(points[pt]))
3183 point_owners[rk].emplace_back(pt);
3184 owners_found.emplace_back(rk);
3188 Assert(owners_found.size() > 0,
3189 ExcMessage(
"No owners found for the point " +
3191 if (owners_found.size() == 1)
3192 map_owners_found[pt] = owners_found[0];
3195 map_owners_guessed[pt] = owners_found;
3198 return std::make_tuple(std::move(point_owners),
3199 std::move(map_owners_found),
3200 std::move(map_owners_guessed));
3203 template <
int spacedim>
3205 std::tuple<std::map<unsigned int, std::vector<unsigned int>>,
3206 std::map<unsigned int, unsigned int>,
3207 std::map<unsigned int, std::vector<unsigned int>>>
3215 std::map<unsigned int, std::vector<unsigned int>> point_owners;
3216 std::map<unsigned int, unsigned int> map_owners_found;
3217 std::map<unsigned int, std::vector<unsigned int>> map_owners_guessed;
3218 std::vector<std::pair<BoundingBox<spacedim>,
unsigned int>> search_result;
3220 unsigned int n_points = points.size();
3221 for (
unsigned int pt_n = 0; pt_n < n_points; ++pt_n)
3223 search_result.clear();
3226 covering_rtree.query(boost::geometry::index::intersects(points[pt_n]),
3227 std::back_inserter(search_result));
3230 std::set<unsigned int> owners_found;
3232 for (
const auto &rank_bbox : search_result)
3236 const bool pt_inserted = owners_found.insert(pt_n).second;
3238 point_owners[rank_bbox.second].emplace_back(pt_n);
3240 Assert(owners_found.size() > 0,
3241 ExcMessage(
"No owners found for the point " +
3243 if (owners_found.size() == 1)
3244 map_owners_found[pt_n] = *owners_found.begin();
3249 std::back_inserter(map_owners_guessed[pt_n]));
3252 return std::make_tuple(std::move(point_owners),
3253 std::move(map_owners_found),
3254 std::move(map_owners_guessed));
3258 template <
int dim,
int spacedim>
3260 std::set<typename Triangulation<dim, spacedim>::active_cell_iterator>>
3264 std::set<typename Triangulation<dim, spacedim>::active_cell_iterator>>
3269 for (; cell != endc; ++cell)
3270 for (
const unsigned int i : cell->vertex_indices())
3275 for (; cell != endc; ++cell)
3277 for (
unsigned int i : cell->face_indices())
3279 if ((cell->at_boundary(i) ==
false) &&
3280 (cell->neighbor(i)->is_active()))
3283 adjacent_cell = cell->neighbor(i);
3284 for (
unsigned int j = 0; j < cell->face(i)->n_vertices(); ++j)
3293 for (
unsigned int i = 0; i < cell->
n_lines(); ++i)
3294 if (cell->line(i)->has_children())
3308 template <
int dim,
int spacedim>
3309 std::map<unsigned int, types::global_vertex_index>
3313 std::map<unsigned int, types::global_vertex_index>
3314 local_to_global_vertex_index;
3316#ifndef DEAL_II_WITH_MPI
3323 ExcMessage(
"This function does not make any sense "
3324 "for parallel::distributed::Triangulation "
3325 "objects if you do not have MPI enabled."));
3329 using active_cell_iterator =
3331 const std::vector<std::set<active_cell_iterator>> vertex_to_cell =
3336 unsigned int max_cellid_size = 0;
3337 std::set<std::pair<types::subdomain_id, types::global_vertex_index>>
3339 std::map<types::subdomain_id, std::set<unsigned int>> vertices_to_recv;
3347 std::set<active_cell_iterator> missing_vert_cells;
3348 std::set<unsigned int> used_vertex_index;
3349 for (; cell != endc; ++cell)
3351 if (cell->is_locally_owned())
3353 for (
const unsigned int i : cell->vertex_indices())
3356 typename std::set<active_cell_iterator>::iterator
3357 adjacent_cell = vertex_to_cell[cell->vertex_index(i)].begin(),
3358 end_adj_cell = vertex_to_cell[cell->vertex_index(i)].end();
3359 for (; adjacent_cell != end_adj_cell; ++adjacent_cell)
3360 lowest_subdomain_id =
3362 (*adjacent_cell)->subdomain_id());
3365 if (lowest_subdomain_id == cell->subdomain_id())
3369 if (used_vertex_index.find(cell->vertex_index(i)) ==
3370 used_vertex_index.end())
3373 local_to_global_vertex_index[cell->vertex_index(i)] =
3379 vertex_to_cell[cell->vertex_index(i)].begin();
3380 for (; adjacent_cell != end_adj_cell; ++adjacent_cell)
3381 if ((*adjacent_cell)->subdomain_id() !=
3382 cell->subdomain_id())
3386 tmp((*adjacent_cell)->subdomain_id(),
3387 cell->vertex_index(i));
3388 if (vertices_added.find(tmp) ==
3389 vertices_added.end())
3391 vertices_to_send[(*adjacent_cell)
3394 cell->vertex_index(i),
3395 cell->id().to_string());
3396 if (cell->id().to_string().size() >
3399 cell->id().to_string().size();
3400 vertices_added.insert(tmp);
3403 used_vertex_index.insert(cell->vertex_index(i));
3410 vertices_to_recv[lowest_subdomain_id].insert(
3411 cell->vertex_index(i));
3412 missing_vert_cells.insert(cell);
3419 if (cell->is_ghost())
3421 for (
unsigned int i : cell->face_indices())
3423 if (cell->at_boundary(i) ==
false)
3425 if (cell->neighbor(i)->is_active())
3428 spacedim>::active_cell_iterator
3429 adjacent_cell = cell->neighbor(i);
3430 if ((adjacent_cell->is_locally_owned()))
3433 adjacent_cell->subdomain_id();
3434 if (cell->subdomain_id() < adj_subdomain_id)
3435 for (
unsigned int j = 0;
3436 j < cell->face(i)->n_vertices();
3439 vertices_to_recv[cell->subdomain_id()].insert(
3440 cell->face(i)->vertex_index(j));
3441 missing_vert_cells.insert(cell);
3457 int ierr = MPI_Exscan(&next_index,
3465 std::map<unsigned int, types::global_vertex_index>::iterator
3466 global_index_it = local_to_global_vertex_index.begin(),
3467 global_index_end = local_to_global_vertex_index.end();
3468 for (; global_index_it != global_index_end; ++global_index_it)
3469 global_index_it->second +=
shift;
3483 std::vector<std::vector<types::global_vertex_index>> vertices_send_buffers(
3484 vertices_to_send.size());
3485 std::vector<MPI_Request> first_requests(vertices_to_send.size());
3489 std::string>>>::iterator
3490 vert_to_send_it = vertices_to_send.begin(),
3491 vert_to_send_end = vertices_to_send.end();
3492 for (
unsigned int i = 0; vert_to_send_it != vert_to_send_end;
3493 ++vert_to_send_it, ++i)
3495 int destination = vert_to_send_it->first;
3496 const unsigned int n_vertices = vert_to_send_it->second.size();
3497 const int buffer_size = 2 * n_vertices;
3498 vertices_send_buffers[i].resize(buffer_size);
3501 for (
unsigned int j = 0; j < n_vertices; ++j)
3503 vertices_send_buffers[i][2 * j] =
3504 std::get<0>(vert_to_send_it->second[j]);
3505 vertices_send_buffers[i][2 * j + 1] =
3506 local_to_global_vertex_index[std::get<1>(
3507 vert_to_send_it->second[j])];
3511 ierr = MPI_Isend(vertices_send_buffers[i].data(),
3517 &first_requests[i]);
3522 std::vector<std::vector<types::global_vertex_index>> vertices_recv_buffers(
3523 vertices_to_recv.size());
3524 typename std::map<types::subdomain_id, std::set<unsigned int>>::iterator
3525 vert_to_recv_it = vertices_to_recv.begin(),
3526 vert_to_recv_end = vertices_to_recv.end();
3527 for (
unsigned int i = 0; vert_to_recv_it != vert_to_recv_end;
3528 ++vert_to_recv_it, ++i)
3530 int source = vert_to_recv_it->first;
3531 const unsigned int n_vertices = vert_to_recv_it->second.size();
3532 const int buffer_size = 2 * n_vertices;
3533 vertices_recv_buffers[i].resize(buffer_size);
3536 ierr = MPI_Recv(vertices_recv_buffers[i].data(),
3548 std::vector<std::vector<char>> cellids_send_buffers(
3549 vertices_to_send.size());
3550 std::vector<MPI_Request> second_requests(vertices_to_send.size());
3551 vert_to_send_it = vertices_to_send.begin();
3552 for (
unsigned int i = 0; vert_to_send_it != vert_to_send_end;
3553 ++vert_to_send_it, ++i)
3555 int destination = vert_to_send_it->first;
3556 const unsigned int n_vertices = vert_to_send_it->second.size();
3557 const int buffer_size = max_cellid_size * n_vertices;
3558 cellids_send_buffers[i].resize(buffer_size);
3561 unsigned int pos = 0;
3562 for (
unsigned int j = 0; j < n_vertices; ++j)
3564 std::string cell_id = std::get<2>(vert_to_send_it->second[j]);
3565 for (
unsigned int k = 0; k < max_cellid_size; ++k, ++pos)
3567 if (k < cell_id.size())
3568 cellids_send_buffers[i][pos] = cell_id[k];
3572 cellids_send_buffers[i][pos] =
'-';
3577 ierr = MPI_Isend(cellids_send_buffers[i].data(),
3583 &second_requests[i]);
3588 std::vector<std::vector<char>> cellids_recv_buffers(
3589 vertices_to_recv.size());
3590 vert_to_recv_it = vertices_to_recv.begin();
3591 for (
unsigned int i = 0; vert_to_recv_it != vert_to_recv_end;
3592 ++vert_to_recv_it, ++i)
3594 int source = vert_to_recv_it->first;
3595 const unsigned int n_vertices = vert_to_recv_it->second.size();
3596 const int buffer_size = max_cellid_size * n_vertices;
3597 cellids_recv_buffers[i].resize(buffer_size);
3600 ierr = MPI_Recv(cellids_recv_buffers[i].data(),
3612 vert_to_recv_it = vertices_to_recv.begin();
3613 for (
unsigned int i = 0; vert_to_recv_it != vert_to_recv_end;
3614 ++i, ++vert_to_recv_it)
3616 for (
unsigned int j = 0; j < vert_to_recv_it->second.size(); ++j)
3618 const unsigned int local_pos_recv = vertices_recv_buffers[i][2 * j];
3620 vertices_recv_buffers[i][2 * j + 1];
3621 const std::string cellid_recv(
3622 &cellids_recv_buffers[i][max_cellid_size * j],
3623 &cellids_recv_buffers[i][max_cellid_size * j] + max_cellid_size);
3625 typename std::set<active_cell_iterator>::iterator
3626 cell_set_it = missing_vert_cells.begin(),
3627 end_cell_set = missing_vert_cells.end();
3628 for (; (found ==
false) && (cell_set_it != end_cell_set);
3631 typename std::set<active_cell_iterator>::iterator
3633 vertex_to_cell[(*cell_set_it)->vertex_index(i)].begin(),
3635 vertex_to_cell[(*cell_set_it)->vertex_index(i)].end();
3636 for (; candidate_cell != end_cell; ++candidate_cell)
3638 std::string current_cellid =
3639 (*candidate_cell)->id().to_string();
3640 current_cellid.resize(max_cellid_size,
'-');
3641 if (current_cellid.compare(cellid_recv) == 0)
3643 local_to_global_vertex_index
3644 [(*candidate_cell)->vertex_index(local_pos_recv)] =
3656 return local_to_global_vertex_index;
3661 template <
int dim,
int spacedim>
3677 for (
const auto &cell :
triangulation.active_cell_iterators())
3679 const unsigned int index = cell->active_cell_index();
3680 cell_connectivity.
add(index, index);
3681 for (
auto f : cell->face_indices())
3682 if ((cell->at_boundary(f) ==
false) &&
3683 (cell->neighbor(f)->has_children() ==
false))
3685 const unsigned int other_index =
3686 cell->neighbor(f)->active_cell_index();
3687 cell_connectivity.
add(index, other_index);
3688 cell_connectivity.
add(other_index, index);
3695 template <
int dim,
int spacedim>
3701 std::vector<std::vector<unsigned int>> vertex_to_cell(
3703 for (
const auto &cell :
triangulation.active_cell_iterators())
3705 for (
const unsigned int v : cell->vertex_indices())
3706 vertex_to_cell[cell->vertex_index(v)].push_back(
3707 cell->active_cell_index());
3712 for (
const auto &cell :
triangulation.active_cell_iterators())
3714 for (
const unsigned int v : cell->vertex_indices())
3715 for (
unsigned int n = 0;
3716 n < vertex_to_cell[cell->vertex_index(v)].size();
3718 cell_connectivity.
add(cell->active_cell_index(),
3719 vertex_to_cell[cell->vertex_index(v)][n]);
3724 template <
int dim,
int spacedim>
3728 const unsigned int level,
3731 std::vector<std::vector<unsigned int>> vertex_to_cell(
3738 for (
const unsigned int v : cell->vertex_indices())
3739 vertex_to_cell[cell->vertex_index(v)].push_back(cell->index());
3749 for (
const unsigned int v : cell->vertex_indices())
3750 for (
unsigned int n = 0;
3751 n < vertex_to_cell[cell->vertex_index(v)].size();
3753 cell_connectivity.
add(cell->index(),
3754 vertex_to_cell[cell->vertex_index(v)][n]);
3760 template <
int dim,
int spacedim>
3768 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
3769 "are already partitioned implicitly and can not be "
3770 "partitioned again explicitly."));
3772 std::vector<unsigned int> cell_weights;
3782 for (
const auto &cell :
triangulation.active_cell_iterators())
3783 if (cell->is_locally_owned())
3784 cell_weights[cell->active_cell_index()] =
3794 if (
const auto shared_tria =
3798 shared_tria->get_communicator(),
3811 template <
int dim,
int spacedim>
3814 const std::vector<unsigned int> &cell_weights,
3820 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
3821 "are already partitioned implicitly and can not be "
3822 "partitioned again explicitly."));
3826 if (n_partitions == 1)
3828 for (
const auto &cell :
triangulation.active_cell_iterators())
3829 cell->set_subdomain_id(0);
3843 sp_cell_connectivity.
copy_from(cell_connectivity);
3846 sp_cell_connectivity,
3853 template <
int dim,
int spacedim>
3862 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
3863 "are already partitioned implicitly and can not be "
3864 "partitioned again explicitly."));
3866 std::vector<unsigned int> cell_weights;
3876 for (
const auto &cell :
triangulation.active_cell_iterators())
3877 if (cell->is_locally_owned())
3878 cell_weights[cell->active_cell_index()] =
3888 if (
const auto shared_tria =
3892 shared_tria->get_communicator(),
3899 cell_connection_graph,
3906 template <
int dim,
int spacedim>
3909 const std::vector<unsigned int> &cell_weights,
3916 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
3917 "are already partitioned implicitly and can not be "
3918 "partitioned again explicitly."));
3921 ExcMessage(
"Connectivity graph has wrong size"));
3923 ExcMessage(
"Connectivity graph has wrong size"));
3929 if (n_partitions == 1)
3931 for (
const auto &cell :
triangulation.active_cell_iterators())
3932 cell->set_subdomain_id(0);
3940 std::vector<unsigned int> partition_indices(
triangulation.n_active_cells());
3948 for (
const auto &cell :
triangulation.active_cell_iterators())
3949 cell->set_subdomain_id(partition_indices[cell->active_cell_index()]);
3961 unsigned int & current_proc_idx,
3962 unsigned int & current_cell_idx,
3964 const unsigned int n_partitions)
3966 if (cell->is_active())
3968 while (current_cell_idx >=
3970 (current_proc_idx + 1) / n_partitions))
3972 cell->set_subdomain_id(current_proc_idx);
3977 for (
unsigned int n = 0; n < cell->n_children(); ++n)
3987 template <
int dim,
int spacedim>
3991 const bool group_siblings)
3995 ExcMessage(
"Objects of type parallel::distributed::Triangulation "
3996 "are already partitioned implicitly and can not be "
3997 "partitioned again explicitly."));
4004 if (n_partitions == 1)
4006 for (
const auto &cell :
triangulation.active_cell_iterators())
4007 cell->set_subdomain_id(0);
4013 std::vector<types::global_dof_index> coarse_cell_to_p4est_tree_permutation;
4014 std::vector<types::global_dof_index> p4est_tree_to_coarse_cell_permutation;
4020 coarse_cell_to_p4est_tree_permutation.resize(
triangulation.n_cells(0));
4022 coarse_cell_to_p4est_tree_permutation);
4024 p4est_tree_to_coarse_cell_permutation =
4027 unsigned int current_proc_idx = 0;
4028 unsigned int current_cell_idx = 0;
4033 for (
unsigned int idx = 0; idx <
triangulation.n_cells(0); ++idx)
4035 const unsigned int coarse_cell_idx =
4036 p4est_tree_to_coarse_cell_permutation[idx];
4059 for (; cell != endc; ++cell)
4061 if (cell->is_active())
4063 bool all_children_active =
true;
4064 std::map<unsigned int, unsigned int> map_cpu_n_cells;
4065 for (
unsigned int n = 0; n < cell->n_children(); ++n)
4066 if (!cell->child(n)->is_active())
4068 all_children_active =
false;
4072 ++map_cpu_n_cells[cell->child(n)->subdomain_id()];
4074 if (!all_children_active)
4077 unsigned int new_owner = cell->child(0)->subdomain_id();
4078 for (std::map<unsigned int, unsigned int>::iterator it =
4079 map_cpu_n_cells.begin();
4080 it != map_cpu_n_cells.end();
4082 if (it->second > map_cpu_n_cells[new_owner])
4083 new_owner = it->first;
4085 for (
unsigned int n = 0; n < cell->n_children(); ++n)
4086 cell->child(n)->set_subdomain_id(new_owner);
4092 template <
int dim,
int spacedim>
4097 for (
int lvl = n_levels - 1; lvl >= 0; --lvl)
4102 for (; cell != endc; ++cell)
4104 if (cell->is_active())
4105 cell->set_level_subdomain_id(cell->subdomain_id());
4108 Assert(cell->child(0)->level_subdomain_id() !=
4111 cell->set_level_subdomain_id(
4112 cell->child(0)->level_subdomain_id());
4120 template <
int dim,
int spacedim>
4121 std::vector<types::subdomain_id>
4123 const std::vector<CellId> & cell_ids)
4125 std::vector<types::subdomain_id> subdomain_ids;
4126 subdomain_ids.reserve(cell_ids.size());
4135 *parallel_tria =
dynamic_cast<
4139#ifndef DEAL_II_WITH_P4EST
4143 "You are attempting to use a functionality that is only available "
4144 "if deal.II was configured to use p4est, but cmake did not find a "
4145 "valid p4est library."));
4150 for (
const auto &cell_id : cell_ids)
4153 typename ::internal::p4est::types<dim>::quadrant p4est_cell,
4156 ::internal::p4est::init_coarse_quadrant<dim>(p4est_cell);
4157 for (
const auto &child_index : cell_id.get_child_indices())
4159 ::internal::p4est::init_quadrant_children<dim>(
4160 p4est_cell, p4est_children);
4162 p4est_children[
static_cast<unsigned int>(child_index)];
4168 const_cast<typename ::internal::p4est::types<dim>::forest
4169 *
>(parallel_tria->get_p4est()),
4170 cell_id.get_coarse_cell_id(),
4173 parallel_tria->get_communicator()));
4177 subdomain_ids.push_back(owner);
4187 const std::vector<types::subdomain_id> &true_subdomain_ids_of_cells =
4188 shared_tria->get_true_subdomain_ids_of_cells();
4190 for (
const auto &cell_id : cell_ids)
4192 const unsigned int active_cell_index =
4193 shared_tria->create_cell_iterator(cell_id)->active_cell_index();
4194 subdomain_ids.push_back(
4195 true_subdomain_ids_of_cells[active_cell_index]);
4202 for (
const auto &cell_id : cell_ids)
4204 subdomain_ids.push_back(
4205 triangulation.create_cell_iterator(cell_id)->subdomain_id());
4209 return subdomain_ids;
4214 template <
int dim,
int spacedim>
4217 std::vector<types::subdomain_id> & subdomain)
4222 for (
const auto &cell :
triangulation.active_cell_iterators())
4223 subdomain[cell->active_cell_index()] = cell->subdomain_id();
4228 template <
int dim,
int spacedim>
4234 unsigned int count = 0;
4235 for (
const auto &cell :
triangulation.active_cell_iterators())
4236 if (cell->subdomain_id() == subdomain)
4244 template <
int dim,
int spacedim>
4249 std::vector<bool> locally_owned_vertices =
4256 if (
const auto *tr =
dynamic_cast<
4259 for (
const auto &cell :
triangulation.active_cell_iterators())
4260 if (cell->is_artificial() ||
4261 (cell->is_ghost() &&
4262 (cell->subdomain_id() < tr->locally_owned_subdomain())))
4263 for (
const unsigned int v : cell->vertex_indices())
4264 locally_owned_vertices[cell->vertex_index(v)] =
false;
4266 return locally_owned_vertices;
4271 template <
int dim,
int spacedim>
4277 for (
const auto &cell :
triangulation.active_cell_iterators())
4278 if (!cell->is_artificial())
4279 min_diameter =
std::min(min_diameter, cell->diameter(mapping));
4281 double global_min_diameter = 0;
4283#ifdef DEAL_II_WITH_MPI
4287 global_min_diameter =
4291 global_min_diameter = min_diameter;
4293 return global_min_diameter;
4298 template <
int dim,
int spacedim>
4303 double max_diameter = 0.;
4304 for (
const auto &cell :
triangulation.active_cell_iterators())
4305 if (!cell->is_artificial())
4306 max_diameter =
std::max(max_diameter, cell->diameter(mapping));
4308 double global_max_diameter = 0;
4310#ifdef DEAL_II_WITH_MPI
4314 global_max_diameter =
4318 global_max_diameter = max_diameter;
4320 return global_max_diameter;
4327 namespace FixUpDistortedChildCells
4350 template <
typename Iterator,
int spacedim>
4355 const unsigned int structdim =
4356 Iterator::AccessorType::structure_dimension;
4357 Assert(spacedim == Iterator::AccessorType::dimension,
4363 Assert(object->refinement_case() ==
4371 Tensor<spacedim - structdim, spacedim>
4374 for (
const unsigned int i : object->vertex_indices())
4375 parent_vertices[i] =
object->vertex(i);
4378 parent_vertices, parent_alternating_forms);
4380 const Tensor<spacedim - structdim, spacedim>
4381 average_parent_alternating_form =
4382 std::accumulate(parent_alternating_forms,
4383 parent_alternating_forms +
4397 Tensor<spacedim - structdim, spacedim> child_alternating_forms
4401 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4402 for (
const unsigned int i : object->child(c)->vertex_indices())
4403 child_vertices[c][i] =
object->child(c)->vertex(i);
4411 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4413 1] = object_mid_point;
4415 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4417 child_vertices[c], child_alternating_forms[c]);
4429 double objective = 0;
4430 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4431 for (
const unsigned int i : object->child(c)->vertex_indices())
4433 (child_alternating_forms[c][i] -
4434 average_parent_alternating_form /
std::pow(2., 1. * structdim))
4446 template <
typename Iterator>
4449 const unsigned int f,
4450 std::integral_constant<int, 1>)
4452 return object->vertex(f);
4462 template <
typename Iterator>
4465 const unsigned int f,
4466 std::integral_constant<int, 2>)
4468 return object->line(f)->center();
4478 template <
typename Iterator>
4481 const unsigned int f,
4482 std::integral_constant<int, 3>)
4484 return object->face(f)->center();
4511 template <
typename Iterator>
4515 const unsigned int structdim =
4516 Iterator::AccessorType::structure_dimension;
4518 double diameter =
object->diameter();
4519 for (
const unsigned int f : object->face_indices())
4520 for (
unsigned int e = f + 1;
e <
object->n_faces(); ++
e)
4525 std::integral_constant<int, structdim>())
4527 object,
e, std::integral_constant<int, structdim>())));
4538 template <
typename Iterator>
4542 const unsigned int structdim =
4543 Iterator::AccessorType::structure_dimension;
4544 const unsigned int spacedim = Iterator::AccessorType::space_dimension;
4551 Assert(object->refinement_case() ==
4561 unsigned int iteration = 0;
4566 double initial_delta = 0;
4573 const double step_length =
diameter / 4 / (iteration + 1);
4578 for (
unsigned int d = 0;
d < spacedim; ++
d)
4580 const double eps = step_length / 10;
4594 if (gradient.norm() == 0)
4603 std::min(2 * current_value / (gradient * gradient),
4604 step_length / gradient.norm()) *
4609 const double previous_value = current_value;
4613 initial_delta = (previous_value - current_value);
4616 if ((iteration >= 1) &&
4617 ((previous_value - current_value < 0) ||
4618 (
std::fabs(previous_value - current_value) <
4619 0.001 * initial_delta)))
4624 while (iteration < 20);
4640 double old_min_product, new_min_product;
4645 parent_vertices[i] = object->vertex(i);
4647 Tensor<spacedim - structdim, spacedim>
4650 parent_vertices, parent_alternating_forms);
4656 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4657 for (
const unsigned int i : object->child(c)->vertex_indices())
4658 child_vertices[c][i] =
object->child(c)->vertex(i);
4660 Tensor<spacedim - structdim, spacedim> child_alternating_forms
4664 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4666 child_vertices[c], child_alternating_forms[c]);
4669 child_alternating_forms[0][0] * parent_alternating_forms[0];
4670 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4671 for (
const unsigned int i : object->child(c)->vertex_indices())
4672 for (
const unsigned int j : object->vertex_indices())
4673 old_min_product = std::min<double>(old_min_product,
4674 child_alternating_forms[c][i] *
4675 parent_alternating_forms[j]);
4683 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4685 1] = object_mid_point;
4687 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4689 child_vertices[c], child_alternating_forms[c]);
4692 child_alternating_forms[0][0] * parent_alternating_forms[0];
4693 for (
unsigned int c = 0; c <
object->n_children(); ++c)
4694 for (
const unsigned int i : object->child(c)->vertex_indices())
4695 for (
const unsigned int j : object->vertex_indices())
4696 new_min_product = std::min<double>(new_min_product,
4697 child_alternating_forms[c][i] *
4698 parent_alternating_forms[j]);
4706 if (new_min_product >= old_min_product)
4707 object->child(0)->vertex(
4714 return (
std::max(new_min_product, old_min_product) > 0);
4720 template <
int dim,
int spacedim>
4723 const typename ::Triangulation<dim, spacedim>::cell_iterator
4725 std::integral_constant<int, dim>,
4726 std::integral_constant<int, spacedim>)
4736 for (
auto f : cell->face_indices())
4739 Assert(cell->face(f)->refinement_case() ==
4743 bool subface_is_more_refined =
false;
4744 for (
unsigned int g = 0;
4745 g < GeometryInfo<dim>::max_children_per_face;
4747 if (cell->face(f)->child(g)->has_children())
4749 subface_is_more_refined =
true;
4753 if (subface_is_more_refined ==
true)
4764 template <
int dim,
int spacedim>
4772 dim != 1 && spacedim != 1,
4773 "This function is only valid when dim != 1 or spacedim != 1.");
4777 for (
typename std::list<
4779 cell_ptr = distorted_cells.distorted_cells.
begin();
4780 cell_ptr != distorted_cells.distorted_cells.
end();
4786 Assert(!cell->is_active(),
4788 "This function is only valid for a list of cells that "
4789 "have children (i.e., no cell in the list may be active)."));
4793 std::integral_constant<int, dim>(),
4794 std::integral_constant<int, spacedim>());
4798 unfixable_subset.distorted_cells.push_back(cell);
4801 return unfixable_subset;
4806 template <
int dim,
int spacedim>
4809 const bool reset_boundary_ids)
4812 std::vector<types::manifold_id> dst_manifold_ids(src_boundary_ids.size());
4813 auto m_it = dst_manifold_ids.begin();
4814 for (
const auto b : src_boundary_ids)
4819 const std::vector<types::boundary_id> reset_boundary_id =
4820 reset_boundary_ids ?
4821 std::vector<types::boundary_id>(src_boundary_ids.size(), 0) :
4831 template <
int dim,
int spacedim>
4834 const std::vector<types::boundary_id> &src_boundary_ids,
4835 const std::vector<types::manifold_id> &dst_manifold_ids,
4837 const std::vector<types::boundary_id> &reset_boundary_ids_)
4840 const auto reset_boundary_ids =
4841 reset_boundary_ids_.size() ? reset_boundary_ids_ : src_boundary_ids;
4850 for (
auto f : cell->face_indices())
4851 if (cell->face(f)->at_boundary())
4852 for (
unsigned int e = 0;
e < cell->face(f)->n_lines(); ++
e)
4854 const auto bid = cell->face(f)->line(
e)->boundary_id();
4855 const unsigned int ind = std::find(src_boundary_ids.begin(),
4856 src_boundary_ids.end(),
4858 src_boundary_ids.begin();
4859 if (ind < src_boundary_ids.size())
4860 cell->face(f)->line(
e)->set_manifold_id(
4861 dst_manifold_ids[ind]);
4866 for (
auto f : cell->face_indices())
4867 if (cell->face(f)->at_boundary())
4869 const auto bid = cell->face(f)->boundary_id();
4870 const unsigned int ind =
4871 std::find(src_boundary_ids.begin(), src_boundary_ids.end(), bid) -
4872 src_boundary_ids.begin();
4874 if (ind < src_boundary_ids.size())
4877 cell->face(f)->set_manifold_id(dst_manifold_ids[ind]);
4879 cell->face(f)->set_boundary_id(reset_boundary_ids[ind]);
4883 for (
unsigned int e = 0;
e < cell->face(f)->n_lines(); ++
e)
4885 const auto bid = cell->face(f)->line(
e)->boundary_id();
4886 const unsigned int ind = std::find(src_boundary_ids.begin(),
4887 src_boundary_ids.end(),
4889 src_boundary_ids.begin();
4890 if (ind < src_boundary_ids.size())
4891 cell->face(f)->line(
e)->set_boundary_id(
4892 reset_boundary_ids[ind]);
4898 template <
int dim,
int spacedim>
4901 const bool compute_face_ids)
4907 for (; cell != endc; ++cell)
4909 cell->set_manifold_id(cell->material_id());
4910 if (compute_face_ids ==
true)
4912 for (
auto f : cell->face_indices())
4914 if (cell->at_boundary(f) ==
false)
4915 cell->face(f)->set_manifold_id(
4917 cell->neighbor(f)->material_id()));
4919 cell->face(f)->set_manifold_id(cell->material_id());
4926 template <
int dim,
int spacedim>
4931 const std::set<types::manifold_id> &)> &disambiguation_function,
4932 bool overwrite_only_flat_manifold_ids)
4937 const unsigned int n_subobjects =
4941 std::vector<std::set<types::manifold_id>> manifold_ids(n_subobjects + 1);
4942 std::vector<unsigned int> backup;
4946 unsigned next_index = 1;
4950 for (
unsigned int l = 0;
l < cell->n_lines(); ++
l)
4952 if (cell->line(
l)->user_index() == 0)
4955 manifold_ids[next_index].insert(cell->manifold_id());
4956 cell->line(
l)->set_user_index(next_index++);
4959 manifold_ids[cell->line(
l)->user_index()].insert(
4960 cell->manifold_id());
4963 for (
unsigned int l = 0;
l < cell->n_faces(); ++
l)
4965 if (cell->quad(
l)->user_index() == 0)
4968 manifold_ids[next_index].insert(cell->manifold_id());
4969 cell->quad(
l)->set_user_index(next_index++);
4972 manifold_ids[cell->quad(
l)->user_index()].insert(
4973 cell->manifold_id());
4979 for (
unsigned int l = 0;
l < cell->n_lines(); ++
l)
4981 const auto id = cell->line(
l)->user_index();
4985 if (cell->line(
l)->manifold_id() ==
4987 overwrite_only_flat_manifold_ids ==
false)
4988 cell->line(
l)->set_manifold_id(
4989 disambiguation_function(manifold_ids[
id]));
4990 cell->line(
l)->set_user_index(0);
4994 for (
unsigned int l = 0;
l < cell->n_faces(); ++
l)
4996 const auto id = cell->quad(
l)->user_index();
5000 if (cell->quad(
l)->manifold_id() ==
5002 overwrite_only_flat_manifold_ids ==
false)
5003 cell->quad(
l)->set_manifold_id(
5004 disambiguation_function(manifold_ids[
id]));
5005 cell->quad(
l)->set_user_index(0);
5014 template <
int dim,
int spacedim>
5015 std::pair<unsigned int, double>
5019 double max_ratio = 1;
5020 unsigned int index = 0;
5022 for (
unsigned int i = 0; i < dim; ++i)
5023 for (
unsigned int j = i + 1; j < dim; ++j)
5025 unsigned int ax = i % dim;
5026 unsigned int next_ax = j % dim;
5029 cell->extent_in_direction(ax) / cell->extent_in_direction(next_ax);
5031 if (ratio > max_ratio)
5036 else if (1.0 / ratio > max_ratio)
5038 max_ratio = 1.0 / ratio;
5042 return std::make_pair(index, max_ratio);
5046 template <
int dim,
int spacedim>
5049 const bool isotropic,
5050 const unsigned int max_iterations)
5052 unsigned int iter = 0;
5053 bool continue_refinement =
true;
5055 while (continue_refinement && (iter < max_iterations))
5059 continue_refinement =
false;
5062 for (
const unsigned int j : cell->face_indices())
5063 if (cell->at_boundary(j) ==
false &&
5064 cell->neighbor(j)->has_children())
5068 cell->set_refine_flag();
5069 continue_refinement =
true;
5072 continue_refinement |= cell->flag_for_face_refinement(j);
5079 template <
int dim,
int spacedim>
5082 const double max_ratio,
5083 const unsigned int max_iterations)
5085 unsigned int iter = 0;
5086 bool continue_refinement =
true;
5088 while (continue_refinement && (iter < max_iterations))
5091 continue_refinement =
false;
5094 std::pair<unsigned int, double> info =
5095 GridTools::get_longest_direction<dim, spacedim>(cell);
5096 if (info.second > max_ratio)
5098 cell->set_refine_flag(
5100 continue_refinement =
true;
5108 template <
int dim,
int spacedim>
5111 const double limit_angle_fraction)
5119 "have hanging nodes."));
5122 bool has_cells_with_more_than_dim_faces_on_boundary =
true;
5123 bool has_cells_with_dim_faces_on_boundary =
false;
5125 unsigned int refinement_cycles = 0;
5127 while (has_cells_with_more_than_dim_faces_on_boundary)
5129 has_cells_with_more_than_dim_faces_on_boundary =
false;
5133 unsigned int boundary_face_counter = 0;
5134 for (
auto f : cell->face_indices())
5135 if (cell->face(f)->at_boundary())
5136 boundary_face_counter++;
5137 if (boundary_face_counter > dim)
5139 has_cells_with_more_than_dim_faces_on_boundary =
true;
5142 else if (boundary_face_counter == dim)
5143 has_cells_with_dim_faces_on_boundary =
true;
5145 if (has_cells_with_more_than_dim_faces_on_boundary)
5148 refinement_cycles++;
5152 if (has_cells_with_dim_faces_on_boundary)
5155 refinement_cycles++;
5159 while (refinement_cycles > 0)
5162 cell->set_coarsen_flag();
5164 refinement_cycles--;
5172 std::vector<bool> faces_to_remove(tria.
n_raw_faces(),
false);
5174 std::vector<CellData<dim>> cells_to_add;
5178 const unsigned int v0 = 0,
v1 = 1, v2 = (dim > 1 ? 2 : 0),
5179 v3 = (dim > 1 ? 3 : 0);
5183 double angle_fraction = 0;
5189 p0[spacedim > 1 ? 1 : 0] = 1;
5193 if (cell->face(
v0)->at_boundary() && cell->face(v3)->at_boundary())
5195 p0 = cell->vertex(
v0) - cell->vertex(v2);
5196 p1 = cell->vertex(v3) - cell->vertex(v2);
5197 vertex_at_corner = v2;
5199 else if (cell->face(v3)->at_boundary() &&
5200 cell->face(
v1)->at_boundary())
5202 p0 = cell->vertex(v2) - cell->vertex(v3);
5203 p1 = cell->vertex(
v1) - cell->vertex(v3);
5204 vertex_at_corner = v3;
5206 else if (cell->face(1)->at_boundary() &&
5207 cell->face(2)->at_boundary())
5209 p0 = cell->vertex(
v0) - cell->vertex(
v1);
5210 p1 = cell->vertex(v3) - cell->vertex(
v1);
5211 vertex_at_corner =
v1;
5213 else if (cell->face(2)->at_boundary() &&
5214 cell->face(0)->at_boundary())
5216 p0 = cell->vertex(v2) - cell->vertex(
v0);
5217 p1 = cell->vertex(
v1) - cell->vertex(
v0);
5218 vertex_at_corner =
v0;
5229 if (angle_fraction > limit_angle_fraction)
5231 auto flags_removal = [&](
unsigned int f1,
5234 unsigned int n2) ->
void {
5235 cells_to_remove[cell->active_cell_index()] =
true;
5236 cells_to_remove[cell->neighbor(n1)->active_cell_index()] =
true;
5237 cells_to_remove[cell->neighbor(n2)->active_cell_index()] =
true;
5239 faces_to_remove[cell->face(f1)->index()] =
true;
5240 faces_to_remove[cell->face(f2)->index()] =
true;
5242 faces_to_remove[cell->neighbor(n1)->face(f1)->index()] =
true;
5243 faces_to_remove[cell->neighbor(n2)->face(f2)->index()] =
true;
5246 auto cell_creation = [&](
const unsigned int vv0,
5247 const unsigned int vv1,
5248 const unsigned int f0,
5249 const unsigned int f1,
5251 const unsigned int n0,
5252 const unsigned int v0n0,
5253 const unsigned int v1n0,
5255 const unsigned int n1,
5256 const unsigned int v0n1,
5257 const unsigned int v1n1) {
5263 c1.
vertices[v2] = cell->neighbor(n0)->vertex_index(v0n0);
5264 c1.
vertices[v3] = cell->neighbor(n0)->vertex_index(v1n0);
5270 c2.
vertices[
v1] = cell->neighbor(n1)->vertex_index(v0n1);
5271 c2.
vertices[v2] = cell->vertex_index(vv1);
5272 c2.
vertices[v3] = cell->neighbor(n1)->vertex_index(v1n1);
5277 l1.
vertices[0] = cell->vertex_index(vv0);
5278 l1.
vertices[1] = cell->neighbor(n0)->vertex_index(v0n0);
5284 l2.
vertices[0] = cell->vertex_index(vv0);
5285 l2.
vertices[1] = cell->neighbor(n1)->vertex_index(v0n1);
5291 cells_to_add.push_back(c1);
5292 cells_to_add.push_back(c2);
5297 switch (vertex_at_corner)
5300 flags_removal(0, 2, 3, 1);
5301 cell_creation(0, 3, 0, 2, 3, 2, 3, 1, 1, 3);
5304 flags_removal(1, 2, 3, 0);
5305 cell_creation(1, 2, 2, 1, 0, 0, 2, 3, 3, 2);
5308 flags_removal(3, 0, 1, 2);
5309 cell_creation(2, 1, 3, 0, 1, 3, 1, 2, 0, 1);
5312 flags_removal(3, 1, 0, 2);
5313 cell_creation(3, 0, 1, 3, 2, 1, 0, 0, 2, 0);
5326 if (cells_to_add.size() == 0)
5328 while (refinement_cycles > 0)
5331 cell->set_coarsen_flag();
5333 refinement_cycles--;
5341 if (cells_to_remove[cell->active_cell_index()] ==
false)
5344 for (
const unsigned int v : cell->vertex_indices())
5345 c.
vertices[v] = cell->vertex_index(v);
5348 cells_to_add.push_back(c);
5356 for (; face != endf; ++face)
5357 if ((face->at_boundary() ||
5359 faces_to_remove[face->index()] ==
false)
5361 for (
unsigned int l = 0;
l < face->
n_lines(); ++
l)
5366 for (
const unsigned int v : face->vertex_indices())
5367 line.
vertices[v] = face->vertex_index(v);
5373 for (
const unsigned int v : face->line(
l)->vertex_indices())
5374 line.
vertices[v] = face->line(
l)->vertex_index(v);
5383 for (
const unsigned int v : face->vertex_indices())
5384 quad.
vertices[v] = face->vertex_index(v);
5392 subcelldata_to_add);
5397 std::map<types::manifold_id, std::unique_ptr<Manifold<dim, spacedim>>>
5416 template <
int dim,
int spacedim>
5419 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
5420 std::vector<std::vector<Point<dim>>>,
5421 std::vector<std::vector<unsigned int>>>
5433 auto &cells = std::get<0>(cqmp);
5434 auto &qpoints = std::get<1>(cqmp);
5435 auto &maps = std::get<2>(cqmp);
5437 return std::make_tuple(std::move(cells),
5444 template <
int dim,
int spacedim>
5447 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
5448 std::vector<std::vector<Point<dim>>>,
5449 std::vector<std::vector<unsigned int>>,
5450 std::vector<unsigned int>>
5460 Assert((dim == spacedim),
5461 ExcMessage(
"Only implemented for dim==spacedim."));
5470 const unsigned int np = points.size();
5472 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>
5474 std::vector<std::vector<Point<dim>>> qpoints_out;
5475 std::vector<std::vector<unsigned int>> maps_out;
5476 std::vector<unsigned int> missing_points_out;
5480 return std::make_tuple(std::move(cells_out),
5481 std::move(qpoints_out),
5482 std::move(maps_out),
5483 std::move(missing_points_out));
5491 std::vector<std::pair<Point<spacedim>,
unsigned int>> points_and_ids(np);
5492 for (
unsigned int i = 0; i < np; ++i)
5493 points_and_ids[i] = std::make_pair(points[i], i);
5494 const auto p_tree =
pack_rtree(points_and_ids);
5497 std::vector<bool> found_points(points.size(),
false);
5500 const auto already_found = [&found_points](
const auto &id) {
5502 return found_points[
id.second];
5508 const auto store_cell_point_and_id =
5512 const unsigned int &id) {
5513 const auto it = std::find(cells_out.rbegin(), cells_out.rend(), cell);
5514 if (it != cells_out.rend())
5516 const auto cell_id =
5517 (cells_out.size() - 1 - (it - cells_out.rbegin()));
5518 qpoints_out[cell_id].emplace_back(ref_point);
5519 maps_out[cell_id].emplace_back(
id);
5523 cells_out.emplace_back(cell);
5524 qpoints_out.emplace_back(std::vector<
Point<dim>>({ref_point}));
5525 maps_out.emplace_back(std::vector<unsigned int>({
id}));
5530 const auto check_all_points_within_box = [&](
const auto &leaf) {
5531 const auto &box = leaf.first;
5532 const auto &cell_hint = leaf.second;
5534 for (
const auto &point_and_id :
5535 p_tree | bgi::adaptors::queried(!bgi::satisfies(already_found) &&
5536 bgi::intersects(box)))
5538 const auto id = point_and_id.second;
5539 const auto cell_and_ref =
5543 const auto &cell = cell_and_ref.first;
5544 const auto &ref_point = cell_and_ref.second;
5547 store_cell_point_and_id(cell, ref_point,
id);
5549 missing_points_out.emplace_back(
id);
5552 found_points[id] =
true;
5558 check_all_points_within_box(
5559 std::make_pair(mapping.get_bounding_box(cell_hint), cell_hint));
5562 for (
unsigned int i = 0; i < np; ++i)
5563 if (found_points[i] ==
false)
5566 const auto leaf = b_tree.qbegin(bgi::nearest(points[i], 1));
5568 if (leaf != b_tree.qend())
5569 check_all_points_within_box(*leaf);
5577 for (
unsigned int i = 0; i < np; ++i)
5578 if (found_points[i] ==
false)
5579 missing_points_out.emplace_back(i);
5586 unsigned int c = cells_out.size();
5587 unsigned int qps = 0;
5593 for (
unsigned int n = 0; n < c; ++n)
5596 qps += qpoints_out[n].size();
5599 Assert(qps + missing_points_out.size() == np,
5603 return std::make_tuple(std::move(cells_out),
5604 std::move(qpoints_out),
5605 std::move(maps_out),
5606 std::move(missing_points_out));
5611 template <
int dim,
int spacedim>
5614 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
5615 std::vector<std::vector<Point<dim>>>,
5616 std::vector<std::vector<unsigned int>>,
5617 std::vector<std::vector<Point<spacedim>>>,
5618 std::vector<std::vector<unsigned int>>>
5626 const double tolerance)
5630 cache, points, global_bboxes, tolerance,
false)
5635 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
5636 std::vector<std::vector<Point<dim>>>,
5637 std::vector<std::vector<unsigned int>>,
5638 std::vector<std::vector<Point<spacedim>>>,
5639 std::vector<std::vector<unsigned int>>>
5642 std::pair<int, int> dummy{-1, -1};
5644 for (
unsigned int i = 0; i < all.size(); ++i)
5646 if (dummy != std::get<0>(all[i]))
5648 std::get<0>(result).push_back(
5651 std::get<0>(all[i]).
first,
5652 std::get<0>(all[i]).
second});
5654 const unsigned int new_size = std::get<0>(result).size();
5656 std::get<1>(result).resize(new_size);
5657 std::get<2>(result).resize(new_size);
5658 std::get<3>(result).resize(new_size);
5659 std::get<4>(result).resize(new_size);
5661 dummy = std::get<0>(all[i]);
5664 std::get<1>(result).back().push_back(
5665 std::get<3>(all[i]));
5666 std::get<2>(result).back().push_back(std::get<2>(all[i]));
5667 std::get<3>(result).back().push_back(std::get<4>(all[i]));
5668 std::get<4>(result).back().push_back(std::get<1>(all[i]));
5678 template <
int spacedim>
5679 std::tuple<std::vector<unsigned int>,
5680 std::vector<unsigned int>,
5681 std::vector<unsigned int>>
5686 std::vector<std::pair<unsigned int, unsigned int>> ranks_and_indices;
5687 ranks_and_indices.reserve(points.size());
5689 for (
unsigned int i = 0; i < points.size(); ++i)
5691 const auto &
point = points[i];
5692 for (
unsigned rank = 0; rank < global_bboxes.size(); ++rank)
5693 for (
const auto &box : global_bboxes[rank])
5694 if (box.point_inside(
point))
5696 ranks_and_indices.emplace_back(rank, i);
5702 std::sort(ranks_and_indices.begin(), ranks_and_indices.end());
5704 std::vector<unsigned int> ranks;
5705 std::vector<unsigned int> ptr;
5706 std::vector<unsigned int> indices;
5710 for (
const auto &i : ranks_and_indices)
5712 if (dummy_rank != i.first)
5714 dummy_rank = i.first;
5715 ranks.push_back(dummy_rank);
5716 ptr.push_back(indices.size());
5719 indices.push_back(i.second);
5721 ptr.push_back(indices.size());
5723 return std::make_tuple(std::move(ranks),
5725 std::move(indices));
5730 template <
int dim,
int spacedim>
5732 std::pair<typename Triangulation<dim, spacedim>::active_cell_iterator,
5738 const std::vector<bool> &marked_vertices,
5739 const double tolerance)
5742 std::pair<typename Triangulation<dim, spacedim>::active_cell_iterator,
5744 locally_owned_active_cells_around_point;
5747 cache,
point, cell_hint, marked_vertices, tolerance);
5749 cell_hint = first_cell.first;
5752 const auto active_cells_around_point =
5760 locally_owned_active_cells_around_point.reserve(
5761 active_cells_around_point.size());
5763 for (
const auto &cell : active_cells_around_point)
5764 if (cell.first->is_locally_owned())
5765 locally_owned_active_cells_around_point.push_back(cell);
5768 std::sort(locally_owned_active_cells_around_point.begin(),
5769 locally_owned_active_cells_around_point.end(),
5770 [](
const auto &a,
const auto &
b) { return a.first < b.first; });
5772 return locally_owned_active_cells_around_point;
5777 template <
int dim,
int spacedim>
5778 DistributedComputePointLocationsInternal<dim, spacedim>
5783 const double tolerance,
5784 const bool perform_handshake,
5785 const bool enforce_unique_mapping)
5798 const auto potential_owners =
5801 const auto &potential_owners_ranks = std::get<0>(potential_owners);
5802 const auto &potential_owners_ptrs = std::get<1>(potential_owners);
5803 const auto &potential_owners_indices = std::get<2>(potential_owners);
5805 const std::vector<bool> marked_vertices;
5808 const auto translate = [&](
const unsigned int other_rank) {
5809 const auto ptr = std::find(potential_owners_ranks.begin(),
5810 potential_owners_ranks.end(),
5815 const auto other_rank_index =
5816 std::distance(potential_owners_ranks.begin(), ptr);
5818 return other_rank_index;
5822 [&]() {
return potential_owners_ranks; },
5823 [&](
const unsigned int other_rank, std::vector<char> &send_buffer) {
5824 const auto other_rank_index = translate(other_rank);
5826 std::vector<std::pair<unsigned int, Point<spacedim>>> temp;
5827 temp.reserve(potential_owners_ptrs[other_rank_index + 1] -
5828 potential_owners_ptrs[other_rank_index]);
5830 for (
unsigned int i = potential_owners_ptrs[other_rank_index];
5831 i < potential_owners_ptrs[other_rank_index + 1];
5833 temp.emplace_back(potential_owners_indices[i],
5834 points[potential_owners_indices[i]]);
5838 [&](
const unsigned int & other_rank,
5839 const std::vector<char> &recv_buffer,
5840 std::vector<char> & request_buffer) {
5842 std::vector<std::pair<unsigned int, Point<spacedim>>>>(recv_buffer,
5845 std::vector<unsigned int> request_buffer_temp(
5846 recv_buffer_unpacked.size(), 0);
5850 for (
unsigned int i = 0; i < recv_buffer_unpacked.size(); ++i)
5852 const auto &index_and_point = recv_buffer_unpacked[i];
5854 const auto cells_and_reference_positions =
5857 index_and_point.second,
5862 for (
const auto &cell_and_reference_position :
5863 cells_and_reference_positions)
5865 send_components.emplace_back(
5866 std::pair<int, int>(
5867 cell_and_reference_position.first->level(),
5868 cell_and_reference_position.first->index()),
5870 index_and_point.first,
5871 cell_and_reference_position.second,
5872 index_and_point.second,
5875 if (enforce_unique_mapping)
5880 if (perform_handshake)
5881 request_buffer_temp[i] =
5882 enforce_unique_mapping ?
5883 std::min<unsigned int>(
5884 1, cells_and_reference_positions.size()) :
5885 cells_and_reference_positions.size();
5888 if (perform_handshake)
5891 [&](
const unsigned int other_rank, std::vector<char> &recv_buffer) {
5892 if (perform_handshake)
5894 const auto other_rank_index = translate(other_rank);
5898 potential_owners_ptrs[other_rank_index + 1] -
5899 potential_owners_ptrs[other_rank_index]),
5903 [&](
const unsigned int other_rank,
5904 const std::vector<char> &recv_buffer) {
5905 if (perform_handshake)
5907 const auto recv_buffer_unpacked =
5908 Utilities::unpack<std::vector<unsigned int>>(recv_buffer,
5911 const auto other_rank_index = translate(other_rank);
5913 for (
unsigned int i = 0; i < recv_buffer_unpacked.size(); ++i)
5914 for (
unsigned int j = 0; j < recv_buffer_unpacked[i]; ++j)
5915 recv_components.emplace_back(
5917 potential_owners_indices
5918 [i + potential_owners_ptrs[other_rank_index]],
5929 if (enforce_unique_mapping)
5931 std::vector<unsigned int> mask_recv(recv_components.size());
5932 std::vector<unsigned int> mask_send(send_components.size());
5937 auto recv_components_copy = recv_components;
5938 recv_components.clear();
5940 for (
unsigned int i = 0; i < recv_components_copy.size(); ++i)
5941 std::get<2>(recv_components_copy[i]) = i;
5943 std::sort(recv_components_copy.begin(),
5944 recv_components_copy.end(),
5945 [&](
const auto &a,
const auto &
b) {
5946 if (std::get<0>(a) != std::get<0>(b))
5947 return std::get<0>(a) < std::get<0>(b);
5949 return std::get<2>(a) < std::get<2>(b);
5952 std::vector<bool> unique(points.size(),
false);
5954 std::vector<unsigned int> recv_ranks;
5955 std::vector<unsigned int> recv_ptrs;
5958 i < recv_components_copy.size();
5961 if (dummy != std::get<0>(recv_components_copy[i]))
5963 dummy = std::get<0>(recv_components_copy[i]);
5964 recv_ranks.push_back(dummy);
5965 recv_ptrs.push_back(i);
5968 if (unique[std::get<1>(recv_components_copy[i])] ==
false)
5970 recv_components.emplace_back(recv_components_copy[i]);
5972 unique[std::get<1>(recv_components_copy[i])] =
true;
5979 recv_ptrs.push_back(recv_components_copy.size());
5981 Assert(std::all_of(unique.begin(),
5983 [](
const auto &v) { return v; }),
5989 auto send_components_copy = send_components;
5990 send_components.clear();
5992 for (
unsigned int i = 0; i < send_components_copy.size(); ++i)
5993 std::get<5>(send_components_copy[i]) = i;
5995 std::sort(send_components_copy.begin(),
5996 send_components_copy.end(),
5997 [&](
const auto &a,
const auto &
b) {
5998 if (std::get<1>(a) != std::get<1>(b))
5999 return std::get<1>(a) < std::get<1>(b);
6001 return std::get<5>(a) < std::get<5>(b);
6004 std::vector<unsigned int> send_ranks;
6005 std::vector<unsigned int> send_ptrs;
6008 i < send_components_copy.size();
6011 if (dummy != std::get<1>(send_components_copy[i]))
6013 dummy = std::get<1>(send_components_copy[i]);
6014 send_ranks.push_back(dummy);
6015 send_ptrs.push_back(i);
6018 send_ptrs.push_back(send_components_copy.size());
6021#ifdef DEAL_II_WITH_MPI
6022 std::vector<MPI_Request> req(send_ranks.size() + recv_ranks.size());
6024 for (
unsigned int i = 0; i < send_ranks.size(); ++i)
6027 MPI_Irecv(mask_send.data() + send_ptrs[i],
6028 send_ptrs[i + 1] - send_ptrs[i],
6038 for (
unsigned int i = 0; i < recv_ranks.size(); ++i)
6041 MPI_Isend(mask_recv.data() + recv_ptrs[i],
6042 recv_ptrs[i + 1] - recv_ptrs[i],
6048 &req[i] + send_ranks.size());
6052 auto ierr = MPI_Waitall(req.size(), req.data(), MPI_STATUSES_IGNORE);
6055 mask_send = mask_recv;
6059 for (
unsigned int i = 0; i < send_components_copy.size(); ++i)
6060 if (mask_send[i] == 1)
6061 send_components.emplace_back(send_components_copy[i]);
6068 std::sort(send_components.begin(),
6069 send_components.end(),
6070 [&](
const auto &a,
const auto &
b) {
6071 if (std::get<1>(a) != std::get<1>(b))
6072 return std::get<1>(a) < std::get<1>(b);
6074 if (std::get<2>(a) != std::get<2>(b))
6075 return std::get<2>(a) < std::get<2>(b);
6077 return std::get<0>(a) < std::get<0>(b);
6082 i < send_components.size();
6085 std::get<5>(send_components[i]) = i;
6087 if (dummy != std::get<1>(send_components[i]))
6089 dummy = std::get<1>(send_components[i]);
6090 send_ranks.push_back(dummy);
6091 send_ptrs.push_back(i);
6094 send_ptrs.push_back(send_components.size());
6098 std::sort(send_components.begin(),
6099 send_components.end(),
6100 [&](
const auto &a,
const auto &
b) {
6101 if (std::get<0>(a) != std::get<0>(b))
6102 return std::get<0>(a) < std::get<0>(b);
6104 if (std::get<1>(a) != std::get<1>(b))
6105 return std::get<1>(a) < std::get<1>(b);
6107 if (std::get<2>(a) != std::get<2>(b))
6108 return std::get<2>(a) < std::get<2>(b);
6110 return std::get<5>(a) < std::get<5>(b);
6114 if (perform_handshake)
6117 std::sort(recv_components.begin(),
6118 recv_components.end(),
6119 [&](
const auto &a,
const auto &
b) {
6120 if (std::get<0>(a) != std::get<0>(b))
6121 return std::get<0>(a) < std::get<0>(b);
6123 return std::get<1>(a) < std::get<1>(b);
6128 i < recv_components.size();
6131 std::get<2>(recv_components[i]) = i;
6133 if (dummy != std::get<0>(recv_components[i]))
6135 dummy = std::get<0>(recv_components[i]);
6136 recv_ranks.push_back(dummy);
6137 recv_ptrs.push_back(i);
6140 recv_ptrs.push_back(recv_components.size());
6144 std::sort(recv_components.begin(),
6145 recv_components.end(),
6146 [&](
const auto &a,
const auto &
b) {
6147 if (std::get<1>(a) != std::get<1>(b))
6148 return std::get<1>(a) < std::get<1>(b);
6150 if (std::get<0>(a) != std::get<0>(b))
6151 return std::get<0>(a) < std::get<0>(b);
6153 return std::get<2>(a) < std::get<2>(b);
6163 template <
int dim,
int spacedim>
6164 std::map<unsigned int, Point<spacedim>>
6168 std::map<unsigned int, Point<spacedim>> result;
6171 if (!cell->is_artificial())
6174 for (
unsigned int i = 0; i < vs.size(); ++i)
6175 result[cell->vertex_index(i)] = vs[i];
6182 template <
int spacedim>
6187 auto id_and_v = std::min_element(
6192 return p1.second.distance(p) < p2.second.distance(p);
6194 return id_and_v->first;
6198 template <
int dim,
int spacedim>
6199 std::pair<typename Triangulation<dim, spacedim>::active_cell_iterator,
6206 const std::vector<bool> &marked_vertices,
6207 const double tolerance)
6212 const auto &vertex_to_cell_centers =
6220 vertex_to_cell_centers,
6223 used_vertices_rtree,
6227 template <
int spacedim>
6228 std::vector<std::vector<BoundingBox<spacedim>>>
6233#ifndef DEAL_II_WITH_MPI
6235 (void)mpi_communicator;
6238 "GridTools::exchange_local_bounding_boxes() requires MPI."));
6242 unsigned int n_bboxes = local_bboxes.size();
6244 int n_local_data = 2 * spacedim * n_bboxes;
6246 std::vector<double> loc_data_array(n_local_data);
6247 for (
unsigned int i = 0; i < n_bboxes; ++i)
6248 for (
unsigned int d = 0;
d < spacedim; ++
d)
6251 loc_data_array[2 * i * spacedim +
d] =
6252 local_bboxes[i].get_boundary_points().first[
d];
6253 loc_data_array[2 * i * spacedim + spacedim +
d] =
6254 local_bboxes[i].get_boundary_points().second[
d];
6261 std::vector<int> size_all_data(n_procs);
6264 int ierr = MPI_Allgather(&n_local_data,
6267 size_all_data.data(),
6275 std::vector<int> rdispls(n_procs);
6277 for (
unsigned int i = 1; i < n_procs; ++i)
6278 rdispls[i] = rdispls[i - 1] + size_all_data[i - 1];
6282 std::vector<double> data_array(rdispls.back() + size_all_data.back());
6284 ierr = MPI_Allgatherv(loc_data_array.data(),
6288 size_all_data.data(),
6295 std::vector<std::vector<BoundingBox<spacedim>>> global_bboxes(n_procs);
6296 unsigned int begin_idx = 0;
6297 for (
unsigned int i = 0; i < n_procs; ++i)
6300 unsigned int n_bbox_i = size_all_data[i] / (spacedim * 2);
6301 global_bboxes[i].resize(n_bbox_i);
6302 for (
unsigned int bbox = 0; bbox < n_bbox_i; ++bbox)
6305 for (
unsigned int d = 0;
d < spacedim; ++
d)
6307 p1[
d] = data_array[begin_idx + 2 * bbox * spacedim +
d];
6309 data_array[begin_idx + 2 * bbox * spacedim + spacedim +
d];
6312 global_bboxes[i][bbox] = loc_bbox;
6315 begin_idx += size_all_data[i];
6317 return global_bboxes;
6323 template <
int spacedim>
6329#ifndef DEAL_II_WITH_MPI
6330 (void)mpi_communicator;
6332 std::vector<std::pair<BoundingBox<spacedim>,
unsigned int>> boxes_index(
6333 local_description.size());
6335 for (
unsigned int i = 0; i < local_description.size(); ++i)
6336 boxes_index[i] = std::make_pair(local_description[i], 0u);
6340 const std::vector<std::vector<BoundingBox<spacedim>>> global_bboxes =
6344 const unsigned int n_procs =
6348 std::vector<unsigned int> bboxes_position(n_procs);
6350 unsigned int tot_bboxes = 0;
6351 for (
const auto &process_bboxes : global_bboxes)
6352 tot_bboxes += process_bboxes.size();
6355 std::vector<std::pair<BoundingBox<spacedim>,
unsigned int>>
6357 flat_global_bboxes.reserve(tot_bboxes);
6358 unsigned int process_index = 0;
6359 for (
const auto &process_bboxes : global_bboxes)
6362 std::vector<std::pair<BoundingBox<spacedim>,
unsigned int>>
6363 boxes_and_indices(process_bboxes.size());
6366 for (
unsigned int i = 0; i < process_bboxes.size(); ++i)
6367 boxes_and_indices[i] =
6368 std::make_pair(process_bboxes[i], process_index);
6370 flat_global_bboxes.insert(flat_global_bboxes.end(),
6371 boxes_and_indices.begin(),
6372 boxes_and_indices.end());
6380 flat_global_bboxes.begin(), flat_global_bboxes.end());
6386 template <
int dim,
int spacedim>
6390 std::map<
unsigned int, std::vector<unsigned int>> &coinciding_vertex_groups,
6391 std::map<unsigned int, unsigned int> &vertex_to_coinciding_vertex_group)
6396 static const int lookup_table_2d[2][2] =
6403 static const int lookup_table_3d[2][2][2][4] =
6425 if (pair.first.first->level() != pair.second.first.first->level())
6428 const auto face_a = pair.first.first->face(pair.first.second);
6430 pair.second.first.first->face(pair.second.first.second);
6431 const auto mask = pair.second.second;
6436 for (
unsigned int i = 0; i < face_a->n_vertices(); ++i)
6438 const bool face_orientation = mask[0];
6439 const bool face_flip = mask[1];
6440 const bool face_rotation = mask[2];
6450 j = lookup_table_2d[face_flip][i];
6453 j = lookup_table_3d[face_orientation][face_flip]
6461 const auto vertex_a = face_a->vertex_index(i);
6462 const auto vertex_b = face_b->vertex_index(j);
6463 unsigned int temp =
std::min(vertex_a, vertex_b);
6465 auto it_a = vertex_to_coinciding_vertex_group.find(vertex_a);
6466 if (it_a != vertex_to_coinciding_vertex_group.end())
6467 temp =
std::min(temp, it_a->second);
6469 auto it_b = vertex_to_coinciding_vertex_group.find(vertex_b);
6470 if (it_b != vertex_to_coinciding_vertex_group.end())
6471 temp =
std::min(temp, it_b->second);
6473 if (it_a != vertex_to_coinciding_vertex_group.end())
6474 it_a->second = temp;
6476 vertex_to_coinciding_vertex_group[vertex_a] = temp;
6478 if (it_b != vertex_to_coinciding_vertex_group.end())
6479 it_b->second = temp;
6481 vertex_to_coinciding_vertex_group[vertex_b] = temp;
6487 for (
auto &p : vertex_to_coinciding_vertex_group)
6489 if (p.first == p.second)
6491 unsigned int temp = p.second;
6492 while (temp != vertex_to_coinciding_vertex_group[temp])
6493 temp = vertex_to_coinciding_vertex_group[temp];
6499 for (
auto p : vertex_to_coinciding_vertex_group)
6500 coinciding_vertex_groups[p.second] = {};
6502 for (
auto p : vertex_to_coinciding_vertex_group)
6503 coinciding_vertex_groups[p.second].push_back(p.first);
6509 template <
int dim,
int spacedim>
6510 std::map<unsigned int, std::set<::types::subdomain_id>>
6520 std::map<unsigned int, std::vector<unsigned int>> coinciding_vertex_groups;
6521 std::map<unsigned int, unsigned int> vertex_to_coinciding_vertex_group;
6524 coinciding_vertex_groups,
6525 vertex_to_coinciding_vertex_group);
6528 std::vector<bool> vertex_of_own_cell(tria.
n_vertices(),
false);
6530 if (cell->is_locally_owned())
6531 for (
const unsigned int v : cell->vertex_indices())
6532 vertex_of_own_cell[cell->vertex_index(v)] =
true;
6536 std::map<unsigned int, std::set<types::subdomain_id>> result;
6540 if (cell->is_ghost())
6545 for (
const unsigned int v : cell->vertex_indices())
6548 if (vertex_of_own_cell[cell->vertex_index(v)])
6549 result[cell->vertex_index(v)].insert(owner);
6552 auto coinciding_vertex_group =
6553 vertex_to_coinciding_vertex_group.find(cell->vertex_index(v));
6554 if (coinciding_vertex_group !=
6555 vertex_to_coinciding_vertex_group.end())
6556 for (
auto coinciding_vertex :
6557 coinciding_vertex_groups[coinciding_vertex_group->second])
6558 if (vertex_of_own_cell[coinciding_vertex])
6559 result[coinciding_vertex].insert(owner);
6568 template <
int dim,
typename VectorType>
6572 const unsigned int n_subdivisions,
6573 const double tolerance)
6574 : n_subdivisions(n_subdivisions)
6575 , tolerance(tolerance)
6576 , fe_values(mapping,
6578 create_quadrature_rule(n_subdivisions),
6584 template <
int dim,
typename VectorType>
6587 const unsigned int n_subdivisions)
6593 for (
unsigned int j = 0; j <= n_subdivisions; ++j)
6594 for (
unsigned int i = 0; i <= n_subdivisions; ++i)
6596 1.0 / n_subdivisions * j);
6600 for (
unsigned int k = 0; k <= n_subdivisions; ++k)
6601 for (
unsigned int j = 0; j <= n_subdivisions; ++j)
6602 for (
unsigned int i = 0; i <= n_subdivisions; ++i)
6604 1.0 / n_subdivisions * j,
6605 1.0 / n_subdivisions * k);
6614 template <
int dim,
typename VectorType>
6618 const VectorType & ls_vector,
6619 const double iso_level,
6624 if (cell->is_locally_owned())
6625 process_cell(cell, ls_vector, iso_level,
vertices, cells);
6630 template <
int dim,
typename VectorType>
6634 const VectorType & ls_vector,
6635 const double iso_level,
6639 std::vector<value_type> ls_values;
6641 fe_values.reinit(cell);
6642 ls_values.resize(fe_values.n_quadrature_points);
6643 fe_values.get_function_values(ls_vector, ls_values);
6645 ls_values, fe_values.get_quadrature_points(), iso_level,
vertices, cells);
6650 template <
int dim,
typename VectorType>
6653 std::vector<value_type> & ls_values,
6655 const double iso_level,
6659 const unsigned p = n_subdivisions + 1;
6663 for (
unsigned int j = 0; j < n_subdivisions; ++j)
6664 for (
unsigned int i = 0; i < n_subdivisions; ++i)
6666 std::vector<unsigned int> mask{p * (j + 0) + (i + 0),
6667 p * (j + 0) + (i + 1),
6668 p * (j + 1) + (i + 1),
6669 p * (j + 1) + (i + 0)};
6672 ls_values, points, mask, iso_level,
vertices, cells);
6677 for (
unsigned int k = 0; k < n_subdivisions; ++k)
6678 for (
unsigned int j = 0; j < n_subdivisions; ++j)
6679 for (
unsigned int i = 0; i < n_subdivisions; ++i)
6681 std::vector<unsigned int> mask{
6682 p * p * (k + 0) + p * (j + 0) + (i + 0),
6683 p * p * (k + 0) + p * (j + 0) + (i + 1),
6684 p * p * (k + 0) + p * (j + 1) + (i + 1),
6685 p * p * (k + 0) + p * (j + 1) + (i + 0),
6686 p * p * (k + 1) + p * (j + 0) + (i + 0),
6687 p * p * (k + 1) + p * (j + 0) + (i + 1),
6688 p * p * (k + 1) + p * (j + 1) + (i + 1),
6689 p * p * (k + 1) + p * (j + 1) + (i + 0)};
6692 ls_values, points, mask, iso_level,
vertices, cells);
6702 unsigned int n_vertices,
6703 unsigned int n_sub_vertices,
6704 unsigned int n_configurations,
6705 unsigned int n_lines,
6706 unsigned int n_cols,
6707 typename value_type>
6710 const std::array<unsigned int, n_configurations> & cut_line_table,
6713 const std::vector<value_type> & ls_values,
6715 const std::vector<unsigned int> & mask,
6716 const double iso_level,
6717 const double tolerance,
6723 constexpr unsigned int X =
static_cast<unsigned int>(-1);
6726 unsigned int configuration = 0;
6727 for (
unsigned int v = 0; v < n_vertices; ++v)
6728 if (ls_values[mask[v]] < iso_level)
6729 configuration |= (1 << v);
6732 if (cut_line_table[configuration] == 0)
6737 const auto interpolate = [&](
const unsigned int i,
const unsigned int j) {
6738 if (
std::abs(iso_level - ls_values[mask[i]]) < tolerance)
6739 return points[mask[i]];
6740 if (
std::abs(iso_level - ls_values[mask[j]]) < tolerance)
6741 return points[mask[j]];
6742 if (
std::abs(ls_values[mask[i]] - ls_values[mask[j]]) < tolerance)
6743 return points[mask[i]];
6745 const double mu = (iso_level - ls_values[mask[i]]) /
6746 (ls_values[mask[j]] - ls_values[mask[i]]);
6749 mu * (points[mask[j]] - points[mask[i]]));
6753 std::array<Point<dim>, n_lines> vertex_list_all;
6754 for (
unsigned int l = 0;
l < n_lines; ++
l)
6755 if (cut_line_table[configuration] & (1 <<
l))
6756 vertex_list_all[
l] =
6757 interpolate(line_to_vertex_table[
l][0], line_to_vertex_table[
l][1]);
6760 unsigned int local_vertex_count = 0;
6761 std::array<Point<dim>, n_lines> vertex_list_reduced;
6762 std::array<unsigned int, n_lines> local_remap;
6763 std::fill(local_remap.begin(), local_remap.end(), X);
6764 for (
int i = 0; new_line_table[configuration][i] != X; i++)
6765 if (local_remap[new_line_table[configuration][i]] == X)
6767 vertex_list_reduced[local_vertex_count] =
6768 vertex_list_all[new_line_table[configuration][i]];
6769 local_remap[new_line_table[configuration][i]] = local_vertex_count;
6770 local_vertex_count++;
6774 const unsigned int n_vertices_old =
vertices.size();
6775 for (
unsigned int i = 0; i < local_vertex_count; i++)
6776 vertices.push_back(vertex_list_reduced[i]);
6779 for (
unsigned int i = 0; new_line_table[configuration][i] != X;
6780 i += n_sub_vertices)
6782 cells.resize(cells.size() + 1);
6783 cells.back().vertices.resize(n_sub_vertices);
6785 for (
unsigned int v = 0; v < n_sub_vertices; ++v)
6786 cells.back().vertices[v] =
6787 local_remap[new_line_table[configuration][i + v]] +
6795 template <
int dim,
typename VectorType>
6798 const std::vector<value_type> & ls_values,
6799 const std::vector<
Point<2>> & points,
6800 const std::vector<unsigned int> mask,
6801 const double iso_level,
6806 constexpr unsigned int n_vertices = 4;
6807 constexpr unsigned int n_sub_vertices = 2;
6808 constexpr unsigned int n_lines = 4;
6809 constexpr unsigned int n_configurations =
Utilities::pow(2, n_vertices);
6810 constexpr unsigned int X =
static_cast<unsigned int>(-1);
6814 constexpr std::array<unsigned int, n_configurations> cut_line_table = {
6850 {{X, X, X, X, X}}}};
6854 {{{0, 3}}, {{1, 2}}, {{0, 1}}, {{3, 2}}}};
6864 line_to_vertex_table,
6876 template <
int dim,
typename VectorType>
6879 const std::vector<value_type> & ls_values,
6880 const std::vector<
Point<3>> & points,
6881 const std::vector<unsigned int> mask,
6882 const double iso_level,
6887 constexpr unsigned int n_vertices = 8;
6888 constexpr unsigned int n_sub_vertices = 3;
6889 constexpr unsigned int n_lines = 12;
6890 constexpr unsigned int n_configurations =
Utilities::pow(2, n_vertices);
6891 constexpr unsigned int X =
static_cast<unsigned int>(-1);
6896 constexpr std::array<unsigned int, n_configurations> cut_line_table = {{
6897 0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905,
6898 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x99, 0x393, 0x29a,
6899 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93,
6900 0xf99, 0xe90, 0x230, 0x339, 0x33, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
6901 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 0x3a0, 0x2a9,
6902 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6,
6903 0xfaa, 0xea3, 0xda9, 0xca0, 0x460, 0x569, 0x663, 0x76a, 0x66, 0x16f,
6904 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
6905 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff, 0x3f5, 0x2fc, 0xdfc, 0xcf5,
6906 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 0x650, 0x759, 0x453, 0x55a,
6907 0x256, 0x35f, 0x55, 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53,
6908 0x859, 0x950, 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc,
6909 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 0x8c0, 0x9c9,
6910 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc, 0x1c5, 0x2cf, 0x3c6,
6911 0x4ca, 0x5c3, 0x6c9, 0x7c0, 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f,
6912 0xf55, 0xe5c, 0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
6913 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5,
6914 0xff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 0xb60, 0xa69, 0x963, 0x86a,
6915 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663,
6916 0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
6917 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0, 0xd30, 0xc39,
6918 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636,
6919 0x13a, 0x33, 0x339, 0x230, 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f,
6920 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99, 0x190,
6921 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605,
6922 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0}};
6928 {{{X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6929 {{0, 8, 3, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6930 {{0, 1, 9, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6931 {{1, 8, 3, 9, 8, 1, X, X, X, X, X, X, X, X, X, X}},
6932 {{1, 2, 10, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6933 {{0, 8, 3, 1, 2, 10, X, X, X, X, X, X, X, X, X, X}},
6934 {{9, 2, 10, 0, 2, 9, X, X, X, X, X, X, X, X, X, X}},
6935 {{2, 8, 3, 2, 10, 8, 10, 9, 8, X, X, X, X, X, X, X}},
6936 {{3, 11, 2, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6937 {{0, 11, 2, 8, 11, 0, X, X, X, X, X, X, X, X, X, X}},
6938 {{1, 9, 0, 2, 3, 11, X, X, X, X, X, X, X, X, X, X}},
6939 {{1, 11, 2, 1, 9, 11, 9, 8, 11, X, X, X, X, X, X, X}},
6940 {{3, 10, 1, 11, 10, 3, X, X, X, X, X, X, X, X, X, X}},
6941 {{0, 10, 1, 0, 8, 10, 8, 11, 10, X, X, X, X, X, X, X}},
6942 {{3, 9, 0, 3, 11, 9, 11, 10, 9, X, X, X, X, X, X, X}},
6943 {{9, 8, 10, 10, 8, 11, X, X, X, X, X, X, X, X, X, X}},
6944 {{4, 7, 8, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6945 {{4, 3, 0, 7, 3, 4, X, X, X, X, X, X, X, X, X, X}},
6946 {{0, 1, 9, 8, 4, 7, X, X, X, X, X, X, X, X, X, X}},
6947 {{4, 1, 9, 4, 7, 1, 7, 3, 1, X, X, X, X, X, X, X}},
6948 {{1, 2, 10, 8, 4, 7, X, X, X, X, X, X, X, X, X, X}},
6949 {{3, 4, 7, 3, 0, 4, 1, 2, 10, X, X, X, X, X, X, X}},
6950 {{9, 2, 10, 9, 0, 2, 8, 4, 7, X, X, X, X, X, X, X}},
6951 {{2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, X, X, X, X}},
6952 {{8, 4, 7, 3, 11, 2, X, X, X, X, X, X, X, X, X, X}},
6953 {{11, 4, 7, 11, 2, 4, 2, 0, 4, X, X, X, X, X, X, X}},
6954 {{9, 0, 1, 8, 4, 7, 2, 3, 11, X, X, X, X, X, X, X}},
6955 {{4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, X, X, X, X}},
6956 {{3, 10, 1, 3, 11, 10, 7, 8, 4, X, X, X, X, X, X, X}},
6957 {{1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, X, X, X, X}},
6958 {{4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, X, X, X, X}},
6959 {{4, 7, 11, 4, 11, 9, 9, 11, 10, X, X, X, X, X, X, X}},
6960 {{9, 5, 4, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6961 {{9, 5, 4, 0, 8, 3, X, X, X, X, X, X, X, X, X, X}},
6962 {{0, 5, 4, 1, 5, 0, X, X, X, X, X, X, X, X, X, X}},
6963 {{8, 5, 4, 8, 3, 5, 3, 1, 5, X, X, X, X, X, X, X}},
6964 {{1, 2, 10, 9, 5, 4, X, X, X, X, X, X, X, X, X, X}},
6965 {{3, 0, 8, 1, 2, 10, 4, 9, 5, X, X, X, X, X, X, X}},
6966 {{5, 2, 10, 5, 4, 2, 4, 0, 2, X, X, X, X, X, X, X}},
6967 {{2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, X, X, X, X}},
6968 {{9, 5, 4, 2, 3, 11, X, X, X, X, X, X, X, X, X, X}},
6969 {{0, 11, 2, 0, 8, 11, 4, 9, 5, X, X, X, X, X, X, X}},
6970 {{0, 5, 4, 0, 1, 5, 2, 3, 11, X, X, X, X, X, X, X}},
6971 {{2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, X, X, X, X}},
6972 {{10, 3, 11, 10, 1, 3, 9, 5, 4, X, X, X, X, X, X, X}},
6973 {{4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, X, X, X, X}},
6974 {{5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, X, X, X, X}},
6975 {{5, 4, 8, 5, 8, 10, 10, 8, 11, X, X, X, X, X, X, X}},
6976 {{9, 7, 8, 5, 7, 9, X, X, X, X, X, X, X, X, X, X}},
6977 {{9, 3, 0, 9, 5, 3, 5, 7, 3, X, X, X, X, X, X, X}},
6978 {{0, 7, 8, 0, 1, 7, 1, 5, 7, X, X, X, X, X, X, X}},
6979 {{1, 5, 3, 3, 5, 7, X, X, X, X, X, X, X, X, X, X}},
6980 {{9, 7, 8, 9, 5, 7, 10, 1, 2, X, X, X, X, X, X, X}},
6981 {{10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, X, X, X, X}},
6982 {{8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, X, X, X, X}},
6983 {{2, 10, 5, 2, 5, 3, 3, 5, 7, X, X, X, X, X, X, X}},
6984 {{7, 9, 5, 7, 8, 9, 3, 11, 2, X, X, X, X, X, X, X}},
6985 {{9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, X, X, X, X}},
6986 {{2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, X, X, X, X}},
6987 {{11, 2, 1, 11, 1, 7, 7, 1, 5, X, X, X, X, X, X, X}},
6988 {{9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, X, X, X, X}},
6989 {{5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, X}},
6990 {{11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, X}},
6991 {{11, 10, 5, 7, 11, 5, X, X, X, X, X, X, X, X, X, X}},
6992 {{10, 6, 5, X, X, X, X, X, X, X, X, X, X, X, X, X}},
6993 {{0, 8, 3, 5, 10, 6, X, X, X, X, X, X, X, X, X, X}},
6994 {{9, 0, 1, 5, 10, 6, X, X, X, X, X, X, X, X, X, X}},
6995 {{1, 8, 3, 1, 9, 8, 5, 10, 6, X, X, X, X, X, X, X}},
6996 {{1, 6, 5, 2, 6, 1, X, X, X, X, X, X, X, X, X, X}},
6997 {{1, 6, 5, 1, 2, 6, 3, 0, 8, X, X, X, X, X, X, X}},
6998 {{9, 6, 5, 9, 0, 6, 0, 2, 6, X, X, X, X, X, X, X}},
6999 {{5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, X, X, X, X}},
7000 {{2, 3, 11, 10, 6, 5, X, X, X, X, X, X, X, X, X, X}},
7001 {{11, 0, 8, 11, 2, 0, 10, 6, 5, X, X, X, X, X, X, X}},
7002 {{0, 1, 9, 2, 3, 11, 5, 10, 6, X, X, X, X, X, X, X}},
7003 {{5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, X, X, X, X}},
7004 {{6, 3, 11, 6, 5, 3, 5, 1, 3, X, X, X, X, X, X, X}},
7005 {{0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, X, X, X, X}},
7006 {{3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, X, X, X, X}},
7007 {{6, 5, 9, 6, 9, 11, 11, 9, 8, X, X, X, X, X, X, X}},
7008 {{5, 10, 6, 4, 7, 8, X, X, X, X, X, X, X, X, X, X}},
7009 {{4, 3, 0, 4, 7, 3, 6, 5, 10, X, X, X, X, X, X, X}},
7010 {{1, 9, 0, 5, 10, 6, 8, 4, 7, X, X, X, X, X, X, X}},
7011 {{10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, X, X, X, X}},
7012 {{6, 1, 2, 6, 5, 1, 4, 7, 8, X, X, X, X, X, X, X}},
7013 {{1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, X, X, X, X}},
7014 {{8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, X, X, X, X}},
7015 {{7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, X}},
7016 {{3, 11, 2, 7, 8, 4, 10, 6, 5, X, X, X, X, X, X, X}},
7017 {{5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, X, X, X, X}},
7018 {{0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, X, X, X, X}},
7019 {{9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, X}},
7020 {{8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, X, X, X, X}},
7021 {{5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, X}},
7022 {{0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, X}},
7023 {{6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, X, X, X, X}},
7024 {{10, 4, 9, 6, 4, 10, X, X, X, X, X, X, X, X, X, X}},
7025 {{4, 10, 6, 4, 9, 10, 0, 8, 3, X, X, X, X, X, X, X}},
7026 {{10, 0, 1, 10, 6, 0, 6, 4, 0, X, X, X, X, X, X, X}},
7027 {{8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, X, X, X, X}},
7028 {{1, 4, 9, 1, 2, 4, 2, 6, 4, X, X, X, X, X, X, X}},
7029 {{3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, X, X, X, X}},
7030 {{0, 2, 4, 4, 2, 6, X, X, X, X, X, X, X, X, X, X}},
7031 {{8, 3, 2, 8, 2, 4, 4, 2, 6, X, X, X, X, X, X, X}},
7032 {{10, 4, 9, 10, 6, 4, 11, 2, 3, X, X, X, X, X, X, X}},
7033 {{0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, X, X, X, X}},
7034 {{3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, X, X, X, X}},
7035 {{6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, X}},
7036 {{9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, X, X, X, X}},
7037 {{8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, X}},
7038 {{3, 11, 6, 3, 6, 0, 0, 6, 4, X, X, X, X, X, X, X}},
7039 {{6, 4, 8, 11, 6, 8, X, X, X, X, X, X, X, X, X, X}},
7040 {{7, 10, 6, 7, 8, 10, 8, 9, 10, X, X, X, X, X, X, X}},
7041 {{0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, X, X, X, X}},
7042 {{10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, X, X, X, X}},
7043 {{10, 6, 7, 10, 7, 1, 1, 7, 3, X, X, X, X, X, X, X}},
7044 {{1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, X, X, X, X}},
7045 {{2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, X}},
7046 {{7, 8, 0, 7, 0, 6, 6, 0, 2, X, X, X, X, X, X, X}},
7047 {{7, 3, 2, 6, 7, 2, X, X, X, X, X, X, X, X, X, X}},
7048 {{2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, X, X, X, X}},
7049 {{2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, X}},
7050 {{1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, X}},
7051 {{11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, X, X, X, X}},
7052 {{8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, X}},
7053 {{0, 9, 1, 11, 6, 7, X, X, X, X, X, X, X, X, X, X}},
7054 {{7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, X, X, X, X}},
7055 {{7, 11, 6, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7056 {{7, 6, 11, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7057 {{3, 0, 8, 11, 7, 6, X, X, X, X, X, X, X, X, X, X}},
7058 {{0, 1, 9, 11, 7, 6, X, X, X, X, X, X, X, X, X, X}},
7059 {{8, 1, 9, 8, 3, 1, 11, 7, 6, X, X, X, X, X, X, X}},
7060 {{10, 1, 2, 6, 11, 7, X, X, X, X, X, X, X, X, X, X}},
7061 {{1, 2, 10, 3, 0, 8, 6, 11, 7, X, X, X, X, X, X, X}},
7062 {{2, 9, 0, 2, 10, 9, 6, 11, 7, X, X, X, X, X, X, X}},
7063 {{6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, X, X, X, X}},
7064 {{7, 2, 3, 6, 2, 7, X, X, X, X, X, X, X, X, X, X}},
7065 {{7, 0, 8, 7, 6, 0, 6, 2, 0, X, X, X, X, X, X, X}},
7066 {{2, 7, 6, 2, 3, 7, 0, 1, 9, X, X, X, X, X, X, X}},
7067 {{1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, X, X, X, X}},
7068 {{10, 7, 6, 10, 1, 7, 1, 3, 7, X, X, X, X, X, X, X}},
7069 {{10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, X, X, X, X}},
7070 {{0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, X, X, X, X}},
7071 {{7, 6, 10, 7, 10, 8, 8, 10, 9, X, X, X, X, X, X, X}},
7072 {{6, 8, 4, 11, 8, 6, X, X, X, X, X, X, X, X, X, X}},
7073 {{3, 6, 11, 3, 0, 6, 0, 4, 6, X, X, X, X, X, X, X}},
7074 {{8, 6, 11, 8, 4, 6, 9, 0, 1, X, X, X, X, X, X, X}},
7075 {{9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, X, X, X, X}},
7076 {{6, 8, 4, 6, 11, 8, 2, 10, 1, X, X, X, X, X, X, X}},
7077 {{1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, X, X, X, X}},
7078 {{4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, X, X, X, X}},
7079 {{10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, X}},
7080 {{8, 2, 3, 8, 4, 2, 4, 6, 2, X, X, X, X, X, X, X}},
7081 {{0, 4, 2, 4, 6, 2, X, X, X, X, X, X, X, X, X, X}},
7082 {{1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, X, X, X, X}},
7083 {{1, 9, 4, 1, 4, 2, 2, 4, 6, X, X, X, X, X, X, X}},
7084 {{8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, X, X, X, X}},
7085 {{10, 1, 0, 10, 0, 6, 6, 0, 4, X, X, X, X, X, X, X}},
7086 {{4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, X}},
7087 {{10, 9, 4, 6, 10, 4, X, X, X, X, X, X, X, X, X, X}},
7088 {{4, 9, 5, 7, 6, 11, X, X, X, X, X, X, X, X, X, X}},
7089 {{0, 8, 3, 4, 9, 5, 11, 7, 6, X, X, X, X, X, X, X}},
7090 {{5, 0, 1, 5, 4, 0, 7, 6, 11, X, X, X, X, X, X, X}},
7091 {{11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, X, X, X, X}},
7092 {{9, 5, 4, 10, 1, 2, 7, 6, 11, X, X, X, X, X, X, X}},
7093 {{6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, X, X, X, X}},
7094 {{7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, X, X, X, X}},
7095 {{3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, X}},
7096 {{7, 2, 3, 7, 6, 2, 5, 4, 9, X, X, X, X, X, X, X}},
7097 {{9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, X, X, X, X}},
7098 {{3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, X, X, X, X}},
7099 {{6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, X}},
7100 {{9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, X, X, X, X}},
7101 {{1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, X}},
7102 {{4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, X}},
7103 {{7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, X, X, X, X}},
7104 {{6, 9, 5, 6, 11, 9, 11, 8, 9, X, X, X, X, X, X, X}},
7105 {{3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, X, X, X, X}},
7106 {{0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, X, X, X, X}},
7107 {{6, 11, 3, 6, 3, 5, 5, 3, 1, X, X, X, X, X, X, X}},
7108 {{1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, X, X, X, X}},
7109 {{0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, X}},
7110 {{11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, X}},
7111 {{6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, X, X, X, X}},
7112 {{5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, X, X, X, X}},
7113 {{9, 5, 6, 9, 6, 0, 0, 6, 2, X, X, X, X, X, X, X}},
7114 {{1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, X}},
7115 {{1, 5, 6, 2, 1, 6, X, X, X, X, X, X, X, X, X, X}},
7116 {{1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, X}},
7117 {{10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, X, X, X, X}},
7118 {{0, 3, 8, 5, 6, 10, X, X, X, X, X, X, X, X, X, X}},
7119 {{10, 5, 6, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7120 {{11, 5, 10, 7, 5, 11, X, X, X, X, X, X, X, X, X, X}},
7121 {{11, 5, 10, 11, 7, 5, 8, 3, 0, X, X, X, X, X, X, X}},
7122 {{5, 11, 7, 5, 10, 11, 1, 9, 0, X, X, X, X, X, X, X}},
7123 {{10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, X, X, X, X}},
7124 {{11, 1, 2, 11, 7, 1, 7, 5, 1, X, X, X, X, X, X, X}},
7125 {{0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, X, X, X, X}},
7126 {{9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, X, X, X, X}},
7127 {{7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, X}},
7128 {{2, 5, 10, 2, 3, 5, 3, 7, 5, X, X, X, X, X, X, X}},
7129 {{8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, X, X, X, X}},
7130 {{9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, X, X, X, X}},
7131 {{9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, X}},
7132 {{1, 3, 5, 3, 7, 5, X, X, X, X, X, X, X, X, X, X}},
7133 {{0, 8, 7, 0, 7, 1, 1, 7, 5, X, X, X, X, X, X, X}},
7134 {{9, 0, 3, 9, 3, 5, 5, 3, 7, X, X, X, X, X, X, X}},
7135 {{9, 8, 7, 5, 9, 7, X, X, X, X, X, X, X, X, X, X}},
7136 {{5, 8, 4, 5, 10, 8, 10, 11, 8, X, X, X, X, X, X, X}},
7137 {{5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, X, X, X, X}},
7138 {{0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, X, X, X, X}},
7139 {{10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, X}},
7140 {{2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, X, X, X, X}},
7141 {{0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, X}},
7142 {{0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, X}},
7143 {{9, 4, 5, 2, 11, 3, X, X, X, X, X, X, X, X, X, X}},
7144 {{2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, X, X, X, X}},
7145 {{5, 10, 2, 5, 2, 4, 4, 2, 0, X, X, X, X, X, X, X}},
7146 {{3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, X}},
7147 {{5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, X, X, X, X}},
7148 {{8, 4, 5, 8, 5, 3, 3, 5, 1, X, X, X, X, X, X, X}},
7149 {{0, 4, 5, 1, 0, 5, X, X, X, X, X, X, X, X, X, X}},
7150 {{8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, X, X, X, X}},
7151 {{9, 4, 5, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7152 {{4, 11, 7, 4, 9, 11, 9, 10, 11, X, X, X, X, X, X, X}},
7153 {{0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, X, X, X, X}},
7154 {{1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, X, X, X, X}},
7155 {{3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, X}},
7156 {{4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, X, X, X, X}},
7157 {{9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, X}},
7158 {{11, 7, 4, 11, 4, 2, 2, 4, 0, X, X, X, X, X, X, X}},
7159 {{11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, X, X, X, X}},
7160 {{2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, X, X, X, X}},
7161 {{9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, X}},
7162 {{3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, X}},
7163 {{1, 10, 2, 8, 7, 4, X, X, X, X, X, X, X, X, X, X}},
7164 {{4, 9, 1, 4, 1, 7, 7, 1, 3, X, X, X, X, X, X, X}},
7165 {{4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, X, X, X, X}},
7166 {{4, 0, 3, 7, 4, 3, X, X, X, X, X, X, X, X, X, X}},
7167 {{4, 8, 7, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7168 {{9, 10, 8, 10, 11, 8, X, X, X, X, X, X, X, X, X, X}},
7169 {{3, 0, 9, 3, 9, 11, 11, 9, 10, X, X, X, X, X, X, X}},
7170 {{0, 1, 10, 0, 10, 8, 8, 10, 11, X, X, X, X, X, X, X}},
7171 {{3, 1, 10, 11, 3, 10, X, X, X, X, X, X, X, X, X, X}},
7172 {{1, 2, 11, 1, 11, 9, 9, 11, 8, X, X, X, X, X, X, X}},
7173 {{3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, X, X, X, X}},
7174 {{0, 2, 11, 8, 0, 11, X, X, X, X, X, X, X, X, X, X}},
7175 {{3, 2, 11, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7176 {{2, 3, 8, 2, 8, 10, 10, 8, 9, X, X, X, X, X, X, X}},
7177 {{9, 10, 2, 0, 9, 2, X, X, X, X, X, X, X, X, X, X}},
7178 {{2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, X, X, X, X}},
7179 {{1, 10, 2, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7180 {{1, 3, 8, 9, 1, 8, X, X, X, X, X, X, X, X, X, X}},
7181 {{0, 9, 1, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7182 {{0, 3, 8, X, X, X, X, X, X, X, X, X, X, X, X, X}},
7183 {{X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X}}}};
7208 line_to_vertex_table,
7222#include "grid_tools.inst"
bool operator==(const AlignedVector< T > &lhs, const AlignedVector< T > &rhs)
void distribute(VectorType &vec) const
std::pair< Point< spacedim, Number >, Point< spacedim, Number > > & get_boundary_points()
void distribute_dofs(const FiniteElement< dim, spacedim > &fe)
types::global_dof_index n_dofs() 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
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
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner)
numbers::NumberTraits< Number >::real_type norm() const
virtual MPI_Comm get_communicator() const
unsigned int n_quads() const
void load_user_indices(const std::vector< unsigned int > &v)
face_iterator end_face() const
cell_iterator begin(const unsigned int level=0) 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
virtual std::vector< unsigned int > run() override
#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
__global__ void set(Number *val, const Number s, const size_type N)
static ::ExceptionBase & ExcMeshNotOrientable()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
std::string to_string(const T &t)
static ::ExceptionBase & ExcVertexNotUsed(unsigned int arg1)
#define AssertDimension(dim1, dim2)
void copy_from(const size_type n_rows, const size_type n_cols, const ForwardIterator begin, const ForwardIterator end)
#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
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)
Expression fabs(const Expression &x)
Expression floor(const Expression &x)
Expression acos(const Expression &x)
@ 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, SparseMatrix< double > &matrix, const Function< spacedim > *const a=nullptr, const AffineConstraints< double > &constraints=AffineConstraints< double >())
void swap(MemorySpaceData< Number, MemorySpace > &, MemorySpaceData< Number, MemorySpace > &)
Point< spacedim > point(const gp_Pnt &p, const double tolerance=1e-10)
void quadrature_points(const Triangulation< dim, spacedim > &triangulation, const Quadrature< dim > &quadrature, const std::vector< std::vector< BoundingBox< spacedim > > > &global_bounding_boxes, ParticleHandler< dim, spacedim > &particle_handler, const Mapping< dim, spacedim > &mapping=(ReferenceCells::get_hypercube< dim >() .template get_default_linear_mapping< dim, spacedim >()), const std::vector< std::vector< double > > &properties={})
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > d(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)
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
T unpack(const std::vector< char > &buffer, const bool allow_compression=true)
Iterator lower_bound(Iterator first, Iterator last, const T &val)
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
void copy(const T *begin, const T *end, U *dest)
void reinit(MatrixBlock< MatrixType > &v, const BlockSparsityPattern &p)
static constexpr double PI
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 > cos(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sin(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 > &)
unsigned int subdomain_id
uint64_t global_vertex_index
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)
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
constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
bool operator<(const SynchronousIterators< Iterators > &a, const SynchronousIterators< Iterators > &b)
void advance(std::tuple< I1, I2 > &t, const unsigned int n)
#define DEAL_II_VERTEX_INDEX_MPI_TYPE