Reference documentation for deal.II version 9.1.0-pre
grid_tools_dof_handlers.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2001 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/geometry_info.h>
17 #include <deal.II/base/point.h>
18 #include <deal.II/base/tensor.h>
19 
20 #include <deal.II/distributed/shared_tria.h>
21 #include <deal.II/distributed/tria.h>
22 
23 #include <deal.II/dofs/dof_accessor.h>
24 #include <deal.II/dofs/dof_handler.h>
25 
26 #include <deal.II/fe/mapping_q1.h>
27 #include <deal.II/fe/mapping_q_generic.h>
28 
29 #include <deal.II/grid/filtered_iterator.h>
30 #include <deal.II/grid/grid_tools.h>
31 #include <deal.II/grid/tria.h>
32 #include <deal.II/grid/tria_accessor.h>
33 #include <deal.II/grid/tria_iterator.h>
34 
35 #include <deal.II/hp/dof_handler.h>
36 #include <deal.II/hp/mapping_collection.h>
37 
38 #include <deal.II/lac/full_matrix.h>
39 
40 #include <algorithm>
41 #include <array>
42 #include <cmath>
43 #include <list>
44 #include <map>
45 #include <numeric>
46 #include <set>
47 #include <vector>
48 
49 
50 DEAL_II_NAMESPACE_OPEN
51 
52 namespace GridTools
53 {
54  template <int dim, template <int, int> class MeshType, int spacedim>
55  unsigned int
56  find_closest_vertex(const MeshType<dim, spacedim> &mesh,
57  const Point<spacedim> & p,
58  const std::vector<bool> & marked_vertices)
59  {
60  // first get the underlying
61  // triangulation from the
62  // mesh and determine vertices
63  // and used vertices
65 
66  const std::vector<Point<spacedim>> &vertices = tria.get_vertices();
67 
68  Assert(tria.get_vertices().size() == marked_vertices.size() ||
69  marked_vertices.size() == 0,
70  ExcDimensionMismatch(tria.get_vertices().size(),
71  marked_vertices.size()));
72 
73  // If p is an element of marked_vertices,
74  // and q is that of used_Vertices,
75  // the vector marked_vertices does NOT
76  // contain unused vertices if p implies q.
77  // I.e., if p is true q must be true
78  // (if p is false, q could be false or true).
79  // p implies q logic is encapsulated in ~p|q.
80  Assert(
81  marked_vertices.size() == 0 ||
82  std::equal(marked_vertices.begin(),
83  marked_vertices.end(),
84  tria.get_used_vertices().begin(),
85  [](bool p, bool q) { return !p || q; }),
86  ExcMessage(
87  "marked_vertices should be a subset of used vertices in the triangulation "
88  "but marked_vertices contains one or more vertices that are not used vertices!"));
89 
90  // In addition, if a vector bools
91  // is specified (marked_vertices)
92  // marking all the vertices which
93  // could be the potentially closest
94  // vertex to the point, use it instead
95  // of used vertices
96  const std::vector<bool> &used = (marked_vertices.size() == 0) ?
97  tria.get_used_vertices() :
98  marked_vertices;
99 
100  // At the beginning, the first
101  // used vertex is the closest one
102  std::vector<bool>::const_iterator first =
103  std::find(used.begin(), used.end(), true);
104 
105  // Assert that at least one vertex
106  // is actually used
107  Assert(first != used.end(), ExcInternalError());
108 
109  unsigned int best_vertex = std::distance(used.begin(), first);
110  double best_dist = (p - vertices[best_vertex]).norm_square();
111 
112  // For all remaining vertices, test
113  // whether they are any closer
114  for (unsigned int j = best_vertex + 1; j < vertices.size(); j++)
115  if (used[j])
116  {
117  double dist = (p - vertices[j]).norm_square();
118  if (dist < best_dist)
119  {
120  best_vertex = j;
121  best_dist = dist;
122  }
123  }
124 
125  return best_vertex;
126  }
127 
128 
129 
130  template <int dim, template <int, int> class MeshType, int spacedim>
131  unsigned int
133  const MeshType<dim, spacedim> &mesh,
134  const Point<spacedim> & p,
135  const std::vector<bool> & marked_vertices)
136  {
137  // Take a shortcut in the simple case.
138  if (mapping.preserves_vertex_locations() == true)
139  return find_closest_vertex(mesh, p, marked_vertices);
140 
141  // first get the underlying
142  // triangulation from the
143  // mesh and determine vertices
144  // and used vertices
145  const Triangulation<dim, spacedim> &tria = mesh.get_triangulation();
146 
147  auto vertices = extract_used_vertices(tria, mapping);
148 
149  Assert(tria.get_vertices().size() == marked_vertices.size() ||
150  marked_vertices.size() == 0,
151  ExcDimensionMismatch(tria.get_vertices().size(),
152  marked_vertices.size()));
153 
154  // If p is an element of marked_vertices,
155  // and q is that of used_Vertices,
156  // the vector marked_vertices does NOT
157  // contain unused vertices if p implies q.
158  // I.e., if p is true q must be true
159  // (if p is false, q could be false or true).
160  // p implies q logic is encapsulated in ~p|q.
161  Assert(
162  marked_vertices.size() == 0 ||
163  std::equal(marked_vertices.begin(),
164  marked_vertices.end(),
165  tria.get_used_vertices().begin(),
166  [](bool p, bool q) { return !p || q; }),
167  ExcMessage(
168  "marked_vertices should be a subset of used vertices in the triangulation "
169  "but marked_vertices contains one or more vertices that are not used vertices!"));
170 
171  // Remove from the map unwanted elements.
172  if (marked_vertices.size())
173  for (auto it = vertices.begin(); it != vertices.end();)
174  {
175  if (marked_vertices[it->first] == false)
176  {
177  vertices.erase(it++);
178  }
179  else
180  {
181  ++it;
182  }
183  }
184 
185  return find_closest_vertex(vertices, p);
186  }
187 
188 
189 
190  template <int dim, template <int, int> class MeshType, int spacedim>
191 #ifndef _MSC_VER
192  std::vector<typename MeshType<dim, spacedim>::active_cell_iterator>
193 #else
194  std::vector<
195  typename ::internal::
196  ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>
197 #endif
198  find_cells_adjacent_to_vertex(const MeshType<dim, spacedim> &mesh,
199  const unsigned int vertex)
200  {
201  // make sure that the given vertex is
202  // an active vertex of the underlying
203  // triangulation
204  Assert(vertex < mesh.get_triangulation().n_vertices(),
205  ExcIndexRange(0, mesh.get_triangulation().n_vertices(), vertex));
206  Assert(mesh.get_triangulation().get_used_vertices()[vertex],
207  ExcVertexNotUsed(vertex));
208 
209  // use a set instead of a vector
210  // to ensure that cells are inserted only
211  // once
212  std::set<typename ::internal::
213  ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>
214  adjacent_cells;
215 
216  typename ::internal::
217  ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type
218  cell = mesh.begin_active(),
219  endc = mesh.end();
220 
221  // go through all active cells and look if the vertex is part of that cell
222  //
223  // in 1d, this is all we need to care about. in 2d/3d we also need to worry
224  // that the vertex might be a hanging node on a face or edge of a cell; in
225  // this case, we would want to add those cells as well on whose faces the
226  // vertex is located but for which it is not a vertex itself.
227  //
228  // getting this right is a lot simpler in 2d than in 3d. in 2d, a hanging
229  // node can only be in the middle of a face and we can query the neighboring
230  // cell from the current cell. on the other hand, in 3d a hanging node
231  // vertex can also be on an edge but there can be many other cells on
232  // this edge and we can not access them from the cell we are currently
233  // on.
234  //
235  // so, in the 3d case, if we run the algorithm as in 2d, we catch all
236  // those cells for which the vertex we seek is on a *subface*, but we
237  // miss the case of cells for which the vertex we seek is on a
238  // sub-edge for which there is no corresponding sub-face (because the
239  // immediate neighbor behind this face is not refined), see for example
240  // the bits/find_cells_adjacent_to_vertex_6 testcase. thus, if we
241  // haven't yet found the vertex for the current cell we also need to
242  // look at the mid-points of edges
243  //
244  // as a final note, deciding whether a neighbor is actually coarser is
245  // simple in the case of isotropic refinement (we just need to look at
246  // the level of the current and the neighboring cell). however, this
247  // isn't so simple if we have used anisotropic refinement since then
248  // the level of a cell is not indicative of whether it is coarser or
249  // not than the current cell. ultimately, we want to add all cells on
250  // which the vertex is, independent of whether they are coarser or
251  // finer and so in the 2d case below we simply add *any* *active* neighbor.
252  // in the worst case, we add cells multiple times to the adjacent_cells
253  // list, but std::set throws out those cells already entered
254  for (; cell != endc; ++cell)
255  {
256  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; v++)
257  if (cell->vertex_index(v) == vertex)
258  {
259  // OK, we found a cell that contains
260  // the given vertex. We add it
261  // to the list.
262  adjacent_cells.insert(cell);
263 
264  // as explained above, in 2+d we need to check whether
265  // this vertex is on a face behind which there is a
266  // (possibly) coarser neighbor. if this is the case,
267  // then we need to also add this neighbor
268  if (dim >= 2)
269  for (unsigned int vface = 0; vface < dim; vface++)
270  {
271  const unsigned int face =
273 
274  if (!cell->at_boundary(face) &&
275  cell->neighbor(face)->active())
276  {
277  // there is a (possibly) coarser cell behind a
278  // face to which the vertex belongs. the
279  // vertex we are looking at is then either a
280  // vertex of that coarser neighbor, or it is a
281  // hanging node on one of the faces of that
282  // cell. in either case, it is adjacent to the
283  // vertex, so add it to the list as well (if
284  // the cell was already in the list then the
285  // std::set makes sure that we get it only
286  // once)
287  adjacent_cells.insert(cell->neighbor(face));
288  }
289  }
290 
291  // in any case, we have found a cell, so go to the next cell
292  goto next_cell;
293  }
294 
295  // in 3d also loop over the edges
296  if (dim >= 3)
297  {
298  for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
299  if (cell->line(e)->has_children())
300  // the only place where this vertex could have been
301  // hiding is on the mid-edge point of the edge we
302  // are looking at
303  if (cell->line(e)->child(0)->vertex_index(1) == vertex)
304  {
305  adjacent_cells.insert(cell);
306 
307  // jump out of this tangle of nested loops
308  goto next_cell;
309  }
310  }
311 
312  // in more than 3d we would probably have to do the same as
313  // above also for even lower-dimensional objects
314  Assert(dim <= 3, ExcNotImplemented());
315 
316  // move on to the next cell if we have found the
317  // vertex on the current one
318  next_cell:;
319  }
320 
321  // if this was an active vertex then there needs to have been
322  // at least one cell to which it is adjacent!
323  Assert(adjacent_cells.size() > 0, ExcInternalError());
324 
325  // return the result as a vector, rather than the set we built above
326  return std::vector<
327  typename ::internal::
328  ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>(
329  adjacent_cells.begin(), adjacent_cells.end());
330  }
331 
332 
333 
334  namespace
335  {
336  template <int dim, template <int, int> class MeshType, int spacedim>
337  void
338  find_active_cell_around_point_internal(
339  const MeshType<dim, spacedim> &mesh,
340 #ifndef _MSC_VER
341  std::set<typename MeshType<dim, spacedim>::active_cell_iterator>
342  &searched_cells,
343  std::set<typename MeshType<dim, spacedim>::active_cell_iterator>
344  &adjacent_cells)
345 #else
346  std::set<
347  typename ::internal::
348  ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>
349  &searched_cells,
350  std::set<
351  typename ::internal::
352  ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type>
353  &adjacent_cells)
354 #endif
355  {
356 #ifndef _MSC_VER
357  using cell_iterator =
358  typename MeshType<dim, spacedim>::active_cell_iterator;
359 #else
360  using cell_iterator = typename ::internal::
361  ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type;
362 #endif
363 
364  // update the searched cells
365  searched_cells.insert(adjacent_cells.begin(), adjacent_cells.end());
366  // now we to collect all neighbors
367  // of the cells in adjacent_cells we
368  // have not yet searched.
369  std::set<cell_iterator> adjacent_cells_new;
370 
371  typename std::set<cell_iterator>::const_iterator cell =
372  adjacent_cells.begin(),
373  endc =
374  adjacent_cells.end();
375  for (; cell != endc; ++cell)
376  {
377  std::vector<cell_iterator> active_neighbors;
378  get_active_neighbors<MeshType<dim, spacedim>>(*cell,
379  active_neighbors);
380  for (unsigned int i = 0; i < active_neighbors.size(); ++i)
381  if (searched_cells.find(active_neighbors[i]) ==
382  searched_cells.end())
383  adjacent_cells_new.insert(active_neighbors[i]);
384  }
385  adjacent_cells.clear();
386  adjacent_cells.insert(adjacent_cells_new.begin(),
387  adjacent_cells_new.end());
388  if (adjacent_cells.size() == 0)
389  {
390  // we haven't found any other cell that would be a
391  // neighbor of a previously found cell, but we know
392  // that we haven't checked all cells yet. that means
393  // that the domain is disconnected. in that case,
394  // choose the first previously untouched cell we
395  // can find
396  cell_iterator it = mesh.begin_active();
397  for (; it != mesh.end(); ++it)
398  if (searched_cells.find(it) == searched_cells.end())
399  {
400  adjacent_cells.insert(it);
401  break;
402  }
403  }
404  }
405 
406 
407 
408  template <int dim, template <int, int> class MeshType, int spacedim>
409 #ifndef _MSC_VER
410  std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
411  Point<dim>>
412 #else
413  std::pair<
414  typename ::internal::
415  ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type,
416  Point<dim>>
417 #endif
418  find_active_cell_around_point_tolerance(
419  const Mapping<dim, spacedim> & mapping,
420  const MeshType<dim, spacedim> &mesh,
421  const Point<spacedim> & p,
422  const std::vector<bool> & marked_vertices,
423  const double tolerance)
424  {
425  using active_cell_iterator = typename ::internal::
426  ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type;
427 
428  // The best distance is set to the
429  // maximum allowable distance from
430  // the unit cell; we assume a
431  // max. deviation of the given tolerance
432  double best_distance = tolerance;
433  int best_level = -1;
434  std::pair<active_cell_iterator, Point<dim>> best_cell;
435 
436  // Find closest vertex and determine
437  // all adjacent cells
438  std::vector<active_cell_iterator> adjacent_cells_tmp =
440  mesh, find_closest_vertex(mapping, mesh, p, marked_vertices));
441 
442  // Make sure that we have found
443  // at least one cell adjacent to vertex.
444  Assert(adjacent_cells_tmp.size() > 0, ExcInternalError());
445 
446  // Copy all the cells into a std::set
447  std::set<active_cell_iterator> adjacent_cells(adjacent_cells_tmp.begin(),
448  adjacent_cells_tmp.end());
449  std::set<active_cell_iterator> searched_cells;
450 
451  // Determine the maximal number of cells
452  // in the grid.
453  // As long as we have not found
454  // the cell and have not searched
455  // every cell in the triangulation,
456  // we keep on looking.
457  const unsigned int n_active_cells =
458  mesh.get_triangulation().n_active_cells();
459  bool found = false;
460  unsigned int cells_searched = 0;
461  while (!found && cells_searched < n_active_cells)
462  {
463  typename std::set<active_cell_iterator>::const_iterator
464  cell = adjacent_cells.begin(),
465  endc = adjacent_cells.end();
466  for (; cell != endc; ++cell)
467  {
468  try
469  {
470  const Point<dim> p_cell =
471  mapping.transform_real_to_unit_cell(*cell, p);
472 
473  // calculate the infinity norm of
474  // the distance vector to the unit cell.
475  const double dist =
477 
478  // We compare if the point is inside the
479  // unit cell (or at least not too far
480  // outside). If it is, it is also checked
481  // that the cell has a more refined state
482  if ((dist < best_distance) ||
483  ((dist == best_distance) &&
484  ((*cell)->level() > best_level)))
485  {
486  found = true;
487  best_distance = dist;
488  best_level = (*cell)->level();
489  best_cell = std::make_pair(*cell, p_cell);
490  }
491  }
492  catch (
494  &)
495  {
496  // ok, the transformation
497  // failed presumably
498  // because the point we
499  // are looking for lies
500  // outside the current
501  // cell. this means that
502  // the current cell can't
503  // be the cell around the
504  // point, so just ignore
505  // this cell and move on
506  // to the next
507  }
508  }
509 
510  // update the number of cells searched
511  cells_searched += adjacent_cells.size();
512 
513  // if the user provided a custom mask for vertices,
514  // terminate the search without trying to expand the search
515  // to all cells of the triangulation, as done below.
516  if (marked_vertices.size() > 0)
517  cells_searched = n_active_cells;
518 
519  // if we have not found the cell in
520  // question and have not yet searched every
521  // cell, we expand our search to
522  // all the not already searched neighbors of
523  // the cells in adjacent_cells. This is
524  // what find_active_cell_around_point_internal
525  // is for.
526  if (!found && cells_searched < n_active_cells)
527  {
528  find_active_cell_around_point_internal<dim, MeshType, spacedim>(
529  mesh, searched_cells, adjacent_cells);
530  }
531  }
532 
533  AssertThrow(best_cell.first.state() == IteratorState::valid,
534  ExcPointNotFound<spacedim>(p));
535 
536  return best_cell;
537  }
538  } // namespace
539 
540 
541 
542  template <int dim, template <int, int> class MeshType, int spacedim>
543 #ifndef _MSC_VER
544  typename MeshType<dim, spacedim>::active_cell_iterator
545 #else
546  typename ::internal::
547  ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type
548 #endif
549  find_active_cell_around_point(const MeshType<dim, spacedim> &mesh,
550  const Point<spacedim> & p,
551  const std::vector<bool> & marked_vertices)
552  {
553  return find_active_cell_around_point<dim, MeshType, spacedim>(
554  StaticMappingQ1<dim, spacedim>::mapping, mesh, p, marked_vertices)
555  .first;
556  }
557 
558 
559 
560  template <int dim, template <int, int> class MeshType, int spacedim>
561 #ifndef _MSC_VER
562  std::pair<typename MeshType<dim, spacedim>::active_cell_iterator, Point<dim>>
563 #else
564  std::pair<typename ::internal::
565  ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type,
566  Point<dim>>
567 #endif
569  const MeshType<dim, spacedim> &mesh,
570  const Point<spacedim> & p,
571  const std::vector<bool> & marked_vertices)
572  {
573  return find_active_cell_around_point_tolerance(
574  mapping, mesh, p, marked_vertices, 1e-10);
575  }
576 
577 
578 
579  template <int dim, template <int, int> class MeshType, int spacedim>
580 #ifndef _MSC_VER
581  std::vector<std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
582  Point<dim>>>
583 #else
584  std::vector<std::pair<
585  typename ::internal::
586  ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim>>::type,
587  Point<dim>>>
588 #endif
590  const MeshType<dim, spacedim> &mesh,
591  const Point<spacedim> & p,
592  const double tolerance,
593  const std::vector<bool> &marked_vertices)
594  {
595  // first use the result of the single point function as a guess. In order
596  // not to make the other find_all_active_cells_around_point more expensive
597  // and avoid some additional logic there, we first start with one cell as
598  // given by that other function (that possibly goes through a larger set
599  // of cells) and later add a list of more cells as appropriate.
600  std::vector<
601  std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
602  Point<dim>>>
603  cells_and_points;
604  try
605  {
606  cells_and_points.push_back(find_active_cell_around_point_tolerance(
607  mapping, mesh, p, marked_vertices, tolerance));
608  }
609  catch (ExcPointNotFound<spacedim> &)
610  {}
611 
612  if (!cells_and_points.empty())
613  {
614  // check if the given point is on the surface of the unit cell. if yes,
615  // need to find all neighbors
616  const Point<dim> unit_point = cells_and_points.front().second;
617  const auto my_cell = cells_and_points.front().first;
618  Tensor<1, dim> distance_to_center;
619  unsigned int n_dirs_at_threshold = 0;
620  unsigned int last_point_at_threshold = numbers::invalid_unsigned_int;
621  for (unsigned int d = 0; d < dim; ++d)
622  {
623  distance_to_center[d] = std::abs(unit_point[d] - 0.5);
624  if (distance_to_center[d] > 0.5 - tolerance)
625  {
626  ++n_dirs_at_threshold;
627  last_point_at_threshold = d;
628  }
629  }
630 
631  std::vector<typename MeshType<dim, spacedim>::active_cell_iterator>
632  cells_to_add;
633  // point is within face -> only need neighbor
634  if (n_dirs_at_threshold == 1)
635  {
636  unsigned int neighbor_index =
637  2 * last_point_at_threshold +
638  (unit_point[last_point_at_threshold] > 0.5 ? 1 : 0);
639  if (!my_cell->at_boundary(neighbor_index))
640  cells_to_add.push_back(my_cell->neighbor(neighbor_index));
641  }
642  // corner point -> use all neighbors
643  else if (n_dirs_at_threshold == dim)
644  {
645  unsigned int local_vertex_index = 0;
646  for (unsigned int d = 0; d < dim; ++d)
647  local_vertex_index += (unit_point[d] > 0.5 ? 1 : 0) << d;
648  std::vector<typename MeshType<dim, spacedim>::active_cell_iterator>
650  mesh, my_cell->vertex_index(local_vertex_index));
651  for (const auto &cell : cells)
652  if (cell != my_cell)
653  cells_to_add.push_back(cell);
654  }
655  // point on line in 3D: We cannot simply take the intersection between
656  // the two vertices of cels because of hanging nodes. So instead we
657  // list the vertices around both points and then select the
658  // appropriate cells according to the result of read_to_unit_cell
659  // below.
660  else if (n_dirs_at_threshold == 2)
661  {
662  std::pair<unsigned int, unsigned int> vertex_indices[3];
663  unsigned int count_vertex_indices = 0;
664  unsigned int free_direction = numbers::invalid_unsigned_int;
665  for (unsigned int d = 0; d < dim; ++d)
666  {
667  if (distance_to_center[d] > 0.5 - tolerance)
668  {
669  vertex_indices[count_vertex_indices].first = d;
670  vertex_indices[count_vertex_indices].second =
671  unit_point[d] > 0.5 ? 1 : 0;
672  count_vertex_indices++;
673  }
674  else
675  free_direction = d;
676  }
677 
678  AssertDimension(count_vertex_indices, 2);
679  Assert(free_direction != numbers::invalid_unsigned_int,
680  ExcInternalError());
681 
682  const unsigned int first_vertex =
683  (vertex_indices[0].second << vertex_indices[0].first) +
684  (vertex_indices[1].second << vertex_indices[1].first);
685  for (unsigned int d = 0; d < 2; ++d)
686  {
687  auto tentative_cells = find_cells_adjacent_to_vertex(
688  mesh,
689  my_cell->vertex_index(first_vertex + (d << free_direction)));
690  for (const auto &cell : tentative_cells)
691  {
692  bool cell_not_yet_present = true;
693  for (const auto &other_cell : cells_to_add)
694  if (cell == other_cell)
695  {
696  cell_not_yet_present = false;
697  break;
698  }
699  if (cell_not_yet_present)
700  cells_to_add.push_back(cell);
701  }
702  }
703  }
704 
705  const double original_distance_to_unit_cell =
707  for (auto cell : cells_to_add)
708  {
709  if (cell != my_cell)
710  try
711  {
712  const Point<dim> p_unit =
713  mapping.transform_real_to_unit_cell(cell, p);
715  original_distance_to_unit_cell + tolerance)
716  cells_and_points.emplace_back(cell, p_unit);
717  }
718  catch (typename Mapping<dim>::ExcTransformationFailed &)
719  {}
720  }
721  }
722  std::sort(
723  cells_and_points.begin(),
724  cells_and_points.end(),
725  [](const std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
726  Point<dim>> &a,
727  const std::pair<typename MeshType<dim, spacedim>::active_cell_iterator,
728  Point<dim>> &b) { return a.first < b.first; });
729 
730  return cells_and_points;
731  }
732 
733 
734 
735  template <class MeshType>
736  std::vector<typename MeshType::active_cell_iterator>
738  const MeshType &mesh,
739  const std::function<bool(const typename MeshType::active_cell_iterator &)>
740  &predicate)
741  {
742  std::vector<typename MeshType::active_cell_iterator> active_halo_layer;
743  std::vector<bool> locally_active_vertices_on_subdomain(
744  mesh.get_triangulation().n_vertices(), false);
745 
746  // Find the cells for which the predicate is true
747  // These are the cells around which we wish to construct
748  // the halo layer
749  for (typename MeshType::active_cell_iterator cell = mesh.begin_active();
750  cell != mesh.end();
751  ++cell)
752  if (predicate(cell)) // True predicate --> Part of subdomain
753  for (unsigned int v = 0;
754  v < GeometryInfo<MeshType::dimension>::vertices_per_cell;
755  ++v)
756  locally_active_vertices_on_subdomain[cell->vertex_index(v)] = true;
757 
758  // Find the cells that do not conform to the predicate
759  // but share a vertex with the selected subdomain
760  // These comprise the halo layer
761  for (typename MeshType::active_cell_iterator cell = mesh.begin_active();
762  cell != mesh.end();
763  ++cell)
764  if (!predicate(cell)) // False predicate --> Potential halo cell
765  for (unsigned int v = 0;
766  v < GeometryInfo<MeshType::dimension>::vertices_per_cell;
767  ++v)
768  if (locally_active_vertices_on_subdomain[cell->vertex_index(v)] ==
769  true)
770  {
771  active_halo_layer.push_back(cell);
772  break;
773  }
774 
775  return active_halo_layer;
776  }
777 
778 
779 
780  template <class MeshType>
781  std::vector<typename MeshType::cell_iterator>
783  const MeshType &mesh,
784  const std::function<bool(const typename MeshType::cell_iterator &)>
785  & predicate,
786  const unsigned int level)
787  {
788  std::vector<typename MeshType::cell_iterator> level_halo_layer;
789  std::vector<bool> locally_active_vertices_on_level_subdomain(
790  mesh.get_triangulation().n_vertices(), false);
791 
792  // Find the cells for which the predicate is true
793  // These are the cells around which we wish to construct
794  // the halo layer
795  for (typename MeshType::cell_iterator cell = mesh.begin(level);
796  cell != mesh.end(level);
797  ++cell)
798  if (predicate(cell)) // True predicate --> Part of subdomain
799  for (unsigned int v = 0;
800  v < GeometryInfo<MeshType::dimension>::vertices_per_cell;
801  ++v)
802  locally_active_vertices_on_level_subdomain[cell->vertex_index(v)] =
803  true;
804 
805  // Find the cells that do not conform to the predicate
806  // but share a vertex with the selected subdomain on that level
807  // These comprise the halo layer
808  for (typename MeshType::cell_iterator cell = mesh.begin(level);
809  cell != mesh.end(level);
810  ++cell)
811  if (!predicate(cell)) // False predicate --> Potential halo cell
812  for (unsigned int v = 0;
813  v < GeometryInfo<MeshType::dimension>::vertices_per_cell;
814  ++v)
815  if (locally_active_vertices_on_level_subdomain[cell->vertex_index(
816  v)] == true)
817  {
818  level_halo_layer.push_back(cell);
819  break;
820  }
821 
822  return level_halo_layer;
823  }
824 
825 
826  namespace
827  {
828  template <class MeshType>
829  bool
830  contains_locally_owned_cells(
831  const std::vector<typename MeshType::active_cell_iterator> &cells)
832  {
833  for (typename std::vector<
834  typename MeshType::active_cell_iterator>::const_iterator it =
835  cells.begin();
836  it != cells.end();
837  ++it)
838  {
839  if ((*it)->is_locally_owned())
840  return true;
841  }
842  return false;
843  }
844 
845  template <class MeshType>
846  bool
847  contains_artificial_cells(
848  const std::vector<typename MeshType::active_cell_iterator> &cells)
849  {
850  for (typename std::vector<
851  typename MeshType::active_cell_iterator>::const_iterator it =
852  cells.begin();
853  it != cells.end();
854  ++it)
855  {
856  if ((*it)->is_artificial())
857  return true;
858  }
859  return false;
860  }
861  } // namespace
862 
863 
864 
865  template <class MeshType>
866  std::vector<typename MeshType::active_cell_iterator>
867  compute_ghost_cell_halo_layer(const MeshType &mesh)
868  {
869  std::function<bool(const typename MeshType::active_cell_iterator &)>
870  predicate = IteratorFilters::LocallyOwnedCell();
871 
872  const std::vector<typename MeshType::active_cell_iterator>
873  active_halo_layer = compute_active_cell_halo_layer(mesh, predicate);
874 
875  // Check that we never return locally owned or artificial cells
876  // What is left should only be the ghost cells
877  Assert(contains_locally_owned_cells<MeshType>(active_halo_layer) == false,
878  ExcMessage("Halo layer contains locally owned cells"));
879  Assert(contains_artificial_cells<MeshType>(active_halo_layer) == false,
880  ExcMessage("Halo layer contains artificial cells"));
881 
882  return active_halo_layer;
883  }
884 
885 
886 
887  template <class MeshType>
888  std::vector<typename MeshType::active_cell_iterator>
890  const MeshType &mesh,
891  const std::function<bool(const typename MeshType::active_cell_iterator &)>
892  & predicate,
893  const double layer_thickness)
894  {
895  std::vector<typename MeshType::active_cell_iterator>
896  subdomain_boundary_cells, active_cell_layer_within_distance;
897  std::vector<bool> vertices_outside_subdomain(
898  mesh.get_triangulation().n_vertices(), false);
899 
900  const unsigned int spacedim = MeshType::space_dimension;
901 
902  unsigned int n_non_predicate_cells = 0; // Number of non predicate cells
903 
904  // Find the layer of cells for which predicate is true and that
905  // are on the boundary with other cells. These are
906  // subdomain boundary cells.
907 
908  // Find the cells for which the predicate is false
909  // These are the cells which are around the predicate subdomain
910  for (typename MeshType::active_cell_iterator cell = mesh.begin_active();
911  cell != mesh.end();
912  ++cell)
913  if (!predicate(cell)) // Negation of predicate --> Not Part of subdomain
914  {
915  for (unsigned int v = 0;
916  v < GeometryInfo<MeshType::dimension>::vertices_per_cell;
917  ++v)
918  vertices_outside_subdomain[cell->vertex_index(v)] = true;
919  n_non_predicate_cells++;
920  }
921 
922  // If all the active cells conform to the predicate
923  // or if none of the active cells conform to the predicate
924  // there is no active cell layer around the predicate
925  // subdomain (within any distance)
926  if (n_non_predicate_cells == 0 ||
927  n_non_predicate_cells == mesh.get_triangulation().n_active_cells())
928  return std::vector<typename MeshType::active_cell_iterator>();
929 
930  // Find the cells that conform to the predicate
931  // but share a vertex with the cell not in the predicate subdomain
932  for (typename MeshType::active_cell_iterator cell = mesh.begin_active();
933  cell != mesh.end();
934  ++cell)
935  if (predicate(cell)) // True predicate --> Potential boundary cell of the
936  // subdomain
937  for (unsigned int v = 0;
938  v < GeometryInfo<MeshType::dimension>::vertices_per_cell;
939  ++v)
940  if (vertices_outside_subdomain[cell->vertex_index(v)] == true)
941  {
942  subdomain_boundary_cells.push_back(cell);
943  break; // No need to go through remaining vertices
944  }
945 
946  // To cheaply filter out some cells located far away from the predicate
947  // subdomain, get the bounding box of the predicate subdomain.
948  std::pair<Point<spacedim>, Point<spacedim>> bounding_box =
949  compute_bounding_box(mesh, predicate);
950 
951  // DOUBLE_EPSILON to compare really close double values
952  const double &DOUBLE_EPSILON =
953  100. * std::numeric_limits<double>::epsilon();
954 
955  // Add layer_thickness to the bounding box
956  for (unsigned int d = 0; d < spacedim; ++d)
957  {
958  bounding_box.first[d] -= (layer_thickness + DOUBLE_EPSILON); // minp
959  bounding_box.second[d] += (layer_thickness + DOUBLE_EPSILON); // maxp
960  }
961 
962  std::vector<Point<spacedim>>
963  subdomain_boundary_cells_centers; // cache all the subdomain boundary
964  // cells centers here
965  std::vector<double>
966  subdomain_boundary_cells_radii; // cache all the subdomain boundary cells
967  // radii
968  subdomain_boundary_cells_centers.reserve(subdomain_boundary_cells.size());
969  subdomain_boundary_cells_radii.reserve(subdomain_boundary_cells.size());
970  // compute cell radius for each boundary cell of the predicate subdomain
971  for (typename std::vector<typename MeshType::active_cell_iterator>::
972  const_iterator subdomain_boundary_cell_iterator =
973  subdomain_boundary_cells.begin();
974  subdomain_boundary_cell_iterator != subdomain_boundary_cells.end();
975  ++subdomain_boundary_cell_iterator)
976  {
977  const std::pair<Point<spacedim>, double>
978  &subdomain_boundary_cell_enclosing_ball =
979  (*subdomain_boundary_cell_iterator)->enclosing_ball();
980 
981  subdomain_boundary_cells_centers.push_back(
982  subdomain_boundary_cell_enclosing_ball.first);
983  subdomain_boundary_cells_radii.push_back(
984  subdomain_boundary_cell_enclosing_ball.second);
985  }
986  AssertThrow(subdomain_boundary_cells_radii.size() ==
987  subdomain_boundary_cells_centers.size(),
988  ExcInternalError());
989 
990  // Find the cells that are within layer_thickness of predicate subdomain
991  // boundary distance but are inside the extended bounding box. Most cells
992  // might be outside the extended bounding box, so we could skip them. Those
993  // cells that are inside the extended bounding box but are not part of the
994  // predicate subdomain are possible candidates to be within the distance to
995  // the boundary cells of the predicate subdomain.
996  for (typename MeshType::active_cell_iterator cell = mesh.begin_active();
997  cell != mesh.end();
998  ++cell)
999  {
1000  // Ignore all the cells that are in the predicate subdomain
1001  if (predicate(cell))
1002  continue;
1003 
1004  const std::pair<Point<spacedim>, double> &cell_enclosing_ball =
1005  cell->enclosing_ball();
1006 
1007  const Point<spacedim> &cell_enclosing_ball_center =
1008  cell_enclosing_ball.first;
1009  const double &cell_enclosing_ball_radius = cell_enclosing_ball.second;
1010 
1011  bool cell_inside = true; // reset for each cell
1012 
1013  for (unsigned int d = 0; d < spacedim; ++d)
1014  cell_inside &=
1015  (cell_enclosing_ball_center[d] + cell_enclosing_ball_radius >
1016  bounding_box.first[d]) &&
1017  (cell_enclosing_ball_center[d] - cell_enclosing_ball_radius <
1018  bounding_box.second[d]);
1019  // cell_inside is true if its enclosing ball intersects the extended
1020  // bounding box
1021 
1022  // Ignore all the cells that are outside the extended bounding box
1023  if (cell_inside)
1024  for (unsigned int i = 0; i < subdomain_boundary_cells_radii.size();
1025  ++i)
1026  if (cell_enclosing_ball_center.distance_square(
1027  subdomain_boundary_cells_centers[i]) <
1028  Utilities::fixed_power<2>(cell_enclosing_ball_radius +
1029  subdomain_boundary_cells_radii[i] +
1030  layer_thickness + DOUBLE_EPSILON))
1031  {
1032  active_cell_layer_within_distance.push_back(cell);
1033  break; // Exit the loop checking all the remaining subdomain
1034  // boundary cells
1035  }
1036  }
1037  return active_cell_layer_within_distance;
1038  }
1039 
1040 
1041 
1042  template <class MeshType>
1043  std::vector<typename MeshType::active_cell_iterator>
1045  const double layer_thickness)
1046  {
1047  IteratorFilters::LocallyOwnedCell locally_owned_cell_predicate;
1048  std::function<bool(const typename MeshType::active_cell_iterator &)>
1049  predicate(locally_owned_cell_predicate);
1050 
1051  const std::vector<typename MeshType::active_cell_iterator>
1052  ghost_cell_layer_within_distance =
1054  predicate,
1055  layer_thickness);
1056 
1057  // Check that we never return locally owned or artificial cells
1058  // What is left should only be the ghost cells
1059  Assert(
1060  contains_locally_owned_cells<MeshType>(
1061  ghost_cell_layer_within_distance) == false,
1062  ExcMessage(
1063  "Ghost cells within layer_thickness contains locally owned cells."));
1064  Assert(
1065  contains_artificial_cells<MeshType>(ghost_cell_layer_within_distance) ==
1066  false,
1067  ExcMessage(
1068  "Ghost cells within layer_thickness contains artificial cells."
1069  "The function compute_ghost_cell_layer_within_distance "
1070  "is probably called while using parallel::distributed::Triangulation. "
1071  "In such case please refer to the description of this function."));
1072 
1073  return ghost_cell_layer_within_distance;
1074  }
1075 
1076 
1077 
1078  template <class MeshType>
1079  std::pair<Point<MeshType::space_dimension>, Point<MeshType::space_dimension>>
1081  const MeshType &mesh,
1082  const std::function<bool(const typename MeshType::active_cell_iterator &)>
1083  &predicate)
1084  {
1085  std::vector<bool> locally_active_vertices_on_subdomain(
1086  mesh.get_triangulation().n_vertices(), false);
1087 
1088  const unsigned int spacedim = MeshType::space_dimension;
1089 
1090  // Two extreme points can define the bounding box
1091  // around the active cells that conform to the given predicate.
1093 
1094  // initialize minp and maxp with the first predicate cell center
1095  for (typename MeshType::active_cell_iterator cell = mesh.begin_active();
1096  cell != mesh.end();
1097  ++cell)
1098  if (predicate(cell))
1099  {
1100  minp = cell->center();
1101  maxp = cell->center();
1102  break;
1103  }
1104 
1105  // Run through all the cells to check if it belongs to predicate domain,
1106  // if it belongs to the predicate domain, extend the bounding box.
1107  for (typename MeshType::active_cell_iterator cell = mesh.begin_active();
1108  cell != mesh.end();
1109  ++cell)
1110  if (predicate(cell)) // True predicate --> Part of subdomain
1111  for (unsigned int v = 0;
1112  v < GeometryInfo<MeshType::dimension>::vertices_per_cell;
1113  ++v)
1114  if (locally_active_vertices_on_subdomain[cell->vertex_index(v)] ==
1115  false)
1116  {
1117  locally_active_vertices_on_subdomain[cell->vertex_index(v)] =
1118  true;
1119  for (unsigned int d = 0; d < spacedim; ++d)
1120  {
1121  minp[d] = std::min(minp[d], cell->vertex(v)[d]);
1122  maxp[d] = std::max(maxp[d], cell->vertex(v)[d]);
1123  }
1124  }
1125 
1126  return std::make_pair(minp, maxp);
1127  }
1128 
1129 
1130 
1131  template <typename MeshType>
1132  std::list<std::pair<typename MeshType::cell_iterator,
1133  typename MeshType::cell_iterator>>
1134  get_finest_common_cells(const MeshType &mesh_1, const MeshType &mesh_2)
1135  {
1136  Assert(have_same_coarse_mesh(mesh_1, mesh_2),
1137  ExcMessage("The two meshes must be represent triangulations that "
1138  "have the same coarse meshes"));
1139 
1140  // the algorithm goes as follows:
1141  // first, we fill a list with pairs
1142  // of iterators common to the two
1143  // meshes on the coarsest
1144  // level. then we traverse the
1145  // list; each time, we find a pair
1146  // of iterators for which both
1147  // correspond to non-active cells,
1148  // we delete this item and push the
1149  // pairs of iterators to their
1150  // children to the back. if these
1151  // again both correspond to
1152  // non-active cells, we will get to
1153  // the later on for further
1154  // consideration
1155  using CellList = std::list<std::pair<typename MeshType::cell_iterator,
1156  typename MeshType::cell_iterator>>;
1157  CellList cell_list;
1158 
1159  // first push the coarse level cells
1160  typename MeshType::cell_iterator cell_1 = mesh_1.begin(0),
1161  cell_2 = mesh_2.begin(0);
1162  for (; cell_1 != mesh_1.end(0); ++cell_1, ++cell_2)
1163  cell_list.emplace_back(cell_1, cell_2);
1164 
1165  // then traverse list as described
1166  // above
1167  typename CellList::iterator cell_pair = cell_list.begin();
1168  while (cell_pair != cell_list.end())
1169  {
1170  // if both cells in this pair
1171  // have children, then erase
1172  // this element and push their
1173  // children instead
1174  if (cell_pair->first->has_children() &&
1175  cell_pair->second->has_children())
1176  {
1177  Assert(cell_pair->first->refinement_case() ==
1178  cell_pair->second->refinement_case(),
1179  ExcNotImplemented());
1180  for (unsigned int c = 0; c < cell_pair->first->n_children(); ++c)
1181  cell_list.emplace_back(cell_pair->first->child(c),
1182  cell_pair->second->child(c));
1183 
1184  // erasing an iterator
1185  // keeps other iterators
1186  // valid, so already
1187  // advance the present
1188  // iterator by one and then
1189  // delete the element we've
1190  // visited before
1191  const typename CellList::iterator previous_cell_pair = cell_pair;
1192  ++cell_pair;
1193 
1194  cell_list.erase(previous_cell_pair);
1195  }
1196  else
1197  // both cells are active, do
1198  // nothing
1199  ++cell_pair;
1200  }
1201 
1202  // just to make sure everything is ok,
1203  // validate that all pairs have at least one
1204  // active iterator or have different
1205  // refinement_cases
1206  for (cell_pair = cell_list.begin(); cell_pair != cell_list.end();
1207  ++cell_pair)
1208  Assert(cell_pair->first->active() || cell_pair->second->active() ||
1209  (cell_pair->first->refinement_case() !=
1210  cell_pair->second->refinement_case()),
1211  ExcInternalError());
1212 
1213  return cell_list;
1214  }
1215 
1216 
1217 
1218  template <int dim, int spacedim>
1219  bool
1221  const Triangulation<dim, spacedim> &mesh_2)
1222  {
1223  // make sure the two meshes have
1224  // the same number of coarse cells
1225  if (mesh_1.n_cells(0) != mesh_2.n_cells(0))
1226  return false;
1227 
1228  // if so, also make sure they have
1229  // the same vertices on the cells
1230  // of the coarse mesh
1232  mesh_1.begin(0),
1233  cell_2 =
1234  mesh_2.begin(0),
1235  endc = mesh_1.end(0);
1236  for (; cell_1 != endc; ++cell_1, ++cell_2)
1237  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
1238  if (cell_1->vertex(v) != cell_2->vertex(v))
1239  return false;
1240 
1241  // if we've gotten through all
1242  // this, then the meshes really
1243  // seem to have a common coarse
1244  // mesh
1245  return true;
1246  }
1247 
1248 
1249 
1250  template <typename MeshType>
1251  bool
1252  have_same_coarse_mesh(const MeshType &mesh_1, const MeshType &mesh_2)
1253  {
1254  return have_same_coarse_mesh(mesh_1.get_triangulation(),
1255  mesh_2.get_triangulation());
1256  }
1257 
1258 
1259 
1260  template <int dim, int spacedim>
1261  std::pair<typename hp::DoFHandler<dim, spacedim>::active_cell_iterator,
1262  Point<dim>>
1264  const hp::MappingCollection<dim, spacedim> &mapping,
1265  const hp::DoFHandler<dim, spacedim> & mesh,
1266  const Point<spacedim> & p)
1267  {
1268  Assert((mapping.size() == 1) ||
1269  (mapping.size() == mesh.get_fe_collection().size()),
1270  ExcMessage("Mapping collection needs to have either size 1 "
1271  "or size equal to the number of elements in "
1272  "the FECollection."));
1273 
1274  using cell_iterator =
1276 
1277  std::pair<cell_iterator, Point<dim>> best_cell;
1278  // If we have only one element in the MappingCollection,
1279  // we use find_active_cell_around_point using only one
1280  // mapping.
1281  if (mapping.size() == 1)
1282  best_cell = find_active_cell_around_point(mapping[0], mesh, p);
1283  else
1284  {
1285  // The best distance is set to the
1286  // maximum allowable distance from
1287  // the unit cell; we assume a
1288  // max. deviation of 1e-10
1289  double best_distance = 1e-10;
1290  int best_level = -1;
1291 
1292 
1293  // Find closest vertex and determine
1294  // all adjacent cells
1295  unsigned int vertex = find_closest_vertex(mesh, p);
1296 
1297  std::vector<cell_iterator> adjacent_cells_tmp =
1298  find_cells_adjacent_to_vertex(mesh, vertex);
1299 
1300  // Make sure that we have found
1301  // at least one cell adjacent to vertex.
1302  Assert(adjacent_cells_tmp.size() > 0, ExcInternalError());
1303 
1304  // Copy all the cells into a std::set
1305  std::set<cell_iterator> adjacent_cells(adjacent_cells_tmp.begin(),
1306  adjacent_cells_tmp.end());
1307  std::set<cell_iterator> searched_cells;
1308 
1309  // Determine the maximal number of cells
1310  // in the grid.
1311  // As long as we have not found
1312  // the cell and have not searched
1313  // every cell in the triangulation,
1314  // we keep on looking.
1315  const unsigned int n_cells = mesh.get_triangulation().n_cells();
1316  bool found = false;
1317  unsigned int cells_searched = 0;
1318  while (!found && cells_searched < n_cells)
1319  {
1320  typename std::set<cell_iterator>::const_iterator
1321  cell = adjacent_cells.begin(),
1322  endc = adjacent_cells.end();
1323  for (; cell != endc; ++cell)
1324  {
1325  try
1326  {
1327  const Point<dim> p_cell =
1328  mapping[(*cell)->active_fe_index()]
1329  .transform_real_to_unit_cell(*cell, p);
1330 
1331 
1332  // calculate the infinity norm of
1333  // the distance vector to the unit cell.
1334  const double dist =
1336 
1337  // We compare if the point is inside the
1338  // unit cell (or at least not too far
1339  // outside). If it is, it is also checked
1340  // that the cell has a more refined state
1341  if (dist < best_distance || (dist == best_distance &&
1342  (*cell)->level() > best_level))
1343  {
1344  found = true;
1345  best_distance = dist;
1346  best_level = (*cell)->level();
1347  best_cell = std::make_pair(*cell, p_cell);
1348  }
1349  }
1350  catch (
1351  typename MappingQGeneric<dim,
1352  spacedim>::ExcTransformationFailed &)
1353  {
1354  // ok, the transformation
1355  // failed presumably
1356  // because the point we
1357  // are looking for lies
1358  // outside the current
1359  // cell. this means that
1360  // the current cell can't
1361  // be the cell around the
1362  // point, so just ignore
1363  // this cell and move on
1364  // to the next
1365  }
1366  }
1367  // update the number of cells searched
1368  cells_searched += adjacent_cells.size();
1369  // if we have not found the cell in
1370  // question and have not yet searched every
1371  // cell, we expand our search to
1372  // all the not already searched neighbors of
1373  // the cells in adjacent_cells.
1374  if (!found && cells_searched < n_cells)
1375  {
1376  find_active_cell_around_point_internal<dim,
1378  spacedim>(
1379  mesh, searched_cells, adjacent_cells);
1380  }
1381  }
1382  }
1383 
1384  AssertThrow(best_cell.first.state() == IteratorState::valid,
1385  ExcPointNotFound<spacedim>(p));
1386 
1387  return best_cell;
1388  }
1389 
1390 
1391  template <class MeshType>
1392  std::vector<typename MeshType::active_cell_iterator>
1393  get_patch_around_cell(const typename MeshType::active_cell_iterator &cell)
1394  {
1395  Assert(cell->is_locally_owned(),
1396  ExcMessage("This function only makes sense if the cell for "
1397  "which you are asking for a patch, is locally "
1398  "owned."));
1399 
1400  std::vector<typename MeshType::active_cell_iterator> patch;
1401  patch.push_back(cell);
1402  for (unsigned int face_number = 0;
1403  face_number < GeometryInfo<MeshType::dimension>::faces_per_cell;
1404  ++face_number)
1405  if (cell->face(face_number)->at_boundary() == false)
1406  {
1407  if (cell->neighbor(face_number)->has_children() == false)
1408  patch.push_back(cell->neighbor(face_number));
1409  else
1410  // the neighbor is refined. in 2d/3d, we can simply ask for the
1411  // children of the neighbor because they can not be further refined
1412  // and, consequently, the children is active
1413  if (MeshType::dimension > 1)
1414  {
1415  for (unsigned int subface = 0;
1416  subface < cell->face(face_number)->n_children();
1417  ++subface)
1418  patch.push_back(
1419  cell->neighbor_child_on_subface(face_number, subface));
1420  }
1421  else
1422  {
1423  // in 1d, we need to work a bit harder: iterate until we find
1424  // the child by going from cell to child to child etc
1425  typename MeshType::cell_iterator neighbor =
1426  cell->neighbor(face_number);
1427  while (neighbor->has_children())
1428  neighbor = neighbor->child(1 - face_number);
1429 
1430  Assert(neighbor->neighbor(1 - face_number) == cell,
1431  ExcInternalError());
1432  patch.push_back(neighbor);
1433  }
1434  }
1435  return patch;
1436  }
1437 
1438 
1439 
1440  template <class Container>
1441  std::vector<typename Container::cell_iterator>
1443  const std::vector<typename Container::active_cell_iterator> &patch)
1444  {
1445  Assert(patch.size() > 0,
1446  ExcMessage(
1447  "Vector containing patch cells should not be an empty vector!"));
1448  // In order to extract the set of cells with the coarsest common level from
1449  // the give vector of cells: First it finds the number associated with the
1450  // minimum level of refinmenet, namely "min_level"
1451  int min_level = patch[0]->level();
1452 
1453  for (unsigned int i = 0; i < patch.size(); ++i)
1454  min_level = std::min(min_level, patch[i]->level());
1455  std::set<typename Container::cell_iterator> uniform_cells;
1456  typename std::vector<
1457  typename Container::active_cell_iterator>::const_iterator patch_cell;
1458  // it loops through all cells of the input vector
1459  for (patch_cell = patch.begin(); patch_cell != patch.end(); ++patch_cell)
1460  {
1461  // If the refinement level of each cell i the loop be equal to the
1462  // min_level, so that that cell inserted into the set of uniform_cells,
1463  // as the set of cells with the coarsest common refinement level
1464  if ((*patch_cell)->level() == min_level)
1465  uniform_cells.insert(*patch_cell);
1466  else
1467  // If not, it asks for the parent of the cell, until it finds the
1468  // parent cell with the refinement level equal to the min_level and
1469  // inserts that parent cell into the the set of uniform_cells, as the
1470  // set of cells with the coarsest common refinement level.
1471  {
1472  typename Container::cell_iterator parent = *patch_cell;
1473 
1474  while (parent->level() > min_level)
1475  parent = parent->parent();
1476  uniform_cells.insert(parent);
1477  }
1478  }
1479 
1480  return std::vector<typename Container::cell_iterator>(uniform_cells.begin(),
1481  uniform_cells.end());
1482  }
1483 
1484 
1485 
1486  template <class Container>
1487  void
1489  const std::vector<typename Container::active_cell_iterator> &patch,
1491  &local_triangulation,
1492  std::map<
1493  typename Triangulation<Container::dimension,
1494  Container::space_dimension>::active_cell_iterator,
1495  typename Container::active_cell_iterator> &patch_to_global_tria_map)
1496 
1497  {
1498  const std::vector<typename Container::cell_iterator> uniform_cells =
1499  get_cells_at_coarsest_common_level<Container>(patch);
1500  // First it creates triangulation from the vector of "uniform_cells"
1501  local_triangulation.clear();
1502  std::vector<Point<Container::space_dimension>> vertices;
1503  const unsigned int n_uniform_cells = uniform_cells.size();
1504  std::vector<CellData<Container::dimension>> cells(n_uniform_cells);
1505  unsigned int k = 0; // for enumerating cells
1506  unsigned int i = 0; // for enumerating vertices
1507  typename std::vector<typename Container::cell_iterator>::const_iterator
1508  uniform_cell;
1509  for (uniform_cell = uniform_cells.begin();
1510  uniform_cell != uniform_cells.end();
1511  ++uniform_cell)
1512  {
1513  for (unsigned int v = 0;
1514  v < GeometryInfo<Container::dimension>::vertices_per_cell;
1515  ++v)
1516  {
1518  (*uniform_cell)->vertex(v);
1519  bool repeat_vertex = false;
1520 
1521  for (unsigned int m = 0; m < i; ++m)
1522  {
1523  if (position == vertices[m])
1524  {
1525  repeat_vertex = true;
1526  cells[k].vertices[v] = m;
1527  break;
1528  }
1529  }
1530  if (repeat_vertex == false)
1531  {
1532  vertices.push_back(position);
1533  cells[k].vertices[v] = i;
1534  i = i + 1;
1535  }
1536 
1537  } // for vertices_per_cell
1538  k = k + 1;
1539  }
1540  local_triangulation.create_triangulation(vertices, cells, SubCellData());
1541  Assert(local_triangulation.n_active_cells() == uniform_cells.size(),
1542  ExcInternalError());
1543  local_triangulation.clear_user_flags();
1544  unsigned int index = 0;
1545  // Create a map between cells of class DoFHandler into class Triangulation
1546  std::map<typename Triangulation<Container::dimension,
1547  Container::space_dimension>::cell_iterator,
1548  typename Container::cell_iterator>
1549  patch_to_global_tria_map_tmp;
1550  for (typename Triangulation<Container::dimension,
1551  Container::space_dimension>::cell_iterator
1552  coarse_cell = local_triangulation.begin();
1553  coarse_cell != local_triangulation.end();
1554  ++coarse_cell, ++index)
1555  {
1556  patch_to_global_tria_map_tmp.insert(
1557  std::make_pair(coarse_cell, uniform_cells[index]));
1558  // To ensure that the cells with the same coordinates (here, we compare
1559  // their centers) are mapped into each other.
1560 
1561  Assert(coarse_cell->center().distance(uniform_cells[index]->center()) <=
1562  1e-15 * coarse_cell->diameter(),
1563  ExcInternalError());
1564  }
1565  bool refinement_necessary;
1566  // In this loop we start to do refinement on the above coarse triangulation
1567  // to reach to the same level of refinement as the patch cells are really on
1568  do
1569  {
1570  refinement_necessary = false;
1571  for (typename Triangulation<Container::dimension,
1572  Container::space_dimension>::
1573  active_cell_iterator active_tria_cell =
1574  local_triangulation.begin_active();
1575  active_tria_cell != local_triangulation.end();
1576  ++active_tria_cell)
1577  {
1578  if (patch_to_global_tria_map_tmp[active_tria_cell]->has_children())
1579  {
1580  active_tria_cell->set_refine_flag();
1581  refinement_necessary = true;
1582  }
1583  else
1584  for (unsigned int i = 0; i < patch.size(); ++i)
1585  {
1586  // Even though vertices may not be exactly the same, the
1587  // appropriate cells will match since == for TriAccessors
1588  // checks only cell level and index.
1589  if (patch_to_global_tria_map_tmp[active_tria_cell] ==
1590  patch[i])
1591  {
1592  // adjust the cell vertices of the local_triangulation to
1593  // match cell vertices of the global triangulation
1594  for (unsigned int v = 0;
1595  v < GeometryInfo<
1596  Container::dimension>::vertices_per_cell;
1597  ++v)
1598  active_tria_cell->vertex(v) = patch[i]->vertex(v);
1599 
1600  Assert(active_tria_cell->center().distance(
1601  patch_to_global_tria_map_tmp[active_tria_cell]
1602  ->center()) <=
1603  1e-15 * active_tria_cell->diameter(),
1604  ExcInternalError());
1605 
1606  active_tria_cell->set_user_flag();
1607  break;
1608  }
1609  }
1610  }
1611 
1612  if (refinement_necessary)
1613  {
1614  local_triangulation.execute_coarsening_and_refinement();
1615 
1616  for (typename Triangulation<
1617  Container::dimension,
1618  Container::space_dimension>::cell_iterator cell =
1619  local_triangulation.begin();
1620  cell != local_triangulation.end();
1621  ++cell)
1622  {
1623  if (patch_to_global_tria_map_tmp.find(cell) !=
1624  patch_to_global_tria_map_tmp.end())
1625  {
1626  if (cell->has_children())
1627  {
1628  // Note: Since the cell got children, then it should not
1629  // be in the map anymore children may be added into the
1630  // map, instead
1631 
1632  // these children may not yet be in the map
1633  for (unsigned int c = 0; c < cell->n_children(); ++c)
1634  {
1635  if (patch_to_global_tria_map_tmp.find(cell->child(
1636  c)) == patch_to_global_tria_map_tmp.end())
1637  {
1638  patch_to_global_tria_map_tmp.insert(
1639  std::make_pair(
1640  cell->child(c),
1641  patch_to_global_tria_map_tmp[cell]->child(
1642  c)));
1643 
1644  // One might be tempted to assert that the cell
1645  // being added here has the same center as the
1646  // equivalent cell in the global triangulation,
1647  // but it may not be the case. For
1648  // triangulations that have been perturbed or
1649  // smoothed, the cell indices and levels may be
1650  // the same, but the vertex locations may not.
1651  // We adjust the vertices of the cells that have
1652  // no children (ie the active cells) to be
1653  // consistent with the global triangulation
1654  // later on and add assertions at that time
1655  // to guarantee the cells in the
1656  // local_triangulation are physically at the
1657  // same locations of the cells in the patch of
1658  // the global triangulation.
1659  }
1660  }
1661  // The parent cell whose children were added
1662  // into the map should be deleted from the map
1663  patch_to_global_tria_map_tmp.erase(cell);
1664  }
1665  }
1666  }
1667  }
1668  }
1669  while (refinement_necessary);
1670 
1671 
1672  // Last assertion check to make sure we have the right cells and centers
1673  // in the map, and hence the correct vertices of the triangulation
1674  for (typename Triangulation<Container::dimension,
1675  Container::space_dimension>::cell_iterator
1676  cell = local_triangulation.begin();
1677  cell != local_triangulation.end();
1678  ++cell)
1679  {
1680  if (cell->user_flag_set())
1681  {
1682  Assert(patch_to_global_tria_map_tmp.find(cell) !=
1683  patch_to_global_tria_map_tmp.end(),
1684  ExcInternalError());
1685 
1686  Assert(cell->center().distance(
1687  patch_to_global_tria_map_tmp[cell]->center()) <=
1688  1e-15 * cell->diameter(),
1689  ExcInternalError());
1690  }
1691  }
1692 
1693 
1694  typename std::map<
1695  typename Triangulation<Container::dimension,
1696  Container::space_dimension>::cell_iterator,
1697  typename Container::cell_iterator>::iterator
1698  map_tmp_it = patch_to_global_tria_map_tmp.begin(),
1699  map_tmp_end = patch_to_global_tria_map_tmp.end();
1700  // Now we just need to take the temporary map of pairs of type cell_iterator
1701  // "patch_to_global_tria_map_tmp" making pair of active_cell_iterators so
1702  // that filling out the final map "patch_to_global_tria_map"
1703  for (; map_tmp_it != map_tmp_end; ++map_tmp_it)
1704  patch_to_global_tria_map[map_tmp_it->first] = map_tmp_it->second;
1705  }
1706 
1707 
1708 
1709  template <class DoFHandlerType>
1710  std::map<types::global_dof_index,
1711  std::vector<typename DoFHandlerType::active_cell_iterator>>
1712  get_dof_to_support_patch_map(DoFHandlerType &dof_handler)
1713  {
1714  // This is the map from global_dof_index to
1715  // a set of cells on patch. We first map into
1716  // a set because it is very likely that we
1717  // will attempt to add a cell more than once
1718  // to a particular patch and we want to preserve
1719  // uniqueness of cell iterators. std::set does this
1720  // automatically for us. Later after it is all
1721  // constructed, we will copy to a map of vectors
1722  // since that is the preferred output for other
1723  // functions.
1724  std::map<types::global_dof_index,
1725  std::set<typename DoFHandlerType::active_cell_iterator>>
1726  dof_to_set_of_cells_map;
1727 
1728  std::vector<types::global_dof_index> local_dof_indices;
1729  std::vector<types::global_dof_index> local_face_dof_indices;
1730  std::vector<types::global_dof_index> local_line_dof_indices;
1731 
1732  // a place to save the dof_handler user flags and restore them later
1733  // to maintain const of dof_handler.
1734  std::vector<bool> user_flags;
1735 
1736 
1737  // in 3d, we need pointers from active lines to the
1738  // active parent lines, so we construct it as needed.
1739  std::map<typename DoFHandlerType::active_line_iterator,
1740  typename DoFHandlerType::line_iterator>
1741  lines_to_parent_lines_map;
1742  if (DoFHandlerType::dimension == 3)
1743  {
1744  // save user flags as they will be modified and then later restored
1745  dof_handler.get_triangulation().save_user_flags(user_flags);
1746  const_cast<::Triangulation<DoFHandlerType::dimension,
1747  DoFHandlerType::space_dimension> &>(
1748  dof_handler.get_triangulation())
1749  .clear_user_flags();
1750 
1751 
1752  typename DoFHandlerType::active_cell_iterator cell = dof_handler
1753  .begin_active(),
1754  endc = dof_handler.end();
1755  for (; cell != endc; ++cell)
1756  {
1757  // We only want lines that are locally_relevant
1758  // although it doesn't hurt to have lines that
1759  // are children of ghost cells since there are
1760  // few and we don't have to use them.
1761  if (cell->is_artificial() == false)
1762  {
1763  for (unsigned int l = 0;
1764  l <
1766  ++l)
1767  if (cell->line(l)->has_children())
1768  for (unsigned int c = 0; c < cell->line(l)->n_children();
1769  ++c)
1770  {
1771  lines_to_parent_lines_map[cell->line(l)->child(c)] =
1772  cell->line(l);
1773  // set flags to know that child
1774  // line has an active parent.
1775  cell->line(l)->child(c)->set_user_flag();
1776  }
1777  }
1778  }
1779  }
1780 
1781 
1782  // We loop through all cells and add cell to the
1783  // map for the dofs that it immediately touches
1784  // and then account for all the other dofs of
1785  // which it is a part, mainly the ones that must
1786  // be added on account of adaptivity hanging node
1787  // constraints.
1788  typename DoFHandlerType::active_cell_iterator cell =
1789  dof_handler.begin_active(),
1790  endc = dof_handler.end();
1791  for (; cell != endc; ++cell)
1792  {
1793  // Need to loop through all cells that could
1794  // be in the patch of dofs on locally_owned
1795  // cells including ghost cells
1796  if (cell->is_artificial() == false)
1797  {
1798  const unsigned int n_dofs_per_cell = cell->get_fe().dofs_per_cell;
1799  local_dof_indices.resize(n_dofs_per_cell);
1800 
1801  // Take care of adding cell pointer to each
1802  // dofs that exists on cell.
1803  cell->get_dof_indices(local_dof_indices);
1804  for (unsigned int i = 0; i < n_dofs_per_cell; ++i)
1805  dof_to_set_of_cells_map[local_dof_indices[i]].insert(cell);
1806 
1807  // In the case of the adjacent cell (over
1808  // faces or edges) being more refined, we
1809  // want to add all of the children to the
1810  // patch since the support function at that
1811  // dof could be non-zero along that entire
1812  // face (or line).
1813 
1814  // Take care of dofs on neighbor faces
1815  for (unsigned int f = 0;
1816  f < GeometryInfo<DoFHandlerType::dimension>::faces_per_cell;
1817  ++f)
1818  {
1819  if (cell->face(f)->has_children())
1820  {
1821  for (unsigned int c = 0; c < cell->face(f)->n_children();
1822  ++c)
1823  {
1824  // Add cell to dofs of all subfaces
1825  //
1826  // *-------------------*----------*---------*
1827  // | | add cell | |
1828  // | |<- to dofs| |
1829  // | |of subface| |
1830  // | cell *----------*---------*
1831  // | | add cell | |
1832  // | |<- to dofs| |
1833  // | |of subface| |
1834  // *-------------------*----------*---------*
1835  //
1836  Assert(cell->face(f)->child(c)->has_children() == false,
1837  ExcInternalError());
1838 
1839  const unsigned int n_dofs_per_face =
1840  cell->get_fe().dofs_per_face;
1841  local_face_dof_indices.resize(n_dofs_per_face);
1842 
1843  cell->face(f)->child(c)->get_dof_indices(
1844  local_face_dof_indices);
1845  for (unsigned int i = 0; i < n_dofs_per_face; ++i)
1846  dof_to_set_of_cells_map[local_face_dof_indices[i]]
1847  .insert(cell);
1848  }
1849  }
1850  else if ((cell->face(f)->at_boundary() == false) &&
1851  (cell->neighbor_is_coarser(f)))
1852  {
1853  // Add cell to dofs of parent face and all
1854  // child faces of parent face
1855  //
1856  // *-------------------*----------*---------*
1857  // | | | |
1858  // | | cell | |
1859  // | add cell | | |
1860  // | to dofs -> *----------*---------*
1861  // | of parent | add cell | |
1862  // | face |<- to dofs| |
1863  // | |of subface| |
1864  // *-------------------*----------*---------*
1865  //
1866 
1867  // Add cell to all dofs of parent face
1868  std::pair<unsigned int, unsigned int>
1869  neighbor_face_no_subface_no =
1870  cell->neighbor_of_coarser_neighbor(f);
1871  unsigned int face_no = neighbor_face_no_subface_no.first;
1872  unsigned int subface = neighbor_face_no_subface_no.second;
1873 
1874  const unsigned int n_dofs_per_face =
1875  cell->get_fe().dofs_per_face;
1876  local_face_dof_indices.resize(n_dofs_per_face);
1877 
1878  cell->neighbor(f)->face(face_no)->get_dof_indices(
1879  local_face_dof_indices);
1880  for (unsigned int i = 0; i < n_dofs_per_face; ++i)
1881  dof_to_set_of_cells_map[local_face_dof_indices[i]].insert(
1882  cell);
1883 
1884  // Add cell to all dofs of children of
1885  // parent face
1886  for (unsigned int c = 0;
1887  c < cell->neighbor(f)->face(face_no)->n_children();
1888  ++c)
1889  {
1890  if (c != subface) // don't repeat work on dofs of
1891  // original cell
1892  {
1893  const unsigned int n_dofs_per_face =
1894  cell->get_fe().dofs_per_face;
1895  local_face_dof_indices.resize(n_dofs_per_face);
1896 
1897  Assert(cell->neighbor(f)
1898  ->face(face_no)
1899  ->child(c)
1900  ->has_children() == false,
1901  ExcInternalError());
1902  cell->neighbor(f)
1903  ->face(face_no)
1904  ->child(c)
1905  ->get_dof_indices(local_face_dof_indices);
1906  for (unsigned int i = 0; i < n_dofs_per_face; ++i)
1907  dof_to_set_of_cells_map[local_face_dof_indices[i]]
1908  .insert(cell);
1909  }
1910  }
1911  }
1912  }
1913 
1914 
1915  // If 3d, take care of dofs on lines in the
1916  // same pattern as faces above. That is, if
1917  // a cell's line has children, distribute
1918  // cell to dofs of children of line, and
1919  // if cell's line has an active parent, then
1920  // distribute cell to dofs on parent line
1921  // and dofs on all children of parent line.
1922  if (DoFHandlerType::dimension == 3)
1923  {
1924  for (unsigned int l = 0;
1925  l <
1927  ++l)
1928  {
1929  if (cell->line(l)->has_children())
1930  {
1931  for (unsigned int c = 0;
1932  c < cell->line(l)->n_children();
1933  ++c)
1934  {
1935  Assert(cell->line(l)->child(c)->has_children() ==
1936  false,
1937  ExcInternalError());
1938 
1939  // dofs_per_line returns number of dofs
1940  // on line not including the vertices of the line.
1941  const unsigned int n_dofs_per_line =
1942  2 * cell->get_fe().dofs_per_vertex +
1943  cell->get_fe().dofs_per_line;
1944  local_line_dof_indices.resize(n_dofs_per_line);
1945 
1946  cell->line(l)->child(c)->get_dof_indices(
1947  local_line_dof_indices);
1948  for (unsigned int i = 0; i < n_dofs_per_line; ++i)
1949  dof_to_set_of_cells_map[local_line_dof_indices[i]]
1950  .insert(cell);
1951  }
1952  }
1953  // user flag was set above to denote that
1954  // an active parent line exists so add
1955  // cell to dofs of parent and all it's
1956  // children
1957  else if (cell->line(l)->user_flag_set() == true)
1958  {
1959  typename DoFHandlerType::line_iterator parent_line =
1960  lines_to_parent_lines_map[cell->line(l)];
1961  Assert(parent_line->has_children(), ExcInternalError());
1962 
1963  // dofs_per_line returns number of dofs
1964  // on line not including the vertices of the line.
1965  const unsigned int n_dofs_per_line =
1966  2 * cell->get_fe().dofs_per_vertex +
1967  cell->get_fe().dofs_per_line;
1968  local_line_dof_indices.resize(n_dofs_per_line);
1969 
1970  parent_line->get_dof_indices(local_line_dof_indices);
1971  for (unsigned int i = 0; i < n_dofs_per_line; ++i)
1972  dof_to_set_of_cells_map[local_line_dof_indices[i]]
1973  .insert(cell);
1974 
1975  for (unsigned int c = 0; c < parent_line->n_children();
1976  ++c)
1977  {
1978  Assert(parent_line->child(c)->has_children() ==
1979  false,
1980  ExcInternalError());
1981 
1982  const unsigned int n_dofs_per_line =
1983  2 * cell->get_fe().dofs_per_vertex +
1984  cell->get_fe().dofs_per_line;
1985  local_line_dof_indices.resize(n_dofs_per_line);
1986 
1987  parent_line->child(c)->get_dof_indices(
1988  local_line_dof_indices);
1989  for (unsigned int i = 0; i < n_dofs_per_line; ++i)
1990  dof_to_set_of_cells_map[local_line_dof_indices[i]]
1991  .insert(cell);
1992  }
1993  }
1994  } // for lines l
1995  } // if DoFHandlerType::dimension == 3
1996  } // if cell->is_locally_owned()
1997  } // for cells
1998 
1999 
2000  if (DoFHandlerType::dimension == 3)
2001  {
2002  // finally, restore user flags that were changed above
2003  // to when we constructed the pointers to parent of lines
2004  // Since dof_handler is const, we must leave it unchanged.
2005  const_cast<::Triangulation<DoFHandlerType::dimension,
2006  DoFHandlerType::space_dimension> &>(
2007  dof_handler.get_triangulation())
2008  .load_user_flags(user_flags);
2009  }
2010 
2011  // Finally, we copy map of sets to
2012  // map of vectors using the std::vector::assign() function
2013  std::map<types::global_dof_index,
2014  std::vector<typename DoFHandlerType::active_cell_iterator>>
2015  dof_to_cell_patches;
2016 
2017  typename std::map<types::global_dof_index,
2018  std::set<typename DoFHandlerType::active_cell_iterator>>::
2019  iterator it = dof_to_set_of_cells_map.begin(),
2020  it_end = dof_to_set_of_cells_map.end();
2021  for (; it != it_end; ++it)
2022  dof_to_cell_patches[it->first].assign(it->second.begin(),
2023  it->second.end());
2024 
2025  return dof_to_cell_patches;
2026  }
2027 
2028  /*
2029  * Internally used in collect_periodic_faces
2030  */
2031  template <typename CellIterator>
2032  void
2033  match_periodic_face_pairs(
2034  std::set<std::pair<CellIterator, unsigned int>> &pairs1,
2035  std::set<std::pair<typename identity<CellIterator>::type, unsigned int>>
2036  & pairs2,
2037  const int direction,
2038  std::vector<PeriodicFacePair<CellIterator>> &matched_pairs,
2039  const ::Tensor<1, CellIterator::AccessorType::space_dimension>
2040  & offset,
2041  const FullMatrix<double> &matrix)
2042  {
2043  static const int space_dim = CellIterator::AccessorType::space_dimension;
2044  (void)space_dim;
2045  Assert(0 <= direction && direction < space_dim,
2046  ExcIndexRange(direction, 0, space_dim));
2047 
2048  Assert(pairs1.size() == pairs2.size(),
2049  ExcMessage("Unmatched faces on periodic boundaries"));
2050 
2051  unsigned int n_matches = 0;
2052 
2053  // Match with a complexity of O(n^2). This could be improved...
2054  std::bitset<3> orientation;
2055  using PairIterator =
2056  typename std::set<std::pair<CellIterator, unsigned int>>::const_iterator;
2057  for (PairIterator it1 = pairs1.begin(); it1 != pairs1.end(); ++it1)
2058  {
2059  for (PairIterator it2 = pairs2.begin(); it2 != pairs2.end(); ++it2)
2060  {
2061  const CellIterator cell1 = it1->first;
2062  const CellIterator cell2 = it2->first;
2063  const unsigned int face_idx1 = it1->second;
2064  const unsigned int face_idx2 = it2->second;
2065  if (GridTools::orthogonal_equality(orientation,
2066  cell1->face(face_idx1),
2067  cell2->face(face_idx2),
2068  direction,
2069  offset,
2070  matrix))
2071  {
2072  // We have a match, so insert the matching pairs and
2073  // remove the matched cell in pairs2 to speed up the
2074  // matching:
2075  const PeriodicFacePair<CellIterator> matched_face = {
2076  {cell1, cell2}, {face_idx1, face_idx2}, orientation, matrix};
2077  matched_pairs.push_back(matched_face);
2078  pairs2.erase(it2);
2079  ++n_matches;
2080  break;
2081  }
2082  }
2083  }
2084 
2085  // Assure that all faces are matched
2086  AssertThrow(n_matches == pairs1.size() && pairs2.size() == 0,
2087  ExcMessage("Unmatched faces on periodic boundaries"));
2088  }
2089 
2090 
2091 
2092  template <typename MeshType>
2093  void
2095  const MeshType & mesh,
2096  const types::boundary_id b_id,
2097  const int direction,
2099  & matched_pairs,
2101  const FullMatrix<double> & matrix)
2102  {
2103  static const int dim = MeshType::dimension;
2104  static const int space_dim = MeshType::space_dimension;
2105  (void)dim;
2106  (void)space_dim;
2107  Assert(0 <= direction && direction < space_dim,
2108  ExcIndexRange(direction, 0, space_dim));
2109 
2110  Assert(dim == space_dim, ExcNotImplemented());
2111 
2112  // Loop over all cells on the highest level and collect all boundary
2113  // faces 2*direction and 2*direction*1:
2114 
2115  std::set<std::pair<typename MeshType::cell_iterator, unsigned int>> pairs1;
2116  std::set<std::pair<typename MeshType::cell_iterator, unsigned int>> pairs2;
2117 
2118  for (typename MeshType::cell_iterator cell = mesh.begin(0);
2119  cell != mesh.end(0);
2120  ++cell)
2121  {
2122  const typename MeshType::face_iterator face_1 =
2123  cell->face(2 * direction);
2124  const typename MeshType::face_iterator face_2 =
2125  cell->face(2 * direction + 1);
2126 
2127  if (face_1->at_boundary() && face_1->boundary_id() == b_id)
2128  {
2129  const std::pair<typename MeshType::cell_iterator, unsigned int>
2130  pair1 = std::make_pair(cell, 2 * direction);
2131  pairs1.insert(pair1);
2132  }
2133 
2134  if (face_2->at_boundary() && face_2->boundary_id() == b_id)
2135  {
2136  const std::pair<typename MeshType::cell_iterator, unsigned int>
2137  pair2 = std::make_pair(cell, 2 * direction + 1);
2138  pairs2.insert(pair2);
2139  }
2140  }
2141 
2142  Assert(pairs1.size() == pairs2.size(),
2143  ExcMessage("Unmatched faces on periodic boundaries"));
2144 
2145  Assert(pairs1.size() > 0,
2146  ExcMessage("No new periodic face pairs have been found. "
2147  "Are you sure that you've selected the correct boundary "
2148  "id's and that the coarsest level mesh is colorized?"));
2149 
2150 #ifdef DEBUG
2151  const unsigned int size_old = matched_pairs.size();
2152 #endif
2153 
2154  // and call match_periodic_face_pairs that does the actual matching:
2155  match_periodic_face_pairs(
2156  pairs1, pairs2, direction, matched_pairs, offset, matrix);
2157 
2158 #ifdef DEBUG
2159  // check for standard orientation
2160  const unsigned int size_new = matched_pairs.size();
2161  for (unsigned int i = size_old; i < size_new; ++i)
2162  {
2163  Assert(matched_pairs[i].orientation == 1,
2164  ExcMessage(
2165  "Found a face match with non standard orientation. "
2166  "This function is only suitable for meshes with cells "
2167  "in default orientation"));
2168  }
2169 #endif
2170  }
2171 
2172 
2173 
2174  template <typename MeshType>
2175  void
2177  const MeshType & mesh,
2178  const types::boundary_id b_id1,
2179  const types::boundary_id b_id2,
2180  const int direction,
2182  & matched_pairs,
2184  const FullMatrix<double> & matrix)
2185  {
2186  static const int dim = MeshType::dimension;
2187  static const int space_dim = MeshType::space_dimension;
2188  (void)dim;
2189  (void)space_dim;
2190  Assert(0 <= direction && direction < space_dim,
2191  ExcIndexRange(direction, 0, space_dim));
2192 
2193  // Loop over all cells on the highest level and collect all boundary
2194  // faces belonging to b_id1 and b_id2:
2195 
2196  std::set<std::pair<typename MeshType::cell_iterator, unsigned int>> pairs1;
2197  std::set<std::pair<typename MeshType::cell_iterator, unsigned int>> pairs2;
2198 
2199  for (typename MeshType::cell_iterator cell = mesh.begin(0);
2200  cell != mesh.end(0);
2201  ++cell)
2202  {
2203  for (unsigned int i = 0; i < GeometryInfo<dim>::faces_per_cell; ++i)
2204  {
2205  const typename MeshType::face_iterator face = cell->face(i);
2206  if (face->at_boundary() && face->boundary_id() == b_id1)
2207  {
2208  const std::pair<typename MeshType::cell_iterator, unsigned int>
2209  pair1 = std::make_pair(cell, i);
2210  pairs1.insert(pair1);
2211  }
2212 
2213  if (face->at_boundary() && face->boundary_id() == b_id2)
2214  {
2215  const std::pair<typename MeshType::cell_iterator, unsigned int>
2216  pair2 = std::make_pair(cell, i);
2217  pairs2.insert(pair2);
2218  }
2219  }
2220  }
2221 
2222  Assert(pairs1.size() == pairs2.size(),
2223  ExcMessage("Unmatched faces on periodic boundaries"));
2224 
2225  Assert(pairs1.size() > 0,
2226  ExcMessage("No new periodic face pairs have been found. "
2227  "Are you sure that you've selected the correct boundary "
2228  "id's and that the coarsest level mesh is colorized?"));
2229 
2230  // and call match_periodic_face_pairs that does the actual matching:
2231  match_periodic_face_pairs(
2232  pairs1, pairs2, direction, matched_pairs, offset, matrix);
2233  }
2234 
2235 
2236 
2237  /*
2238  * Internally used in orthogonal_equality
2239  *
2240  * An orthogonal equality test for points:
2241  *
2242  * point1 and point2 are considered equal, if
2243  * matrix.point1 + offset - point2
2244  * is parallel to the unit vector in <direction>
2245  */
2246  template <int spacedim>
2247  inline bool
2248  orthogonal_equality(const Point<spacedim> & point1,
2249  const Point<spacedim> & point2,
2250  const int direction,
2251  const Tensor<1, spacedim> &offset,
2252  const FullMatrix<double> & matrix)
2253  {
2254  Assert(0 <= direction && direction < spacedim,
2255  ExcIndexRange(direction, 0, spacedim));
2256 
2257  Assert(matrix.m() == matrix.n(), ExcInternalError());
2258 
2259  Point<spacedim> distance;
2260 
2261  if (matrix.m() == spacedim)
2262  for (int i = 0; i < spacedim; ++i)
2263  for (int j = 0; j < spacedim; ++j)
2264  distance(i) += matrix(i, j) * point1(j);
2265  else
2266  distance = point1;
2267 
2268  distance += offset - point2;
2269 
2270  for (int i = 0; i < spacedim; ++i)
2271  {
2272  // Only compare coordinate-components != direction:
2273  if (i == direction)
2274  continue;
2275 
2276  if (fabs(distance(i)) > 1.e-10)
2277  return false;
2278  }
2279 
2280  return true;
2281  }
2282 
2283 
2284  /*
2285  * Internally used in orthogonal_equality
2286  *
2287  * A lookup table to transform vertex matchings to orientation flags of
2288  * the form (face_orientation, face_flip, face_rotation)
2289  *
2290  * See the comment on the next function as well as the detailed
2291  * documentation of make_periodicity_constraints and
2292  * collect_periodic_faces for details
2293  */
2294  template <int dim>
2295  struct OrientationLookupTable
2296  {};
2297 
2298  template <>
2299  struct OrientationLookupTable<1>
2300  {
2301  using MATCH_T =
2302  std::array<unsigned int, GeometryInfo<1>::vertices_per_face>;
2303  static inline std::bitset<3>
2304  lookup(const MATCH_T &)
2305  {
2306  // The 1D case is trivial
2307  return 1; // [true ,false,false]
2308  }
2309  };
2310 
2311  template <>
2312  struct OrientationLookupTable<2>
2313  {
2314  using MATCH_T =
2315  std::array<unsigned int, GeometryInfo<2>::vertices_per_face>;
2316  static inline std::bitset<3>
2317  lookup(const MATCH_T &matching)
2318  {
2319  // In 2D matching faces (=lines) results in two cases: Either
2320  // they are aligned or flipped. We store this "line_flip"
2321  // property somewhat sloppy as "face_flip"
2322  // (always: face_orientation = true, face_rotation = false)
2323 
2324  static const MATCH_T m_tff = {{0, 1}};
2325  if (matching == m_tff)
2326  return 1; // [true ,false,false]
2327  static const MATCH_T m_ttf = {{1, 0}};
2328  if (matching == m_ttf)
2329  return 3; // [true ,true ,false]
2330  Assert(false, ExcInternalError());
2331  // what follows is dead code, but it avoids warnings about the lack
2332  // of a return value
2333  return 0;
2334  }
2335  };
2336 
2337  template <>
2338  struct OrientationLookupTable<3>
2339  {
2340  using MATCH_T =
2341  std::array<unsigned int, GeometryInfo<3>::vertices_per_face>;
2342  static inline std::bitset<3>
2343  lookup(const MATCH_T &matching)
2344  {
2345  // The full fledged 3D case. *Yay*
2346  // See the documentation in include/deal.II/base/geometry_info.h
2347  // as well as the actual implementation in source/grid/tria.cc
2348  // for more details...
2349 
2350  static const MATCH_T m_tff = {{0, 1, 2, 3}};
2351  if (matching == m_tff)
2352  return 1; // [true ,false,false]
2353  static const MATCH_T m_tft = {{1, 3, 0, 2}};
2354  if (matching == m_tft)
2355  return 5; // [true ,false,true ]
2356  static const MATCH_T m_ttf = {{3, 2, 1, 0}};
2357  if (matching == m_ttf)
2358  return 3; // [true ,true ,false]
2359  static const MATCH_T m_ttt = {{2, 0, 3, 1}};
2360  if (matching == m_ttt)
2361  return 7; // [true ,true ,true ]
2362  static const MATCH_T m_fff = {{0, 2, 1, 3}};
2363  if (matching == m_fff)
2364  return 0; // [false,false,false]
2365  static const MATCH_T m_fft = {{2, 3, 0, 1}};
2366  if (matching == m_fft)
2367  return 4; // [false,false,true ]
2368  static const MATCH_T m_ftf = {{3, 1, 2, 0}};
2369  if (matching == m_ftf)
2370  return 2; // [false,true ,false]
2371  static const MATCH_T m_ftt = {{1, 0, 3, 2}};
2372  if (matching == m_ftt)
2373  return 6; // [false,true ,true ]
2374  Assert(false, ExcInternalError());
2375  // what follows is dead code, but it avoids warnings about the lack
2376  // of a return value
2377  return 0;
2378  }
2379  };
2380 
2381 
2382 
2383  template <typename FaceIterator>
2384  inline bool orthogonal_equality(
2385  std::bitset<3> & orientation,
2386  const FaceIterator & face1,
2387  const FaceIterator & face2,
2388  const int direction,
2390  const FullMatrix<double> & matrix)
2391  {
2392  Assert(matrix.m() == matrix.n(),
2393  ExcMessage("The supplied matrix must be a square matrix"));
2394 
2395  static const int dim = FaceIterator::AccessorType::dimension;
2396 
2397  // Do a full matching of the face vertices:
2398 
2399  std::array<unsigned int, GeometryInfo<dim>::vertices_per_face> matching;
2400 
2401  std::set<unsigned int> face2_vertices;
2402  for (unsigned int i = 0; i < GeometryInfo<dim>::vertices_per_face; ++i)
2403  face2_vertices.insert(i);
2404 
2405  for (unsigned int i = 0; i < GeometryInfo<dim>::vertices_per_face; ++i)
2406  {
2407  for (std::set<unsigned int>::iterator it = face2_vertices.begin();
2408  it != face2_vertices.end();
2409  ++it)
2410  {
2411  if (orthogonal_equality(face1->vertex(i),
2412  face2->vertex(*it),
2413  direction,
2414  offset,
2415  matrix))
2416  {
2417  matching[i] = *it;
2418  face2_vertices.erase(it);
2419  break; // jump out of the innermost loop
2420  }
2421  }
2422  }
2423 
2424  // And finally, a lookup to determine the ordering bitmask:
2425  if (face2_vertices.empty())
2426  orientation = OrientationLookupTable<dim>::lookup(matching);
2427 
2428  return face2_vertices.empty();
2429  }
2430 
2431 
2432 
2433  template <typename FaceIterator>
2434  inline bool
2436  const FaceIterator & face1,
2437  const FaceIterator & face2,
2438  const int direction,
2440  const FullMatrix<double> & matrix)
2441  {
2442  // Call the function above with a dummy orientation array
2443  std::bitset<3> dummy;
2444  return orthogonal_equality(dummy, face1, face2, direction, offset, matrix);
2445  }
2446 
2447 
2448 
2449 } // namespace GridTools
2450 
2451 
2452 #include "grid_tools_dof_handlers.inst"
2453 
2454 
2455 DEAL_II_NAMESPACE_CLOSE
static const unsigned int invalid_unsigned_int
Definition: types.h:173
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1366
void clear_user_flags()
Definition: tria.cc:11096
const std::vector< Point< spacedim > > & get_vertices() const
cell_iterator end() const
Definition: tria.cc:12004
std::map< unsigned int, Point< spacedim > > extract_used_vertices(const Triangulation< dim, spacedim > &container, const Mapping< dim, spacedim > &mapping=StaticMappingQ1< dim, spacedim >::mapping)
Definition: grid_tools.cc:4740
bool have_same_coarse_mesh(const Triangulation< dim, spacedim > &mesh_1, const Triangulation< dim, spacedim > &mesh_2)
MeshType< dim, spacedim >::active_cell_iterator find_active_cell_around_point(const MeshType< dim, spacedim > &mesh, const Point< spacedim > &p, const std::vector< bool > &marked_vertices=std::vector< bool >())
BoundingBox< spacedim > compute_bounding_box(const Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:420
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
std::vector< typename MeshType::active_cell_iterator > compute_ghost_cell_layer_within_distance(const MeshType &mesh, const double layer_thickness)
bool orthogonal_equality(std::bitset< 3 > &orientation, const FaceIterator &face1, const FaceIterator &face2, const int direction, const Tensor< 1, FaceIterator::AccessorType::space_dimension > &offset=Tensor< 1, FaceIterator::AccessorType::space_dimension >(), const FullMatrix< double > &matrix=FullMatrix< double >())
std::vector< std::pair< typename MeshType< dim, spacedim >::active_cell_iterator, Point< dim > > > find_all_active_cells_around_point(const Mapping< dim, spacedim > &mapping, const MeshType< dim, spacedim > &mesh, const Point< spacedim > &p, const double tolerance=1e-12, const std::vector< bool > &marked_vertices=std::vector< bool >())
const std::vector< bool > & get_used_vertices() const
Definition: tria.cc:13104
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
virtual Point< dim > transform_real_to_unit_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< spacedim > &p) const =0
std::vector< typename MeshType::cell_iterator > compute_cell_halo_layer_on_level(const MeshType &mesh, const std::function< bool(const typename MeshType::cell_iterator &)> &predicate, const unsigned int level)
static::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
cell_iterator begin(const unsigned int level=0) const
Definition: tria.cc:11915
unsigned int n_active_cells() const
Definition: tria.cc:12509
unsigned long long int global_dof_index
Definition: types.h:72
static double distance_to_unit_cell(const Point< dim > &p)
std::vector< typename MeshType::active_cell_iterator > compute_active_cell_halo_layer(const MeshType &mesh, const std::function< bool(const typename MeshType::active_cell_iterator &)> &predicate)
typename ActiveSelector::active_cell_iterator active_cell_iterator
Definition: dof_handler.h:194
virtual void execute_coarsening_and_refinement()
Definition: tria.cc:13229
Definition: tria.h:81
static::ExceptionBase & ExcMessage(std::string arg1)
size_type n() const
unsigned int n_cells() const
Definition: tria.cc:12501
const Triangulation< dim, spacedim > & get_triangulation() const
virtual void create_triangulation(const std::vector< Point< spacedim >> &vertices, const std::vector< CellData< dim >> &cells, const SubCellData &subcelldata)
Definition: tria.cc:10556
#define Assert(cond, exc)
Definition: exceptions.h:1227
numbers::NumberTraits< Number >::real_type distance_square(const Point< dim, Number > &p) const
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
Abstract base class for mapping classes.
Definition: dof_tools.h:57
void build_triangulation_from_patch(const std::vector< typename Container::active_cell_iterator > &patch, Triangulation< Container::dimension, Container::space_dimension > &local_triangulation, std::map< typename Triangulation< Container::dimension, Container::space_dimension >::active_cell_iterator, typename Container::active_cell_iterator > &patch_to_global_tria_map)
size_type m() const
std::vector< typename MeshType::active_cell_iterator > compute_ghost_cell_halo_layer(const MeshType &mesh)
std::map< types::global_dof_index, std::vector< typename DoFHandlerType::active_cell_iterator > > get_dof_to_support_patch_map(DoFHandlerType &dof_handler)
std::vector< typename MeshType< dim, spacedim >::active_cell_iterator > find_cells_adjacent_to_vertex(const MeshType< dim, spacedim > &container, const unsigned int vertex_index)
Definition: grid_tools.cc:1298
void collect_periodic_faces(const MeshType &mesh, const types::boundary_id b_id1, const types::boundary_id b_id2, const int direction, std::vector< PeriodicFacePair< typename MeshType::cell_iterator >> &matched_pairs, const Tensor< 1, MeshType::space_dimension > &offset=::Tensor< 1, MeshType::space_dimension >(), const FullMatrix< double > &matrix=FullMatrix< double >())
unsigned int size() const
virtual bool preserves_vertex_locations() const =0
static::ExceptionBase & ExcNotImplemented()
const hp::FECollection< dim, spacedim > & get_fe_collection() const
Iterator points to a valid object.
std::vector< typename Container::cell_iterator > get_cells_at_coarsest_common_level(const std::vector< typename Container::active_cell_iterator > &patch_cells)
static::ExceptionBase & ExcVertexNotUsed(unsigned int arg1)
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: tria.cc:11935
std::list< std::pair< typename MeshType::cell_iterator, typename MeshType::cell_iterator > > get_finest_common_cells(const MeshType &mesh_1, const MeshType &mesh_2)
unsigned int boundary_id
Definition: types.h:111
std::vector< typename MeshType::active_cell_iterator > compute_active_cell_layer_within_distance(const MeshType &mesh, const std::function< bool(const typename MeshType::active_cell_iterator &)> &predicate, const double layer_thickness)
unsigned int find_closest_vertex(const std::map< unsigned int, Point< spacedim >> &vertices, const Point< spacedim > &p)
Definition: grid_tools.cc:4759
virtual void clear()
Definition: tria.cc:10232
std::vector< typename MeshType::active_cell_iterator > get_patch_around_cell(const typename MeshType::active_cell_iterator &cell)
static::ExceptionBase & ExcInternalError()
Triangulation< dim, spacedim > & get_triangulation()
Definition: tria.cc:13182