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