Reference documentation for deal.II version 9.0.0
grid_tools.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/quadrature_lib.h>
17 #include <deal.II/base/thread_management.h>
18 #include <deal.II/base/mpi.h>
19 #include <deal.II/base/mpi.templates.h>
20 
21 #include <deal.II/dofs/dof_handler.h>
22 #include <deal.II/dofs/dof_accessor.h>
23 #include <deal.II/dofs/dof_tools.h>
24 
25 #include <deal.II/distributed/tria.h>
26 #include <deal.II/distributed/shared_tria.h>
27 
28 #include <deal.II/fe/fe_nothing.h>
29 #include <deal.II/fe/fe_values.h>
30 #include <deal.II/fe/mapping_q1.h>
31 #include <deal.II/fe/mapping_q.h>
32 #include <deal.II/fe/mapping_q_generic.h>
33 #include <deal.II/fe/fe_q.h>
34 
35 #include <deal.II/grid/filtered_iterator.h>
36 #include <deal.II/grid/tria.h>
37 #include <deal.II/grid/tria_accessor.h>
38 #include <deal.II/grid/tria_iterator.h>
39 #include <deal.II/grid/grid_tools.h>
40 #include <deal.II/grid/grid_tools_cache.h>
41 #include <deal.II/grid/grid_reordering.h>
42 #include <deal.II/grid/manifold.h>
43 
44 #include <deal.II/lac/dynamic_sparsity_pattern.h>
45 #include <deal.II/lac/filtered_matrix.h>
46 #include <deal.II/lac/precondition.h>
47 #include <deal.II/lac/solver_cg.h>
48 #include <deal.II/lac/sparse_matrix.h>
49 #include <deal.II/lac/sparsity_pattern.h>
50 #include <deal.II/lac/sparsity_tools.h>
51 #include <deal.II/lac/vector.h>
52 #include <deal.II/lac/vector_memory.h>
53 
54 #include <deal.II/numerics/matrix_tools.h>
55 
56 #include <boost/random/uniform_real_distribution.hpp>
57 #include <boost/random/mersenne_twister.hpp>
58 
59 #include <array>
60 #include <cmath>
61 #include <numeric>
62 #include <list>
63 #include <set>
64 #include <tuple>
65 #include <unordered_map>
66 #include <iostream>
67 
68 DEAL_II_NAMESPACE_OPEN
69 
70 
71 namespace GridTools
72 {
73 
74  template <int dim, int spacedim>
75  double
77  {
78  // we can't deal with distributed meshes since we don't have all
79  // vertices locally. there is one exception, however: if the mesh has
80  // never been refined. the way to test this is not to ask
81  // tria.n_levels()==1, since this is something that can happen on one
82  // processor without being true on all. however, we can ask for the
83  // global number of active cells and use that
84 #if defined(DEAL_II_WITH_P4EST) && defined(DEBUG)
86  = dynamic_cast<const parallel::distributed::Triangulation<dim,spacedim>*>(&tria))
87  Assert (p_tria->n_global_active_cells() == tria.n_cells(0),
89 #endif
90 
91  // the algorithm used simply traverses all cells and picks out the
92  // boundary vertices. it may or may not be faster to simply get all
93  // vectors, don't mark boundary vertices, and compute the distances
94  // thereof, but at least as the mesh is refined, it seems better to
95  // first mark boundary nodes, as marking is O(N) in the number of
96  // cells/vertices, while computing the maximal distance is O(N*N)
97  const std::vector<Point<spacedim> > &vertices = tria.get_vertices ();
98  std::vector<bool> boundary_vertices (vertices.size(), false);
99 
101  cell = tria.begin_active();
103  endc = tria.end();
104  for (; cell!=endc; ++cell)
105  for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
106  if (cell->face(face)->at_boundary ())
107  for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_face; ++i)
108  boundary_vertices[cell->face(face)->vertex_index(i)] = true;
109 
110  // now traverse the list of boundary vertices and check distances.
111  // since distances are symmetric, we only have to check one half
112  double max_distance_sqr = 0;
113  std::vector<bool>::const_iterator pi = boundary_vertices.begin();
114  const unsigned int N = boundary_vertices.size();
115  for (unsigned int i=0; i<N; ++i, ++pi)
116  {
117  std::vector<bool>::const_iterator pj = pi+1;
118  for (unsigned int j=i+1; j<N; ++j, ++pj)
119  if ((*pi==true) && (*pj==true) &&
120  ((vertices[i]-vertices[j]).norm_square() > max_distance_sqr))
121  max_distance_sqr = (vertices[i]-vertices[j]).norm_square();
122  };
123 
124  return std::sqrt(max_distance_sqr);
125  }
126 
127 
128 
129  template <int dim, int spacedim>
130  double
131  volume (const Triangulation<dim, spacedim> &triangulation,
132  const Mapping<dim,spacedim> &mapping)
133  {
134  // get the degree of the mapping if possible. if not, just assume 1
135  unsigned int mapping_degree = 1;
136  if (const auto *p = dynamic_cast<const MappingQGeneric<dim,spacedim>*>(&mapping))
137  mapping_degree = p->get_degree();
138  else if (const auto *p = dynamic_cast<const MappingQ<dim,spacedim>*>(&mapping))
139  mapping_degree = p->get_degree();
140 
141  // then initialize an appropriate quadrature formula
142  const QGauss<dim> quadrature_formula (mapping_degree + 1);
143  const unsigned int n_q_points = quadrature_formula.size();
144 
145  // we really want the JxW values from the FEValues object, but it
146  // wants a finite element. create a cheap element as a dummy
147  // element
148  FE_Nothing<dim,spacedim> dummy_fe;
149  FEValues<dim,spacedim> fe_values (mapping, dummy_fe, quadrature_formula,
151 
153  cell = triangulation.begin_active(),
154  endc = triangulation.end();
155 
156  double local_volume = 0;
157 
158  // compute the integral quantities by quadrature
159  for (; cell!=endc; ++cell)
160  if (cell->is_locally_owned())
161  {
162  fe_values.reinit (cell);
163  for (unsigned int q=0; q<n_q_points; ++q)
164  local_volume += fe_values.JxW(q);
165  }
166 
167  double global_volume = 0;
168 
169 #ifdef DEAL_II_WITH_MPI
170  if (const parallel::Triangulation<dim,spacedim> *p_tria
171  = dynamic_cast<const parallel::Triangulation<dim,spacedim>*>(&triangulation))
172  global_volume = Utilities::MPI::sum (local_volume, p_tria->get_communicator());
173  else
174 #endif
175  global_volume = local_volume;
176 
177  return global_volume;
178  }
179 
180 
181 
182  template <>
183  double
184  cell_measure<1>
185  (const std::vector<Point<1> > &all_vertices,
186  const unsigned int (&vertex_indices)[GeometryInfo<1>::vertices_per_cell])
187  {
188  return all_vertices[vertex_indices[1]][0]
189  - all_vertices[vertex_indices[0]][0];
190  }
191 
192 
193 
194  template <>
195  double
196  cell_measure<3>
197  (const std::vector<Point<3> > &all_vertices,
198  const unsigned int (&vertex_indices)[GeometryInfo<3>::vertices_per_cell])
199  {
200  // note that this is the
201  // cell_measure based on the new
202  // deal.II numbering. When called
203  // from inside GridReordering make
204  // sure that you reorder the
205  // vertex_indices before
206  const double x[8] = { all_vertices[vertex_indices[0]](0),
207  all_vertices[vertex_indices[1]](0),
208  all_vertices[vertex_indices[2]](0),
209  all_vertices[vertex_indices[3]](0),
210  all_vertices[vertex_indices[4]](0),
211  all_vertices[vertex_indices[5]](0),
212  all_vertices[vertex_indices[6]](0),
213  all_vertices[vertex_indices[7]](0)
214  };
215  const double y[8] = { all_vertices[vertex_indices[0]](1),
216  all_vertices[vertex_indices[1]](1),
217  all_vertices[vertex_indices[2]](1),
218  all_vertices[vertex_indices[3]](1),
219  all_vertices[vertex_indices[4]](1),
220  all_vertices[vertex_indices[5]](1),
221  all_vertices[vertex_indices[6]](1),
222  all_vertices[vertex_indices[7]](1)
223  };
224  const double z[8] = { all_vertices[vertex_indices[0]](2),
225  all_vertices[vertex_indices[1]](2),
226  all_vertices[vertex_indices[2]](2),
227  all_vertices[vertex_indices[3]](2),
228  all_vertices[vertex_indices[4]](2),
229  all_vertices[vertex_indices[5]](2),
230  all_vertices[vertex_indices[6]](2),
231  all_vertices[vertex_indices[7]](2)
232  };
233 
234  /*
235  This is the same Maple script as in the barycenter method above
236  except of that here the shape functions tphi[0]-tphi[7] are ordered
237  according to the lexicographic numbering.
238 
239  x := array(0..7):
240  y := array(0..7):
241  z := array(0..7):
242  tphi[0] := (1-xi)*(1-eta)*(1-zeta):
243  tphi[1] := xi*(1-eta)*(1-zeta):
244  tphi[2] := (1-xi)* eta*(1-zeta):
245  tphi[3] := xi* eta*(1-zeta):
246  tphi[4] := (1-xi)*(1-eta)*zeta:
247  tphi[5] := xi*(1-eta)*zeta:
248  tphi[6] := (1-xi)* eta*zeta:
249  tphi[7] := xi* eta*zeta:
250  x_real := sum(x[s]*tphi[s], s=0..7):
251  y_real := sum(y[s]*tphi[s], s=0..7):
252  z_real := sum(z[s]*tphi[s], s=0..7):
253  with (linalg):
254  J := matrix(3,3, [[diff(x_real, xi), diff(x_real, eta), diff(x_real, zeta)],
255  [diff(y_real, xi), diff(y_real, eta), diff(y_real, zeta)],
256  [diff(z_real, xi), diff(z_real, eta), diff(z_real, zeta)]]):
257  detJ := det (J):
258 
259  measure := simplify ( int ( int ( int (detJ, xi=0..1), eta=0..1), zeta=0..1)):
260 
261  readlib(C):
262 
263  C(measure, optimized);
264 
265  The C code produced by this maple script is further optimized by
266  hand. In particular, division by 12 is performed only once, not
267  hundred of times.
268  */
269 
270  const double t3 = y[3]*x[2];
271  const double t5 = z[1]*x[5];
272  const double t9 = z[3]*x[2];
273  const double t11 = x[1]*y[0];
274  const double t14 = x[4]*y[0];
275  const double t18 = x[5]*y[7];
276  const double t20 = y[1]*x[3];
277  const double t22 = y[5]*x[4];
278  const double t26 = z[7]*x[6];
279  const double t28 = x[0]*y[4];
280  const double t34 = z[3]*x[1]*y[2]+t3*z[1]-t5*y[7]+y[7]*x[4]*z[6]+t9*y[6]-t11*z[4]-t5*y[3]-t14*z[2]+z[1]*x[4]*y[0]-t18*z[3]+t20*z[0]-t22*z[0]-y[0]*x[5]*z[4]-t26*y[3]+t28*z[2]-t9*y[1]-y[1]*x[4]*z[0]-t11*z[5];
281  const double t37 = y[1]*x[0];
282  const double t44 = x[1]*y[5];
283  const double t46 = z[1]*x[0];
284  const double t49 = x[0]*y[2];
285  const double t52 = y[5]*x[7];
286  const double t54 = x[3]*y[7];
287  const double t56 = x[2]*z[0];
288  const double t58 = x[3]*y[2];
289  const double t64 = -x[6]*y[4]*z[2]-t37*z[2]+t18*z[6]-x[3]*y[6]*z[2]+t11*z[2]+t5*y[0]+t44*z[4]-t46*y[4]-t20*z[7]-t49*z[6]-t22*z[1]+t52*z[3]-t54*z[2]-t56*y[4]-t58*z[0]+y[1]*x[2]*z[0]+t9*y[7]+t37*z[4];
290  const double t66 = x[1]*y[7];
291  const double t68 = y[0]*x[6];
292  const double t70 = x[7]*y[6];
293  const double t73 = z[5]*x[4];
294  const double t76 = x[6]*y[7];
295  const double t90 = x[4]*z[0];
296  const double t92 = x[1]*y[3];
297  const double t95 = -t66*z[3]-t68*z[2]-t70*z[2]+t26*y[5]-t73*y[6]-t14*z[6]+t76*z[2]-t3*z[6]+x[6]*y[2]*z[4]-z[3]*x[6]*y[2]+t26*y[4]-t44*z[3]-x[1]*y[2]*z[0]+x[5]*y[6]*z[4]+t54*z[5]+t90*y[2]-t92*z[2]+t46*y[2];
298  const double t102 = x[2]*y[0];
299  const double t107 = y[3]*x[7];
300  const double t114 = x[0]*y[6];
301  const double t125 = y[0]*x[3]*z[2]-z[7]*x[5]*y[6]-x[2]*y[6]*z[4]+t102*z[6]-t52*z[6]+x[2]*y[4]*z[6]-t107*z[5]-t54*z[6]+t58*z[6]-x[7]*y[4]*z[6]+t37*z[5]-t114*z[4]+t102*z[4]-z[1]*x[2]*y[0]+t28*z[6]-y[5]*x[6]*z[4]-z[5]*x[1]*y[4]-t73*y[7];
302  const double t129 = z[0]*x[6];
303  const double t133 = y[1]*x[7];
304  const double t145 = y[1]*x[5];
305  const double t156 = t90*y[6]-t129*y[4]+z[7]*x[2]*y[6]-t133*z[5]+x[5]*y[3]*z[7]-t26*y[2]-t70*z[3]+t46*y[3]+z[5]*x[7]*y[4]+z[7]*x[3]*y[6]-t49*z[4]+t145*z[7]-x[2]*y[7]*z[6]+t70*z[5]+t66*z[5]-z[7]*x[4]*y[6]+t18*z[4]+x[1]*y[4]*z[0];
306  const double t160 = x[5]*y[4];
307  const double t165 = z[1]*x[7];
308  const double t178 = z[1]*x[3];
309  const double t181 = t107*z[6]+t22*z[7]+t76*z[3]+t160*z[1]-x[4]*y[2]*z[6]+t70*z[4]+t165*y[5]+x[7]*y[2]*z[6]-t76*z[5]-t76*z[4]+t133*z[3]-t58*z[1]+y[5]*x[0]*z[4]+t114*z[2]-t3*z[7]+t20*z[2]+t178*y[7]+t129*y[2];
310  const double t207 = t92*z[7]+t22*z[6]+z[3]*x[0]*y[2]-x[0]*y[3]*z[2]-z[3]*x[7]*y[2]-t165*y[3]-t9*y[0]+t58*z[7]+y[3]*x[6]*z[2]+t107*z[2]+t73*y[0]-x[3]*y[5]*z[7]+t3*z[0]-t56*y[6]-z[5]*x[0]*y[4]+t73*y[1]-t160*z[6]+t160*z[0];
311  const double t228 = -t44*z[7]+z[5]*x[6]*y[4]-t52*z[4]-t145*z[4]+t68*z[4]+t92*z[5]-t92*z[0]+t11*z[3]+t44*z[0]+t178*y[5]-t46*y[5]-t178*y[0]-t145*z[0]-t20*z[5]-t37*z[3]-t160*z[7]+t145*z[3]+x[4]*y[6]*z[2];
312 
313  return (t34+t64+t95+t125+t156+t181+t207+t228)/12.;
314  }
315 
316 
317 
318  template <>
319  double
320  cell_measure<2>
321  (const std::vector<Point<2> > &all_vertices,
322  const unsigned int (&vertex_indices) [GeometryInfo<2>::vertices_per_cell])
323  {
324  /*
325  Get the computation of the measure by this little Maple script. We
326  use the blinear mapping of the unit quad to the real quad. However,
327  every transformation mapping the unit faces to straight lines should
328  do.
329 
330  Remember that the area of the quad is given by
331  \int_K 1 dx dy = \int_{\hat K} |det J| d(xi) d(eta)
332 
333  # x and y are arrays holding the x- and y-values of the four vertices
334  # of this cell in real space.
335  x := array(0..3);
336  y := array(0..3);
337  z := array(0..3);
338  tphi[0] := (1-xi)*(1-eta):
339  tphi[1] := xi*(1-eta):
340  tphi[2] := (1-xi)*eta:
341  tphi[3] := xi*eta:
342  x_real := sum(x[s]*tphi[s], s=0..3):
343  y_real := sum(y[s]*tphi[s], s=0..3):
344  z_real := sum(z[s]*tphi[s], s=0..3):
345 
346  Jxi := <diff(x_real,xi) | diff(y_real,xi) | diff(z_real,xi)>;
347  Jeta := <diff(x_real,eta)| diff(y_real,eta)| diff(z_real,eta)>;
348  with(VectorCalculus):
349  J := CrossProduct(Jxi, Jeta);
350  detJ := sqrt(J[1]^2 + J[2]^2 +J[3]^2);
351 
352  # measure := evalf (Int (Int (detJ, xi=0..1, method = _NCrule ) , eta=0..1, method = _NCrule ) ):
353  # readlib(C):
354 
355  # C(measure, optimized);
356 
357  additional optimizaton: divide by 2 only one time
358  */
359 
360  const double x[4] = { all_vertices[vertex_indices[0]](0),
361  all_vertices[vertex_indices[1]](0),
362  all_vertices[vertex_indices[2]](0),
363  all_vertices[vertex_indices[3]](0)
364  };
365 
366  const double y[4] = { all_vertices[vertex_indices[0]](1),
367  all_vertices[vertex_indices[1]](1),
368  all_vertices[vertex_indices[2]](1),
369  all_vertices[vertex_indices[3]](1)
370  };
371 
372  return (-x[1]*y[0]+x[1]*y[3]+y[0]*x[2]+x[0]*y[1]-x[0]*y[2]-y[1]*x[3]-x[2]*y[3]+x[3]*y[2])/2;
373 
374  }
375 
376 
377 
378  template <int dim, int spacedim>
381  {
382  using iterator = typename Triangulation<dim, spacedim>::active_cell_iterator;
383  const auto predicate = [](const iterator &)
384  {
385  return true;
386  };
387 
388  return compute_bounding_box(tria, std::function<bool(const iterator &)>(predicate));
389  }
390 
391 
392 
393  template <int dim, int spacedim>
394  void
395  delete_unused_vertices (std::vector<Point<spacedim> > &vertices,
396  std::vector<CellData<dim> > &cells,
397  SubCellData &subcelldata)
398  {
399  Assert(subcelldata.check_consistency(dim),
400  ExcMessage("Invalid SubCellData supplied according to ::check_consistency(). "
401  "This is caused by data containing objects for the wrong dimension."));
402 
403  // first check which vertices are actually used
404  std::vector<bool> vertex_used (vertices.size(), false);
405  for (unsigned int c=0; c<cells.size(); ++c)
406  for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
407  {
408  Assert(cells[c].vertices[v] < vertices.size(),
409  ExcMessage("Invalid vertex index encountered! cells["
411  + "].vertices["
413  + "]="
414  + Utilities::int_to_string(cells[c].vertices[v])
415  + " is invalid, because only "
416  + Utilities::int_to_string(vertices.size())
417  + " vertices were supplied."));
418  vertex_used[cells[c].vertices[v]] = true;
419  }
420 
421 
422  // then renumber the vertices that are actually used in the same order as
423  // they were beforehand
424  const unsigned int invalid_vertex = numbers::invalid_unsigned_int;
425  std::vector<unsigned int> new_vertex_numbers (vertices.size(), invalid_vertex);
426  unsigned int next_free_number = 0;
427  for (unsigned int i=0; i<vertices.size(); ++i)
428  if (vertex_used[i] == true)
429  {
430  new_vertex_numbers[i] = next_free_number;
431  ++next_free_number;
432  }
433 
434  // next replace old vertex numbers by the new ones
435  for (unsigned int c=0; c<cells.size(); ++c)
436  for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
437  cells[c].vertices[v] = new_vertex_numbers[cells[c].vertices[v]];
438 
439  // same for boundary data
440  for (unsigned int c=0; c<subcelldata.boundary_lines.size(); ++c)
441  for (unsigned int v=0; v<GeometryInfo<1>::vertices_per_cell; ++v)
442  {
443  Assert(subcelldata.boundary_lines[c].vertices[v] < new_vertex_numbers.size(),
444  ExcMessage("Invalid vertex index in subcelldata.boundary_lines. "
445  "subcelldata.boundary_lines["
447  + "].vertices["
449  + "]="
450  + Utilities::int_to_string(subcelldata.boundary_lines[c].vertices[v])
451  + " is invalid, because only "
452  + Utilities::int_to_string(vertices.size())
453  + " vertices were supplied."));
454  subcelldata.boundary_lines[c].vertices[v]
455  = new_vertex_numbers[subcelldata.boundary_lines[c].vertices[v]];
456  }
457 
458  for (unsigned int c=0; c<subcelldata.boundary_quads.size(); ++c)
459  for (unsigned int v=0; v<GeometryInfo<2>::vertices_per_cell; ++v)
460  {
461  Assert(subcelldata.boundary_quads[c].vertices[v] < new_vertex_numbers.size(),
462  ExcMessage("Invalid vertex index in subcelldata.boundary_quads. "
463  "subcelldata.boundary_quads["
465  + "].vertices["
467  + "]="
468  + Utilities::int_to_string(subcelldata.boundary_quads[c].vertices[v])
469  + " is invalid, because only "
470  + Utilities::int_to_string(vertices.size())
471  + " vertices were supplied."));
472 
473  subcelldata.boundary_quads[c].vertices[v]
474  = new_vertex_numbers[subcelldata.boundary_quads[c].vertices[v]];
475  }
476 
477  // finally copy over the vertices which we really need to a new array and
478  // replace the old one by the new one
479  std::vector<Point<spacedim> > tmp;
480  tmp.reserve (std::count(vertex_used.begin(), vertex_used.end(), true));
481  for (unsigned int v=0; v<vertices.size(); ++v)
482  if (vertex_used[v] == true)
483  tmp.push_back (vertices[v]);
484  swap (vertices, tmp);
485  }
486 
487 
488 
489  template <int dim, int spacedim>
490  void
491  delete_duplicated_vertices (std::vector<Point<spacedim> > &vertices,
492  std::vector<CellData<dim> > &cells,
493  SubCellData &subcelldata,
494  std::vector<unsigned int> &considered_vertices,
495  double tol)
496  {
497  // create a vector of vertex
498  // indices. initialize it to the identity,
499  // later on change that if necessary.
500  std::vector<unsigned int> new_vertex_numbers(vertices.size());
501  for (unsigned int i=0; i<vertices.size(); ++i)
502  new_vertex_numbers[i] = i;
503 
504  // if the considered_vertices vector is
505  // empty, consider all vertices
506  if (considered_vertices.size()==0)
507  considered_vertices = new_vertex_numbers;
508 
509  Assert(considered_vertices.size() <= vertices.size(),
510  ExcInternalError());
511 
512 
513  // now loop over all vertices to be
514  // considered and try to find an identical
515  // one
516  for (unsigned int i=0; i<considered_vertices.size(); ++i)
517  {
518  Assert(considered_vertices[i]<vertices.size(),
519  ExcInternalError());
520  if (new_vertex_numbers[considered_vertices[i]]!=considered_vertices[i])
521  // this vertex has been identified with
522  // another one already, skip it in the
523  // test
524  continue;
525  // this vertex is not identified with
526  // another one so far. search in the list
527  // of remaining vertices. if a duplicate
528  // vertex is found, set the new vertex
529  // index for that vertex to this vertex'
530  // index.
531  for (unsigned int j=i+1; j<considered_vertices.size(); ++j)
532  {
533  bool equal=true;
534  for (unsigned int d=0; d<spacedim; ++d)
535  equal &= (fabs(vertices[considered_vertices[j]](d)-vertices[considered_vertices[i]](d))<tol);
536  if (equal)
537  {
538  new_vertex_numbers[considered_vertices[j]]=considered_vertices[i];
539  // we do not suppose, that there might be another duplicate
540  // vertex, so break here
541  break;
542  }
543  }
544  }
545 
546  // now we got a renumbering list. simply
547  // renumber all vertices (non-duplicate
548  // vertices get renumbered to themselves, so
549  // nothing bad happens). after that, the
550  // duplicate vertices will be unused, so call
551  // delete_unused_vertices() to do that part
552  // of the job.
553  for (unsigned int c=0; c<cells.size(); ++c)
554  for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
555  cells[c].vertices[v]=new_vertex_numbers[cells[c].vertices[v]];
556 
557  delete_unused_vertices(vertices, cells, subcelldata);
558  }
559 
560 
561 
562 // define some transformations in an anonymous namespace
563  namespace
564  {
565  template <int spacedim>
566  class Shift
567  {
568  public:
569  explicit Shift (const Tensor<1,spacedim> &shift)
570  :
571  shift(shift)
572  {}
573  Point<spacedim> operator() (const Point<spacedim> p) const
574  {
575  return p+shift;
576  }
577  private:
579  };
580 
581 
582  // the following class is only
583  // needed in 2d, so avoid trouble
584  // with compilers warning otherwise
585  class Rotate2d
586  {
587  public:
588  explicit Rotate2d (const double angle)
589  :
590  angle(angle)
591  {}
592  Point<2> operator() (const Point<2> &p) const
593  {
594  return Point<2> (std::cos(angle)*p(0) - std::sin(angle) * p(1),
595  std::sin(angle)*p(0) + std::cos(angle) * p(1));
596  }
597  private:
598  const double angle;
599  };
600 
601  // Transformation to rotate around one of the cartesian axes.
602  class Rotate3d
603  {
604  public:
605  Rotate3d (const double angle,
606  const unsigned int axis)
607  :
608  angle(angle),
609  axis(axis)
610  {}
611 
612  Point<3> operator() (const Point<3> &p) const
613  {
614  if (axis==0)
615  return Point<3> (p(0),
616  std::cos(angle)*p(1) - std::sin(angle) * p(2),
617  std::sin(angle)*p(1) + std::cos(angle) * p(2));
618  else if (axis==1)
619  return Point<3> (std::cos(angle)*p(0) + std::sin(angle) * p(2),
620  p(1),
621  -std::sin(angle)*p(0) + std::cos(angle) * p(2));
622  else
623  return Point<3> (std::cos(angle)*p(0) - std::sin(angle) * p(1),
624  std::sin(angle)*p(0) + std::cos(angle) * p(1),
625  p(2));
626  }
627  private:
628  const double angle;
629  const unsigned int axis;
630  };
631 
632  template <int spacedim>
633  class Scale
634  {
635  public:
636  explicit Scale (const double factor)
637  :
638  factor(factor)
639  {}
640  Point<spacedim> operator() (const Point<spacedim> p) const
641  {
642  return p*factor;
643  }
644  private:
645  const double factor;
646  };
647  }
648 
649 
650  template <int dim, int spacedim>
651  void
652  shift (const Tensor<1,spacedim> &shift_vector,
653  Triangulation<dim, spacedim> &triangulation)
654  {
655  transform (Shift<spacedim>(shift_vector), triangulation);
656  }
657 
658 
659 
660  void
661  rotate (const double angle,
662  Triangulation<2> &triangulation)
663  {
664  transform (Rotate2d(angle), triangulation);
665  }
666 
667  template <int dim>
668  void
669  rotate (const double angle,
670  const unsigned int axis,
671  Triangulation<dim,3> &triangulation)
672  {
673  Assert(axis<3, ExcMessage("Invalid axis given!"));
674 
675  transform (Rotate3d(angle, axis), triangulation);
676  }
677 
678  template <int dim, int spacedim>
679  void
680  scale (const double scaling_factor,
681  Triangulation<dim, spacedim> &triangulation)
682  {
683  Assert (scaling_factor>0, ExcScalingFactorNotPositive (scaling_factor));
684  transform (Scale<spacedim>(scaling_factor), triangulation);
685  }
686 
687 
688  namespace
689  {
695  void laplace_solve (const SparseMatrix<double> &S,
696  const std::map<types::global_dof_index,double> &fixed_dofs,
697  Vector<double> &u)
698  {
699  const unsigned int n_dofs=S.n();
702  prec.initialize(S, 1.2);
703  FilteredMatrix<Vector<double> > PF (prec);
704 
705  SolverControl control (n_dofs, 1.e-10, false, false);
707  SolverCG<Vector<double> > solver (control, mem);
708 
709  Vector<double> f(n_dofs);
710 
711  SF.add_constraints(fixed_dofs);
712  SF.apply_constraints (f, true);
713  solver.solve(SF, u, f, PF);
714  }
715  }
716 
717 
718 
719  // Implementation for 1D only
720  template <>
721  void laplace_transform (const std::map<unsigned int,Point<1> > &,
723  const Function<1> *,
724  const bool )
725  {
726  Assert(false, ExcNotImplemented());
727  }
728 
729 
730  // Implementation for dimensions except 1
731  template <int dim>
732  void
733  laplace_transform (const std::map<unsigned int,Point<dim> > &new_points,
734  Triangulation<dim> &triangulation,
735  const Function<dim> *coefficient,
736  const bool solve_for_absolute_positions)
737  {
738  // first provide everything that is needed for solving a Laplace
739  // equation.
740  FE_Q<dim> q1(1);
741 
742  DoFHandler<dim> dof_handler(triangulation);
743  dof_handler.distribute_dofs(q1);
744 
745  DynamicSparsityPattern dsp (dof_handler.n_dofs (),
746  dof_handler.n_dofs ());
747  DoFTools::make_sparsity_pattern (dof_handler, dsp);
748  dsp.compress ();
749 
750  SparsityPattern sparsity_pattern;
751  sparsity_pattern.copy_from (dsp);
752  sparsity_pattern.compress ();
753 
754  SparseMatrix<double> S(sparsity_pattern);
755 
756  QGauss<dim> quadrature(4);
757 
758  MatrixCreator::create_laplace_matrix(StaticMappingQ1<dim>::mapping, dof_handler, quadrature, S, coefficient);
759 
760  // set up the boundary values for the laplace problem
761  std::map<types::global_dof_index,double> fixed_dofs[dim];
762  typename std::map<unsigned int,Point<dim> >::const_iterator map_end=new_points.end();
763 
764  // fill these maps using the data given by new_points
765  typename DoFHandler<dim>::cell_iterator cell=dof_handler.begin_active(),
766  endc=dof_handler.end();
767  for (; cell!=endc; ++cell)
768  {
769  // loop over all vertices of the cell and see if it is listed in the map
770  // given as first argument of the function
771  for (unsigned int vertex_no=0;
772  vertex_no<GeometryInfo<dim>::vertices_per_cell; ++vertex_no)
773  {
774  const unsigned int vertex_index=cell->vertex_index(vertex_no);
775  const Point<dim> &vertex_point=cell->vertex(vertex_no);
776 
777  const typename std::map<unsigned int,Point<dim> >::const_iterator map_iter
778  = new_points.find(vertex_index);
779 
780  if (map_iter!=map_end)
781  for (unsigned int i=0; i<dim; ++i)
782  fixed_dofs[i].insert(std::pair<types::global_dof_index,double>
783  (cell->vertex_dof_index(vertex_no, 0),
784  (solve_for_absolute_positions ?
785  map_iter->second(i) :
786  map_iter->second(i) - vertex_point[i])
787  ));
788  }
789  }
790 
791  // solve the dim problems with different right hand sides.
792  Vector<double> us[dim];
793  for (unsigned int i=0; i<dim; ++i)
794  us[i].reinit (dof_handler.n_dofs());
795 
796  // solve linear systems in parallel
797  Threads::TaskGroup<> tasks;
798  for (unsigned int i=0; i<dim; ++i)
799  tasks += Threads::new_task (&laplace_solve,
800  S, fixed_dofs[i], us[i]);
801  tasks.join_all ();
802 
803  // change the coordinates of the points of the triangulation
804  // according to the computed values
805  std::vector<bool> vertex_touched (triangulation.n_vertices(), false);
806  for (cell=dof_handler.begin_active(); cell!=endc; ++cell)
807  for (unsigned int vertex_no=0;
808  vertex_no<GeometryInfo<dim>::vertices_per_cell; ++vertex_no)
809  if (vertex_touched[cell->vertex_index(vertex_no)] == false)
810  {
811  Point<dim> &v = cell->vertex(vertex_no);
812 
813  const types::global_dof_index dof_index = cell->vertex_dof_index(vertex_no, 0);
814  for (unsigned int i=0; i<dim; ++i)
815  if (solve_for_absolute_positions)
816  v(i) = us[i](dof_index);
817  else
818  v(i) += us[i](dof_index);
819 
820  vertex_touched[cell->vertex_index(vertex_no)] = true;
821  }
822  }
823 
824  template <int dim, int spacedim>
825  std::map<unsigned int, Point<spacedim> >
827  {
828  std::map<unsigned int, Point<spacedim> > vertex_map;
830  cell = tria.begin_active(),
831  endc = tria.end();
832  for (; cell!=endc; ++cell)
833  {
834  for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
835  {
837  = cell->face(i);
838  if (face->at_boundary())
839  {
840  for (unsigned j = 0; j < GeometryInfo<dim>::vertices_per_face; ++j)
841  {
842  const Point<spacedim> &vertex = face->vertex(j);
843  const unsigned int vertex_index = face->vertex_index(j);
844  vertex_map[vertex_index] = vertex;
845  }
846  }
847  }
848  }
849  return vertex_map;
850  }
851 
856  template <int dim, int spacedim>
857  void
858  distort_random (const double factor,
859  Triangulation<dim,spacedim> &triangulation,
860  const bool keep_boundary)
861  {
862  // if spacedim>dim we need to make sure that we perturb
863  // points but keep them on
864  // the manifold. however, this isn't implemented right now
865  Assert (spacedim == dim, ExcNotImplemented());
866 
867 
868  // find the smallest length of the
869  // lines adjacent to the
870  // vertex. take the initial value
871  // to be larger than anything that
872  // might be found: the diameter of
873  // the triangulation, here
874  // estimated by adding up the
875  // diameters of the coarse grid
876  // cells.
877  double almost_infinite_length = 0;
879  cell=triangulation.begin(0); cell!=triangulation.end(0); ++cell)
880  almost_infinite_length += cell->diameter();
881 
882  std::vector<double> minimal_length (triangulation.n_vertices(),
883  almost_infinite_length);
884 
885  // also note if a vertex is at the boundary
886  std::vector<bool> at_boundary (keep_boundary ? triangulation.n_vertices() : 0, false);
887  // for parallel::shared::Triangulation we need to work on all vertices,
888  // not just the ones related to loacally owned cells;
889  const bool is_parallel_shared
890  = (dynamic_cast<parallel::shared::Triangulation<dim,spacedim>*> (&triangulation) != nullptr);
892  cell=triangulation.begin_active(); cell!=triangulation.end(); ++cell)
893  if (is_parallel_shared || cell->is_locally_owned())
894  {
895  if (dim>1)
896  {
897  for (unsigned int i=0; i<GeometryInfo<dim>::lines_per_cell; ++i)
898  {
899  const typename Triangulation<dim,spacedim>::line_iterator line
900  = cell->line(i);
901 
902  if (keep_boundary && line->at_boundary())
903  {
904  at_boundary[line->vertex_index(0)] = true;
905  at_boundary[line->vertex_index(1)] = true;
906  }
907 
908  minimal_length[line->vertex_index(0)]
909  = std::min(line->diameter(),
910  minimal_length[line->vertex_index(0)]);
911  minimal_length[line->vertex_index(1)]
912  = std::min(line->diameter(),
913  minimal_length[line->vertex_index(1)]);
914  }
915  }
916  else //dim==1
917  {
918  if (keep_boundary)
919  for (unsigned int vertex=0; vertex<2; ++vertex)
920  if (cell->at_boundary(vertex) == true)
921  at_boundary[cell->vertex_index(vertex)] = true;
922 
923  minimal_length[cell->vertex_index(0)]
924  = std::min(cell->diameter(),
925  minimal_length[cell->vertex_index(0)]);
926  minimal_length[cell->vertex_index(1)]
927  = std::min(cell->diameter(),
928  minimal_length[cell->vertex_index(1)]);
929  }
930  }
931 
932  // create a random number generator for the interval [-1,1]. we use
933  // this to make sure the distribution we get is repeatable, i.e.,
934  // if you call the function twice on the same mesh, then you will
935  // get the same mesh. this would not be the case if you used
936  // the rand() function, which carries around some internal state
937  boost::random::mt19937 rng;
938  boost::random::uniform_real_distribution<> uniform_distribution(-1,1);
939 
940  // If the triangulation is distributed, we need to
941  // exchange the moved vertices across mpi processes
942  if (parallel::distributed::Triangulation< dim, spacedim > *distributed_triangulation
943  = dynamic_cast<parallel::distributed::Triangulation<dim,spacedim>*> (&triangulation))
944  {
945  const std::vector<bool> locally_owned_vertices = get_locally_owned_vertices(triangulation);
946  std::vector<bool> vertex_moved (triangulation.n_vertices(), false);
947 
948  // Next move vertices on locally owned cells
950  cell=triangulation.begin_active(); cell!=triangulation.end(); ++cell)
951  if (cell->is_locally_owned())
952  {
953  for (unsigned int vertex_no=0; vertex_no<GeometryInfo<dim>::vertices_per_cell;
954  ++vertex_no)
955  {
956  const unsigned global_vertex_no = cell->vertex_index(vertex_no);
957 
958  // ignore this vertex if we shall keep the boundary and
959  // this vertex *is* at the boundary, if it is already moved
960  // or if another process moves this vertex
961  if ((keep_boundary && at_boundary[global_vertex_no])
962  || vertex_moved[global_vertex_no]
963  || !locally_owned_vertices[global_vertex_no])
964  continue;
965 
966  // first compute a random shift vector
967  Point<spacedim> shift_vector;
968  for (unsigned int d=0; d<spacedim; ++d)
969  shift_vector(d) = uniform_distribution(rng);
970 
971  shift_vector *= factor * minimal_length[global_vertex_no] /
972  std::sqrt(shift_vector.square());
973 
974  // finally move the vertex
975  cell->vertex(vertex_no) += shift_vector;
976  vertex_moved[global_vertex_no] = true;
977  }
978  }
979 
980 #ifdef DEAL_II_WITH_P4EST
981  distributed_triangulation
982  ->communicate_locally_moved_vertices(locally_owned_vertices);
983 #else
984  (void)distributed_triangulation;
985  Assert (false, ExcInternalError());
986 #endif
987  }
988  else
989  // if this is a sequential triangulation, we could in principle
990  // use the algorithm above, but we'll use an algorithm that we used
991  // before the parallel::distributed::Triangulation was introduced
992  // in order to preserve backward compatibility
993  {
994  // loop over all vertices and compute their new locations
995  const unsigned int n_vertices = triangulation.n_vertices();
996  std::vector<Point<spacedim> > new_vertex_locations (n_vertices);
997  const std::vector<Point<spacedim> > &old_vertex_locations
998  = triangulation.get_vertices();
999 
1000  for (unsigned int vertex=0; vertex<n_vertices; ++vertex)
1001  {
1002  // ignore this vertex if we will keep the boundary and
1003  // this vertex *is* at the boundary
1004  if (keep_boundary && at_boundary[vertex])
1005  new_vertex_locations[vertex] = old_vertex_locations[vertex];
1006  else
1007  {
1008  // compute a random shift vector
1009  Point<spacedim> shift_vector;
1010  for (unsigned int d=0; d<spacedim; ++d)
1011  shift_vector(d) = uniform_distribution(rng);
1012 
1013  shift_vector *= factor * minimal_length[vertex] /
1014  std::sqrt(shift_vector.square());
1015 
1016  // record new vertex location
1017  new_vertex_locations[vertex] = old_vertex_locations[vertex] + shift_vector;
1018  }
1019  }
1020 
1021  // now do the actual move of the vertices
1023  cell=triangulation.begin_active(); cell!=triangulation.end(); ++cell)
1024  for (unsigned int vertex_no=0;
1025  vertex_no<GeometryInfo<dim>::vertices_per_cell; ++vertex_no)
1026  cell->vertex(vertex_no) = new_vertex_locations[cell->vertex_index(vertex_no)];
1027  }
1028 
1029  // Correct hanging nodes if necessary
1030  if (dim>=2)
1031  {
1032  // We do the same as in GridTools::transform
1033  //
1034  // exclude hanging nodes at the boundaries of artificial cells:
1035  // these may belong to ghost cells for which we know the exact
1036  // location of vertices, whereas the artificial cell may or may
1037  // not be further refined, and so we cannot know whether
1038  // the location of the hanging node is correct or not
1040  cell = triangulation.begin_active(),
1041  endc = triangulation.end();
1042  for (; cell!=endc; ++cell)
1043  if (!cell->is_artificial())
1044  for (unsigned int face=0;
1045  face<GeometryInfo<dim>::faces_per_cell; ++face)
1046  if (cell->face(face)->has_children() &&
1047  !cell->face(face)->at_boundary())
1048  {
1049  // this face has hanging nodes
1050  if (dim==2)
1051  cell->face(face)->child(0)->vertex(1)
1052  = (cell->face(face)->vertex(0) +
1053  cell->face(face)->vertex(1)) / 2;
1054  else if (dim==3)
1055  {
1056  cell->face(face)->child(0)->vertex(1)
1057  = .5*(cell->face(face)->vertex(0)
1058  +cell->face(face)->vertex(1));
1059  cell->face(face)->child(0)->vertex(2)
1060  = .5*(cell->face(face)->vertex(0)
1061  +cell->face(face)->vertex(2));
1062  cell->face(face)->child(1)->vertex(3)
1063  = .5*(cell->face(face)->vertex(1)
1064  +cell->face(face)->vertex(3));
1065  cell->face(face)->child(2)->vertex(3)
1066  = .5*(cell->face(face)->vertex(2)
1067  +cell->face(face)->vertex(3));
1068 
1069  // center of the face
1070  cell->face(face)->child(0)->vertex(3)
1071  = .25*(cell->face(face)->vertex(0)
1072  +cell->face(face)->vertex(1)
1073  +cell->face(face)->vertex(2)
1074  +cell->face(face)->vertex(3));
1075  }
1076  }
1077  }
1078  }
1079 
1080 
1081 
1082  template <int dim, template <int, int> class MeshType, int spacedim>
1083  unsigned int
1084  find_closest_vertex (const MeshType<dim,spacedim> &mesh,
1085  const Point<spacedim> &p,
1086  const std::vector<bool> &marked_vertices)
1087  {
1088  // first get the underlying
1089  // triangulation from the
1090  // mesh and determine vertices
1091  // and used vertices
1092  const Triangulation<dim, spacedim> &tria = mesh.get_triangulation();
1093 
1094  const std::vector< Point<spacedim> > &vertices = tria.get_vertices();
1095 
1096  Assert ( tria.get_vertices().size() == marked_vertices.size() || marked_vertices.size() ==0,
1097  ExcDimensionMismatch(tria.get_vertices().size(), marked_vertices.size()));
1098 
1099  // If p is an element of marked_vertices,
1100  // and q is that of used_Vertices,
1101  // the vector marked_vertices does NOT
1102  // contain unused vertices if p implies q.
1103  // I.e., if p is true q must be true
1104  // (if p is false, q could be false or true).
1105  // p implies q logic is encapsulated in ~p|q.
1106  Assert( marked_vertices.size()==0
1107  ||
1108  std::equal( marked_vertices.begin(),
1109  marked_vertices.end(),
1110  tria.get_used_vertices().begin(),
1111  [](bool p, bool q)
1112  {
1113  return !p || q;
1114  }),
1115  ExcMessage("marked_vertices should be a subset of used vertices in the triangulation "
1116  "but marked_vertices contains one or more vertices that are not used vertices!") );
1117 
1118  // In addition, if a vector bools
1119  // is specified (marked_vertices)
1120  // marking all the vertices which
1121  // could be the potentially closest
1122  // vertex to the point, use it instead
1123  // of used vertices
1124  const std::vector<bool> &used =
1125  (marked_vertices.size()==0) ? tria.get_used_vertices() : marked_vertices;
1126 
1127  // At the beginning, the first
1128  // used vertex is the closest one
1129  std::vector<bool>::const_iterator first =
1130  std::find(used.begin(), used.end(), true);
1131 
1132  // Assert that at least one vertex
1133  // is actually used
1134  Assert(first != used.end(), ExcInternalError());
1135 
1136  unsigned int best_vertex = std::distance(used.begin(), first);
1137  double best_dist = (p - vertices[best_vertex]).norm_square();
1138 
1139  // For all remaining vertices, test
1140  // whether they are any closer
1141  for (unsigned int j = best_vertex+1; j < vertices.size(); j++)
1142  if (used[j])
1143  {
1144  double dist = (p - vertices[j]).norm_square();
1145  if (dist < best_dist)
1146  {
1147  best_vertex = j;
1148  best_dist = dist;
1149  }
1150  }
1151 
1152  return best_vertex;
1153  }
1154 
1155 
1156 
1157  template <int dim, template <int, int> class MeshType, int spacedim>
1158  unsigned int
1160  const MeshType<dim,spacedim> &mesh,
1161  const Point<spacedim> &p,
1162  const std::vector<bool> &marked_vertices)
1163  {
1164  // Take a shortcut in the simple case.
1165  if (mapping.preserves_vertex_locations() == true)
1166  return find_closest_vertex(mesh, p, marked_vertices);
1167 
1168  // first get the underlying
1169  // triangulation from the
1170  // mesh and determine vertices
1171  // and used vertices
1172  const Triangulation<dim, spacedim> &tria = mesh.get_triangulation();
1173 
1174  auto vertices = extract_used_vertices(tria, mapping);
1175 
1176  Assert ( tria.get_vertices().size() == marked_vertices.size() || marked_vertices.size() ==0,
1177  ExcDimensionMismatch(tria.get_vertices().size(), marked_vertices.size()));
1178 
1179  // If p is an element of marked_vertices,
1180  // and q is that of used_Vertices,
1181  // the vector marked_vertices does NOT
1182  // contain unused vertices if p implies q.
1183  // I.e., if p is true q must be true
1184  // (if p is false, q could be false or true).
1185  // p implies q logic is encapsulated in ~p|q.
1186  Assert( marked_vertices.size()==0
1187  ||
1188  std::equal( marked_vertices.begin(),
1189  marked_vertices.end(),
1190  tria.get_used_vertices().begin(),
1191  [](bool p, bool q)
1192  {
1193  return !p || q;
1194  }),
1195  ExcMessage("marked_vertices should be a subset of used vertices in the triangulation "
1196  "but marked_vertices contains one or more vertices that are not used vertices!") );
1197 
1198  // Remove from the map unwanted elements.
1199  if (marked_vertices.size())
1200  for (auto it = vertices.begin(); it != vertices.end(); )
1201  {
1202  if (marked_vertices[it->first] == false)
1203  {
1204  vertices.erase(it++);
1205  }
1206  else
1207  {
1208  ++it;
1209  }
1210  }
1211 
1212  return find_closest_vertex(vertices, p);
1213  }
1214 
1215 
1216 
1217  template <int dim, template <int, int> class MeshType, int spacedim>
1218 #ifndef _MSC_VER
1219  std::vector<typename MeshType<dim, spacedim>::active_cell_iterator>
1220 #else
1221  std::vector<typename ::internal::ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim> >::type>
1222 #endif
1223  find_cells_adjacent_to_vertex(const MeshType<dim,spacedim> &mesh,
1224  const unsigned int vertex)
1225  {
1226  // make sure that the given vertex is
1227  // an active vertex of the underlying
1228  // triangulation
1229  Assert(vertex < mesh.get_triangulation().n_vertices(),
1230  ExcIndexRange(0,mesh.get_triangulation().n_vertices(),vertex));
1231  Assert(mesh.get_triangulation().get_used_vertices()[vertex],
1232  ExcVertexNotUsed(vertex));
1233 
1234  // use a set instead of a vector
1235  // to ensure that cells are inserted only
1236  // once
1237  std::set<typename ::internal::ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim> >::type> adjacent_cells;
1238 
1239  typename ::internal::ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim> >::type
1240  cell = mesh.begin_active(),
1241  endc = mesh.end();
1242 
1243  // go through all active cells and look if the vertex is part of that cell
1244  //
1245  // in 1d, this is all we need to care about. in 2d/3d we also need to worry
1246  // that the vertex might be a hanging node on a face or edge of a cell; in
1247  // this case, we would want to add those cells as well on whose faces the
1248  // vertex is located but for which it is not a vertex itself.
1249  //
1250  // getting this right is a lot simpler in 2d than in 3d. in 2d, a hanging
1251  // node can only be in the middle of a face and we can query the neighboring
1252  // cell from the current cell. on the other hand, in 3d a hanging node
1253  // vertex can also be on an edge but there can be many other cells on
1254  // this edge and we can not access them from the cell we are currently
1255  // on.
1256  //
1257  // so, in the 3d case, if we run the algorithm as in 2d, we catch all
1258  // those cells for which the vertex we seek is on a *subface*, but we
1259  // miss the case of cells for which the vertex we seek is on a
1260  // sub-edge for which there is no corresponding sub-face (because the
1261  // immediate neighbor behind this face is not refined), see for example
1262  // the bits/find_cells_adjacent_to_vertex_6 testcase. thus, if we
1263  // haven't yet found the vertex for the current cell we also need to
1264  // look at the mid-points of edges
1265  //
1266  // as a final note, deciding whether a neighbor is actually coarser is
1267  // simple in the case of isotropic refinement (we just need to look at
1268  // the level of the current and the neighboring cell). however, this
1269  // isn't so simple if we have used anisotropic refinement since then
1270  // the level of a cell is not indicative of whether it is coarser or
1271  // not than the current cell. ultimately, we want to add all cells on
1272  // which the vertex is, independent of whether they are coarser or
1273  // finer and so in the 2d case below we simply add *any* *active* neighbor.
1274  // in the worst case, we add cells multiple times to the adjacent_cells
1275  // list, but std::set throws out those cells already entered
1276  for (; cell != endc; ++cell)
1277  {
1278  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; v++)
1279  if (cell->vertex_index(v) == vertex)
1280  {
1281  // OK, we found a cell that contains
1282  // the given vertex. We add it
1283  // to the list.
1284  adjacent_cells.insert(cell);
1285 
1286  // as explained above, in 2+d we need to check whether
1287  // this vertex is on a face behind which there is a
1288  // (possibly) coarser neighbor. if this is the case,
1289  // then we need to also add this neighbor
1290  if (dim >= 2)
1291  for (unsigned int vface = 0; vface < dim; vface++)
1292  {
1293  const unsigned int face =
1295 
1296  if (!cell->at_boundary(face)
1297  &&
1298  cell->neighbor(face)->active())
1299  {
1300  // there is a (possibly) coarser cell behind a
1301  // face to which the vertex belongs. the
1302  // vertex we are looking at is then either a
1303  // vertex of that coarser neighbor, or it is a
1304  // hanging node on one of the faces of that
1305  // cell. in either case, it is adjacent to the
1306  // vertex, so add it to the list as well (if
1307  // the cell was already in the list then the
1308  // std::set makes sure that we get it only
1309  // once)
1310  adjacent_cells.insert (cell->neighbor(face));
1311  }
1312  }
1313 
1314  // in any case, we have found a cell, so go to the next cell
1315  goto next_cell;
1316  }
1317 
1318  // in 3d also loop over the edges
1319  if (dim >= 3)
1320  {
1321  for (unsigned int e=0; e<GeometryInfo<dim>::lines_per_cell; ++e)
1322  if (cell->line(e)->has_children())
1323  // the only place where this vertex could have been
1324  // hiding is on the mid-edge point of the edge we
1325  // are looking at
1326  if (cell->line(e)->child(0)->vertex_index(1) == vertex)
1327  {
1328  adjacent_cells.insert(cell);
1329 
1330  // jump out of this tangle of nested loops
1331  goto next_cell;
1332  }
1333  }
1334 
1335  // in more than 3d we would probably have to do the same as
1336  // above also for even lower-dimensional objects
1337  Assert (dim <= 3, ExcNotImplemented());
1338 
1339  // move on to the next cell if we have found the
1340  // vertex on the current one
1341 next_cell:
1342  ;
1343  }
1344 
1345  // if this was an active vertex then there needs to have been
1346  // at least one cell to which it is adjacent!
1347  Assert (adjacent_cells.size() > 0, ExcInternalError());
1348 
1349  // return the result as a vector, rather than the set we built above
1350  return
1351  std::vector<typename ::internal::ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim> >::type>
1352  (adjacent_cells.begin(), adjacent_cells.end());
1353  }
1354 
1355 
1356 
1357  namespace
1358  {
1359  template <int dim, template <int, int> class MeshType, int spacedim>
1360  void find_active_cell_around_point_internal
1361  (const MeshType<dim,spacedim> &mesh,
1362 #ifndef _MSC_VER
1363  std::set<typename MeshType<dim, spacedim>::active_cell_iterator> &searched_cells,
1364  std::set<typename MeshType<dim, spacedim>::active_cell_iterator> &adjacent_cells)
1365 #else
1366  std::set<typename ::internal::ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim> >::type> &searched_cells,
1367  std::set<typename ::internal::ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim> >::type> &adjacent_cells)
1368 #endif
1369  {
1370 #ifndef _MSC_VER
1371  typedef typename MeshType<dim, spacedim>::active_cell_iterator cell_iterator;
1372 #else
1373  typedef typename ::internal::ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim> >::type cell_iterator;
1374 #endif
1375 
1376  // update the searched cells
1377  searched_cells.insert(adjacent_cells.begin(), adjacent_cells.end());
1378  // now we to collect all neighbors
1379  // of the cells in adjacent_cells we
1380  // have not yet searched.
1381  std::set<cell_iterator> adjacent_cells_new;
1382 
1383  typename std::set<cell_iterator>::const_iterator
1384  cell = adjacent_cells.begin(),
1385  endc = adjacent_cells.end();
1386  for (; cell != endc; ++cell)
1387  {
1388  std::vector<cell_iterator> active_neighbors;
1389  get_active_neighbors<MeshType<dim, spacedim> >(*cell, active_neighbors);
1390  for (unsigned int i=0; i<active_neighbors.size(); ++i)
1391  if (searched_cells.find(active_neighbors[i]) == searched_cells.end())
1392  adjacent_cells_new.insert(active_neighbors[i]);
1393  }
1394  adjacent_cells.clear();
1395  adjacent_cells.insert(adjacent_cells_new.begin(), adjacent_cells_new.end());
1396  if (adjacent_cells.size() == 0)
1397  {
1398  // we haven't found any other cell that would be a
1399  // neighbor of a previously found cell, but we know
1400  // that we haven't checked all cells yet. that means
1401  // that the domain is disconnected. in that case,
1402  // choose the first previously untouched cell we
1403  // can find
1404  cell_iterator it = mesh.begin_active();
1405  for ( ; it!=mesh.end(); ++it)
1406  if (searched_cells.find(it) == searched_cells.end())
1407  {
1408  adjacent_cells.insert(it);
1409  break;
1410  }
1411  }
1412  }
1413  }
1414 
1415  template <int dim, template <int, int> class MeshType, int spacedim>
1416 #ifndef _MSC_VER
1417  typename MeshType<dim, spacedim>::active_cell_iterator
1418 #else
1419  typename ::internal::ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim> >::type
1420 #endif
1421  find_active_cell_around_point (const MeshType<dim,spacedim> &mesh,
1422  const Point<spacedim> &p,
1423  const std::vector<bool> &marked_vertices)
1424  {
1425  return
1426  find_active_cell_around_point<dim,MeshType,spacedim>
1428  mesh, p, marked_vertices).first;
1429  }
1430 
1431 
1432  template <int dim, template <int, int> class MeshType, int spacedim>
1433 #ifndef _MSC_VER
1434  std::pair<typename MeshType<dim, spacedim>::active_cell_iterator, Point<dim> >
1435 #else
1436  std::pair<typename ::internal::ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim> >::type, Point<dim> >
1437 #endif
1439  const MeshType<dim,spacedim> &mesh,
1440  const Point<spacedim> &p,
1441  const std::vector<bool> &marked_vertices)
1442  {
1443  typedef typename ::internal::ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim> >::type active_cell_iterator;
1444 
1445  // The best distance is set to the
1446  // maximum allowable distance from
1447  // the unit cell; we assume a
1448  // max. deviation of 1e-10
1449  double best_distance = 1e-10;
1450  int best_level = -1;
1451  std::pair<active_cell_iterator, Point<dim> > best_cell;
1452 
1453  // Find closest vertex and determine
1454  // all adjacent cells
1455  std::vector<active_cell_iterator> adjacent_cells_tmp
1457  find_closest_vertex(mapping, mesh, p, marked_vertices));
1458 
1459  // Make sure that we have found
1460  // at least one cell adjacent to vertex.
1461  Assert(adjacent_cells_tmp.size()>0, ExcInternalError());
1462 
1463  // Copy all the cells into a std::set
1464  std::set<active_cell_iterator> adjacent_cells (adjacent_cells_tmp.begin(),
1465  adjacent_cells_tmp.end());
1466  std::set<active_cell_iterator> searched_cells;
1467 
1468  // Determine the maximal number of cells
1469  // in the grid.
1470  // As long as we have not found
1471  // the cell and have not searched
1472  // every cell in the triangulation,
1473  // we keep on looking.
1474  const unsigned int n_active_cells = mesh.get_triangulation().n_active_cells();
1475  bool found = false;
1476  unsigned int cells_searched = 0;
1477  while (!found && cells_searched < n_active_cells)
1478  {
1479  typename std::set<active_cell_iterator>::const_iterator
1480  cell = adjacent_cells.begin(),
1481  endc = adjacent_cells.end();
1482  for (; cell != endc; ++cell)
1483  {
1484  try
1485  {
1486  const Point<dim> p_cell = mapping.transform_real_to_unit_cell(*cell, p);
1487 
1488  // calculate the infinity norm of
1489  // the distance vector to the unit cell.
1490  const double dist = GeometryInfo<dim>::distance_to_unit_cell(p_cell);
1491 
1492  // We compare if the point is inside the
1493  // unit cell (or at least not too far
1494  // outside). If it is, it is also checked
1495  // that the cell has a more refined state
1496  if ((dist < best_distance)
1497  ||
1498  ((dist == best_distance)
1499  &&
1500  ((*cell)->level() > best_level)))
1501  {
1502  found = true;
1503  best_distance = dist;
1504  best_level = (*cell)->level();
1505  best_cell = std::make_pair(*cell, p_cell);
1506  }
1507  }
1509  {
1510  // ok, the transformation
1511  // failed presumably
1512  // because the point we
1513  // are looking for lies
1514  // outside the current
1515  // cell. this means that
1516  // the current cell can't
1517  // be the cell around the
1518  // point, so just ignore
1519  // this cell and move on
1520  // to the next
1521  }
1522  }
1523 
1524  // update the number of cells searched
1525  cells_searched += adjacent_cells.size();
1526 
1527  // if the user provided a custom mask for vertices,
1528  // terminate the search without trying to expand the search
1529  // to all cells of the triangulation, as done below.
1530  if (marked_vertices.size() > 0)
1531  cells_searched = n_active_cells;
1532 
1533  // if we have not found the cell in
1534  // question and have not yet searched every
1535  // cell, we expand our search to
1536  // all the not already searched neighbors of
1537  // the cells in adjacent_cells. This is
1538  // what find_active_cell_around_point_internal
1539  // is for.
1540  if (!found && cells_searched < n_active_cells)
1541  {
1542  find_active_cell_around_point_internal<dim,MeshType,spacedim>
1543  (mesh, searched_cells, adjacent_cells);
1544  }
1545  }
1546 
1547  AssertThrow (best_cell.first.state() == IteratorState::valid,
1548  ExcPointNotFound<spacedim>(p));
1549 
1550  return best_cell;
1551  }
1552 
1553 
1554 
1555  template <int dim,int spacedim>
1556  std::vector<std::vector<Tensor<1,spacedim> > >
1558  const std::vector<std::set<typename Triangulation<dim,spacedim>::active_cell_iterator> > &vertex_to_cells)
1559  {
1560  const std::vector<Point<spacedim> > &vertices = mesh.get_vertices();
1561  const unsigned int n_vertices = vertex_to_cells.size();
1562 
1563  AssertDimension(vertices.size(), n_vertices);
1564 
1565 
1566  std::vector<std::vector<Tensor<1,spacedim> > > vertex_to_cell_centers(n_vertices);
1567  for (unsigned int vertex=0; vertex<n_vertices; ++vertex)
1568  if (mesh.vertex_used(vertex))
1569  {
1570  const unsigned int n_neighbor_cells = vertex_to_cells[vertex].size();
1571  vertex_to_cell_centers[vertex].resize(n_neighbor_cells);
1572 
1573  typename std::set<typename Triangulation<dim,spacedim>::active_cell_iterator>::iterator it = vertex_to_cells[vertex].begin();
1574  for (unsigned int cell=0; cell<n_neighbor_cells; ++cell,++it)
1575  {
1576  vertex_to_cell_centers[vertex][cell] = (*it)->center() - vertices[vertex];
1577  vertex_to_cell_centers[vertex][cell] /= vertex_to_cell_centers[vertex][cell].norm();
1578  }
1579  }
1580  return vertex_to_cell_centers;
1581  }
1582 
1583 
1584  namespace
1585  {
1586  template <int spacedim>
1587  bool
1588  compare_point_association(const unsigned int a,
1589  const unsigned int b,
1590  const Tensor<1,spacedim> &point_direction,
1591  const std::vector<Tensor<1,spacedim> > &center_directions)
1592  {
1593  const double scalar_product_a = center_directions[a] * point_direction;
1594  const double scalar_product_b = center_directions[b] * point_direction;
1595 
1596  // The function is supposed to return if a is before b. We are looking
1597  // for the alignment of point direction and center direction, therefore
1598  // return if the scalar product of a is larger.
1599  return (scalar_product_a > scalar_product_b);
1600  }
1601  }
1602 
1603  template <int dim, template <int, int> class MeshType, int spacedim>
1604 #ifndef _MSC_VER
1605  std::pair<typename MeshType<dim, spacedim>::active_cell_iterator, Point<dim> >
1606 #else
1607  std::pair<typename ::internal::ActiveCellIterator<dim, spacedim, MeshType<dim, spacedim> >::type, Point<dim> >
1608 #endif
1610  const MeshType<dim,spacedim> &mesh,
1611  const Point<spacedim> &p,
1612  const std::vector<std::set<typename MeshType<dim,spacedim>::active_cell_iterator > > &vertex_to_cells,
1613  const std::vector<std::vector<Tensor<1,spacedim> > > &vertex_to_cell_centers,
1614  const typename MeshType<dim, spacedim>::active_cell_iterator &cell_hint ,
1615  const std::vector<bool> &marked_vertices)
1616  {
1617  std::pair<typename MeshType<dim, spacedim>::active_cell_iterator, Point<dim> > cell_and_position;
1618  // To handle points at the border we keep track of points which are close to the unit cell:
1619  std::pair<typename MeshType<dim, spacedim>::active_cell_iterator, Point<dim> > cell_and_position_approx;
1620 
1621  bool found_cell = false;
1622  bool approx_cell = false;
1623 
1624  unsigned int closest_vertex_index = 0;
1625  Tensor<1,spacedim> vertex_to_point;
1626  auto current_cell = cell_hint;
1627 
1628  while (found_cell == false)
1629  {
1630  // First look at the vertices of the cell cell_hint. If it's an
1631  // invalid cell, then query for the closest global vertex
1632  if (current_cell.state() == IteratorState::valid)
1633  {
1634  const unsigned int closest_vertex = find_closest_vertex_of_cell<dim,spacedim>(current_cell , p);
1635  vertex_to_point = p - current_cell ->vertex(closest_vertex);
1636  closest_vertex_index = current_cell ->vertex_index(closest_vertex);
1637  }
1638  else
1639  {
1640  closest_vertex_index = GridTools::find_closest_vertex(mesh,p,marked_vertices);
1641  vertex_to_point = p - mesh.get_vertices()[closest_vertex_index];
1642  }
1643 
1644  const double vertex_point_norm = vertex_to_point.norm();
1645  if (vertex_point_norm > 0)
1646  vertex_to_point /= vertex_point_norm;
1647 
1648  const unsigned int n_neighbor_cells = vertex_to_cells[closest_vertex_index].size();
1649 
1650  // Create a corresponding map of vectors from vertex to cell center
1651  std::vector<unsigned int> neighbor_permutation(n_neighbor_cells);
1652 
1653  for (unsigned int i=0; i<n_neighbor_cells; ++i)
1654  neighbor_permutation[i] = i;
1655 
1656  auto comp = [&](const unsigned int a, const unsigned int b) -> bool
1657  {
1658  return compare_point_association<spacedim>(a,b,vertex_to_point,vertex_to_cell_centers[closest_vertex_index]);
1659  };
1660 
1661  std::sort(neighbor_permutation.begin(),
1662  neighbor_permutation.end(),
1663  comp);
1664  // It is possible the vertex is close
1665  // to an edge, thus we add a tolerance
1666  // setting it initially to 1e-10
1667  // to keep also the "best" cell
1668  double best_distance = 1e-10;
1669 
1670  // Search all of the cells adjacent to the closest vertex of the cell hint
1671  // Most likely we will find the point in them.
1672  for (unsigned int i=0; i<n_neighbor_cells; ++i)
1673  {
1674  try
1675  {
1676  auto cell = vertex_to_cells[closest_vertex_index].begin();
1677  std::advance(cell,neighbor_permutation[i]);
1678  const Point<dim> p_unit = mapping.transform_real_to_unit_cell(*cell, p);
1680  {
1681  cell_and_position.first = *cell;
1682  cell_and_position.second = p_unit;
1683  found_cell = true;
1684  approx_cell = false;
1685  break;
1686  }
1687  // The point is not inside this cell: checking how far outside it is
1688  // and whether we want to use this cell as a backup if we can't find
1689  // a cell within which the point lies.
1690  const double dist = GeometryInfo<dim>::distance_to_unit_cell(p_unit);
1691  if (dist < best_distance)
1692  {
1693  best_distance = dist;
1694  cell_and_position_approx.first = *cell;
1695  cell_and_position_approx.second = p_unit;
1696  approx_cell = true;
1697  }
1698  }
1699  catch (typename Mapping<dim>::ExcTransformationFailed &)
1700  {}
1701  }
1702 
1703  if (found_cell == true)
1704  return cell_and_position;
1705  else if (approx_cell == true)
1706  return cell_and_position_approx;
1707 
1708  // The first time around, we check for vertices in the hint_cell. If that
1709  // does not work, we set the cell iterator to an invalid one, and look
1710  // for a global vertex close to the point. If that does not work, we are in
1711  // trouble, and just throw an exception.
1712  //
1713  // If we got here, then we did not find the point. If the
1714  // current_cell.state() here is not IteratorState::valid, it means that
1715  // the user did not provide a hint_cell, and at the beginning of the
1716  // while loop we performed an actual global search on the mesh
1717  // vertices. Not finding the point then means the point is outside the
1718  // domain.
1719  AssertThrow(current_cell.state() == IteratorState::valid,
1720  ExcPointNotFound<spacedim>(p));
1721 
1722  current_cell = typename MeshType<dim,spacedim>::active_cell_iterator();
1723  }
1724  return cell_and_position;
1725  }
1726 
1727 
1728 
1729  template <int dim, int spacedim>
1730  unsigned int
1732  const Point<spacedim> &position)
1733  {
1734  double minimum_distance = position.distance_square(cell->vertex(0));
1735  unsigned int closest_vertex = 0;
1736 
1737  for (unsigned int v=1; v<GeometryInfo<dim>::vertices_per_cell; ++v)
1738  {
1739  const double vertex_distance = position.distance_square(cell->vertex(v));
1740  if (vertex_distance < minimum_distance)
1741  {
1742  closest_vertex = v;
1743  minimum_distance = vertex_distance;
1744  }
1745  }
1746  return closest_vertex;
1747  }
1748 
1749 
1750 
1751  namespace internal
1752  {
1753  namespace BoundingBoxPredicate
1754  {
1755  template < class MeshType >
1756  std::tuple< BoundingBox < MeshType::space_dimension >, bool >
1757  compute_cell_predicate_bounding_box
1758  (const typename MeshType::cell_iterator &parent_cell,
1759  const std::function<bool (const typename MeshType::active_cell_iterator &)> &predicate)
1760  {
1761  bool has_predicate = false; // Start assuming there's no cells with predicate inside
1762  std::vector< typename MeshType::active_cell_iterator > active_cells;
1763  if (parent_cell->active())
1764  active_cells = {parent_cell};
1765  else
1766  //Finding all active cells descendants of the current one (or the current one if it is active)
1767  active_cells = get_active_child_cells < MeshType > (parent_cell);
1768 
1769  const unsigned int spacedim = MeshType::space_dimension;
1770 
1771  // Looking for the first active cell which has the property predicate
1772  unsigned int i = 0;
1773  while ( i < active_cells.size() && !predicate(active_cells[i]) )
1774  ++i;
1775 
1776  // No active cells or no active cells with property
1777  if ( active_cells.size() == 0 || i == active_cells.size() )
1778  {
1779  BoundingBox<spacedim> bbox;
1780  return std::make_tuple(bbox, has_predicate);
1781  }
1782 
1783  // The two boundary points defining the boundary box
1784  Point<spacedim> maxp = active_cells[i]->vertex(0);
1785  Point<spacedim> minp = active_cells[i]->vertex(0);
1786 
1787  for (; i < active_cells.size() ; ++i)
1788  if ( predicate(active_cells[i]) )
1789  for (unsigned int v=0; v<GeometryInfo<spacedim>::vertices_per_cell; ++v)
1790  for ( unsigned int d=0; d<spacedim; ++d)
1791  {
1792  minp[d] = std::min( minp[d], active_cells[i]->vertex(v)[d]);
1793  maxp[d] = std::max( maxp[d], active_cells[i]->vertex(v)[d]);
1794  }
1795 
1796  has_predicate = true;
1797  BoundingBox < spacedim > bbox(std::make_pair(minp,maxp));
1798  return std::make_tuple(bbox, has_predicate);
1799  }
1800  }
1801  }
1802 
1803 
1804 
1805  template < class MeshType >
1806  std::vector< BoundingBox<MeshType::space_dimension> >
1808  (const MeshType &mesh,
1809  const std::function<bool (const typename MeshType::active_cell_iterator &)> &predicate,
1810  const unsigned int refinement_level,
1811  const bool allow_merge,
1812  const unsigned int max_boxes)
1813  {
1814  // Algorithm brief description: begin with creating bounding boxes of all cells at
1815  // refinement_level (and coarser levels if there are active cells) which have the predicate
1816  // property. These are then merged
1817 
1818  Assert( refinement_level <= mesh.n_levels(),
1819  ExcMessage ( "Error: refinement level is higher then total levels in the triangulation!") );
1820 
1821  const unsigned int spacedim = MeshType::space_dimension;
1822  std::vector< BoundingBox < spacedim > > bounding_boxes;
1823 
1824  // Creating a bounding box for all active cell on coarser level
1825 
1826  for (unsigned int i=0; i < refinement_level; ++i)
1827  for (typename MeshType::cell_iterator cell: mesh.active_cell_iterators_on_level(i))
1828  {
1829  bool has_predicate = false;
1831  std::tie(bbox, has_predicate) =
1832  internal::BoundingBoxPredicate::compute_cell_predicate_bounding_box <MeshType> (cell, predicate);
1833  if (has_predicate)
1834  bounding_boxes.push_back(bbox);
1835  }
1836 
1837  // Creating a Bounding Box for all cells on the chosen refinement_level
1838  for (const typename MeshType::cell_iterator &cell: mesh.cell_iterators_on_level(refinement_level))
1839  {
1840  bool has_predicate = false;
1842  std::tie(bbox, has_predicate) =
1843  internal::BoundingBoxPredicate::compute_cell_predicate_bounding_box <MeshType> (cell, predicate);
1844  if (has_predicate)
1845  bounding_boxes.push_back(bbox);
1846  }
1847 
1848  if ( !allow_merge)
1849  // If merging is not requested return the created bounding_boxes
1850  return bounding_boxes;
1851  else
1852  {
1853  // Merging part of the algorithm
1854  // Part 1: merging neighbors
1855  // This array stores the indices of arrays we have already merged
1856  std::vector<unsigned int> merged_boxes_idx;
1857  bool found_neighbors = true;
1858 
1859  // We merge only neighbors which can be expressed by a single bounding box
1860  // e.g. in 1d [0,1] and [1,2] can be described with [0,2] without losing anything
1861  while (found_neighbors)
1862  {
1863  found_neighbors = false;
1864  for (unsigned int i=0; i<bounding_boxes.size()-1; ++i)
1865  {
1866  if ( std::find(merged_boxes_idx.begin(),merged_boxes_idx.end(),i) == merged_boxes_idx.end())
1867  for (unsigned int j=i+1; j<bounding_boxes.size(); ++j)
1868  if ( std::find(merged_boxes_idx.begin(),merged_boxes_idx.end(),j) == merged_boxes_idx.end()
1869  && bounding_boxes[i].get_neighbor_type (bounding_boxes[j]) == NeighborType::mergeable_neighbors )
1870  {
1871  bounding_boxes[i].merge_with(bounding_boxes[j]);
1872  merged_boxes_idx.push_back(j);
1873  found_neighbors = true;
1874  }
1875  }
1876  }
1877 
1878  // Copying the merged boxes into merged_b_boxes
1879  std::vector< BoundingBox < spacedim > > merged_b_boxes;
1880  for (unsigned int i=0; i<bounding_boxes.size(); ++i)
1881  if (std::find(merged_boxes_idx.begin(),merged_boxes_idx.end(),i) == merged_boxes_idx.end())
1882  merged_b_boxes.push_back(bounding_boxes[i]);
1883 
1884  // Part 2: if there are too many bounding boxes, merging smaller boxes
1885  // This has sense only in dimension 2 or greater, since in dimension 1,
1886  // neighboring intervals can always be merged without problems
1887  if ( (merged_b_boxes.size() > max_boxes) && (spacedim > 1) )
1888  {
1889  std::vector<double> volumes;
1890  for (unsigned int i=0; i< merged_b_boxes.size(); ++i)
1891  volumes.push_back(merged_b_boxes[i].volume());
1892 
1893  while ( merged_b_boxes.size() > max_boxes)
1894  {
1895  unsigned int min_idx = std::min_element(volumes.begin(),volumes.end()) -
1896  volumes.begin();
1897  volumes.erase(volumes.begin() + min_idx);
1898  //Finding a neighbor
1899  bool not_removed = true;
1900  for (unsigned int i=0; i<merged_b_boxes.size() && not_removed; ++i)
1901  // We merge boxes if we have "attached" or "mergeable" neighbors, even though mergeable should
1902  // be dealt with in Part 1
1903  if ( i != min_idx &&
1904  (merged_b_boxes[i].get_neighbor_type (merged_b_boxes[min_idx]) == NeighborType::attached_neighbors ||
1905  merged_b_boxes[i].get_neighbor_type (merged_b_boxes[min_idx]) == NeighborType::mergeable_neighbors) )
1906  {
1907  merged_b_boxes[i].merge_with(merged_b_boxes[min_idx]);
1908  merged_b_boxes.erase(merged_b_boxes.begin() + min_idx);
1909  not_removed = false;
1910  }
1911  Assert( !not_removed,
1912  ExcMessage ( "Error: couldn't merge bounding boxes!") );
1913  }
1914  }
1915  Assert( merged_b_boxes.size() <= max_boxes,
1916  ExcMessage ( "Error: couldn't reach target number of bounding boxes!") );
1917  return merged_b_boxes;
1918  }
1919  }
1920 
1921 
1922 
1923 
1924  template <int spacedim>
1925  std::tuple< std::vector< std::vector< unsigned int > >,
1926  std::map< unsigned int, unsigned int>,
1927  std::map< unsigned int, std::vector< unsigned int > > >
1928  guess_point_owner (const std::vector< std::vector< BoundingBox<spacedim> > >
1929  &global_bboxes,
1930  const std::vector< Point<spacedim> > &points)
1931  {
1932  unsigned int n_procs = global_bboxes.size();
1933  std::vector< std::vector< unsigned int > > point_owners(n_procs);
1934  std::map< unsigned int, unsigned int> map_owners_found;
1935  std::map< unsigned int, std::vector< unsigned int > > map_owners_guessed;
1936 
1937  unsigned int n_points = points.size();
1938  for (unsigned int pt=0; pt<n_points; ++pt)
1939  {
1940  // Keep track of how many processes we guess to own the point
1941  std::vector< unsigned int > owners_found;
1942  // Check in which other processes the point might be
1943  for (unsigned int rk=0; rk<n_procs; ++rk)
1944  {
1945  for (const BoundingBox<spacedim> &bbox: global_bboxes[rk])
1946  if (bbox.point_inside(points[pt]))
1947  {
1948  point_owners[rk].emplace_back(pt);
1949  owners_found.emplace_back(rk);
1950  break; // We can check now the next process
1951  }
1952  }
1953  Assert(owners_found.size() > 0,
1954  ExcMessage("No owners found for the point " + std::to_string(pt)));
1955  if (owners_found.size()==1)
1956  map_owners_found[pt] = owners_found[0];
1957  else
1958  // Multiple owners
1959  map_owners_guessed[pt] = owners_found;
1960  }
1961 
1962  std::tuple< std::vector< std::vector< unsigned int > >,
1963  std::map< unsigned int, unsigned int>,
1964  std::map< unsigned int, std::vector< unsigned int > > >
1965  output_tuple;
1966 
1967  std::get<0>(output_tuple) = point_owners;
1968  std::get<1>(output_tuple) = map_owners_found;
1969  std::get<2>(output_tuple) = map_owners_guessed;
1970 
1971  return output_tuple;
1972  }
1973 
1974 
1975 
1976  template <int dim, int spacedim>
1977  std::vector<std::set<typename Triangulation<dim,spacedim>::active_cell_iterator> >
1979  {
1980  std::vector<std::set<typename Triangulation<dim,spacedim>::active_cell_iterator> >
1981  vertex_to_cell_map(triangulation.n_vertices());
1982  typename Triangulation<dim,spacedim>::active_cell_iterator cell = triangulation.begin_active(),
1983  endc = triangulation.end();
1984  for (; cell!=endc; ++cell)
1985  for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
1986  vertex_to_cell_map[cell->vertex_index(i)].insert(cell);
1987 
1988  // Take care of hanging nodes
1989  cell = triangulation.begin_active();
1990  for (; cell!=endc; ++cell)
1991  {
1992  for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
1993  {
1994  if ((cell->at_boundary(i)==false) && (cell->neighbor(i)->active()))
1995  {
1996  typename Triangulation<dim,spacedim>::active_cell_iterator adjacent_cell =
1997  cell->neighbor(i);
1998  for (unsigned int j=0; j<GeometryInfo<dim>::vertices_per_face; ++j)
1999  vertex_to_cell_map[cell->face(i)->vertex_index(j)].insert(adjacent_cell);
2000  }
2001  }
2002 
2003  // in 3d also loop over the edges
2004  if (dim==3)
2005  {
2006  for (unsigned int i=0; i<GeometryInfo<dim>::lines_per_cell; ++i)
2007  if (cell->line(i)->has_children())
2008  // the only place where this vertex could have been
2009  // hiding is on the mid-edge point of the edge we
2010  // are looking at
2011  vertex_to_cell_map[cell->line(i)->child(0)->vertex_index(1)].insert(cell);
2012  }
2013  }
2014 
2015  return vertex_to_cell_map;
2016  }
2017 
2018 
2019 
2020  template <int dim, int spacedim>
2021  std::map<unsigned int,types::global_vertex_index>
2024  {
2025  std::map<unsigned int,types::global_vertex_index> local_to_global_vertex_index;
2026 
2027 #ifndef DEAL_II_WITH_MPI
2028 
2029  // without MPI, this function doesn't make sense because on cannot
2030  // use parallel::distributed::Triangulation in any meaningful
2031  // way
2032  (void)triangulation;
2033  Assert (false, ExcMessage ("This function does not make any sense "
2034  "for parallel::distributed::Triangulation "
2035  "objects if you do not have MPI enabled."));
2036 
2037 #else
2038 
2039  typedef typename Triangulation<dim,spacedim>::active_cell_iterator active_cell_iterator;
2040  const std::vector<std::set<active_cell_iterator> > vertex_to_cell =
2041  vertex_to_cell_map(triangulation);
2042 
2043  // Create a local index for the locally "owned" vertices
2044  types::global_vertex_index next_index = 0;
2045  unsigned int max_cellid_size = 0;
2046  std::set<std::pair<types::subdomain_id,types::global_vertex_index> > vertices_added;
2047  std::map<types::subdomain_id,std::set<unsigned int> > vertices_to_recv;
2048  std::map<types::subdomain_id,std::vector<std::tuple<types::global_vertex_index,
2049  types::global_vertex_index,std::string> > > vertices_to_send;
2050  active_cell_iterator cell = triangulation.begin_active(),
2051  endc = triangulation.end();
2052  std::set<active_cell_iterator> missing_vert_cells;
2053  std::set<unsigned int> used_vertex_index;
2054  for (; cell!=endc; ++cell)
2055  {
2056  if (cell->is_locally_owned())
2057  {
2058  for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_cell; ++i)
2059  {
2060  types::subdomain_id lowest_subdomain_id = cell->subdomain_id();
2061  typename std::set<active_cell_iterator>::iterator
2062  adjacent_cell = vertex_to_cell[cell->vertex_index(i)].begin(),
2063  end_adj_cell = vertex_to_cell[cell->vertex_index(i)].end();
2064  for (; adjacent_cell!=end_adj_cell; ++adjacent_cell)
2065  lowest_subdomain_id = std::min(lowest_subdomain_id,
2066  (*adjacent_cell)->subdomain_id());
2067 
2068  // See if I "own" this vertex
2069  if (lowest_subdomain_id==cell->subdomain_id())
2070  {
2071  // Check that the vertex we are working on a vertex that has not be
2072  // dealt with yet
2073  if (used_vertex_index.find(cell->vertex_index(i))==used_vertex_index.end())
2074  {
2075  // Set the local index
2076  local_to_global_vertex_index[cell->vertex_index(i)] = next_index++;
2077 
2078  // Store the information that will be sent to the adjacent cells
2079  // on other subdomains
2080  adjacent_cell = vertex_to_cell[cell->vertex_index(i)].begin();
2081  for (; adjacent_cell!=end_adj_cell; ++adjacent_cell)
2082  if ((*adjacent_cell)->subdomain_id()!=cell->subdomain_id())
2083  {
2084  std::pair<types::subdomain_id,types::global_vertex_index>
2085  tmp((*adjacent_cell)->subdomain_id(), cell->vertex_index(i));
2086  if (vertices_added.find(tmp)==vertices_added.end())
2087  {
2088  vertices_to_send[(*adjacent_cell)->subdomain_id()].emplace_back
2089  (i, cell->vertex_index(i), cell->id().to_string());
2090  if (cell->id().to_string().size() > max_cellid_size)
2091  max_cellid_size = cell->id().to_string().size();
2092  vertices_added.insert(tmp);
2093  }
2094  }
2095  used_vertex_index.insert(cell->vertex_index(i));
2096  }
2097  }
2098  else
2099  {
2100  // We don't own the vertex so we will receive its global index
2101  vertices_to_recv[lowest_subdomain_id].insert(cell->vertex_index(i));
2102  missing_vert_cells.insert(cell);
2103  }
2104  }
2105  }
2106 
2107  // Some hanging nodes are vertices of ghost cells. They need to be
2108  // received.
2109  if (cell->is_ghost())
2110  {
2111  for (unsigned int i=0; i<GeometryInfo<dim>::faces_per_cell; ++i)
2112  {
2113  if (cell->at_boundary(i)==false)
2114  {
2115  if (cell->neighbor(i)->active())
2116  {
2117  typename Triangulation<dim,spacedim>::active_cell_iterator adjacent_cell =
2118  cell->neighbor(i);
2119  if ((adjacent_cell->is_locally_owned()))
2120  {
2121  types::subdomain_id adj_subdomain_id = adjacent_cell->subdomain_id();
2122  if (cell->subdomain_id()<adj_subdomain_id)
2123  for (unsigned int j=0; j<GeometryInfo<dim>::vertices_per_face; ++j)
2124  {
2125  vertices_to_recv[cell->subdomain_id()].insert(cell->face(i)->vertex_index(j));
2126  missing_vert_cells.insert(cell);
2127  }
2128  }
2129  }
2130  }
2131  }
2132  }
2133  }
2134 
2135  // Get the size of the largest CellID string
2136  max_cellid_size = Utilities::MPI::max(max_cellid_size, triangulation.get_communicator());
2137 
2138  // Make indices global by getting the number of vertices owned by each
2139  // processors and shifting the indices accordingly
2140  const unsigned int n_cpu = Utilities::MPI::n_mpi_processes(triangulation.get_communicator());
2141  std::vector<types::global_vertex_index> indices(n_cpu);
2142  int ierr = MPI_Allgather(&next_index, 1, DEAL_II_VERTEX_INDEX_MPI_TYPE, indices.data(),
2143  1, DEAL_II_VERTEX_INDEX_MPI_TYPE, triangulation.get_communicator());
2144  AssertThrowMPI(ierr);
2145  Assert(indices.begin() + triangulation.locally_owned_subdomain() < indices.end(),
2146  ExcInternalError());
2147  const types::global_vertex_index shift = std::accumulate(indices.begin(),
2148  indices.begin()+triangulation.locally_owned_subdomain(),
2150 
2151  std::map<unsigned int,types::global_vertex_index>::iterator
2152  global_index_it = local_to_global_vertex_index.begin(),
2153  global_index_end = local_to_global_vertex_index.end();
2154  for (; global_index_it!=global_index_end; ++global_index_it)
2155  global_index_it->second += shift;
2156 
2157  // In a first message, send the global ID of the vertices and the local
2158  // positions in the cells. In a second messages, send the cell ID as a
2159  // resize string. This is done in two messages so that types are not mixed
2160 
2161  // Send the first message
2162  std::vector<std::vector<types::global_vertex_index> > vertices_send_buffers(
2163  vertices_to_send.size());
2164  std::vector<MPI_Request> first_requests(vertices_to_send.size());
2165  typename std::map<types::subdomain_id,
2166  std::vector<std::tuple<types::global_vertex_index,
2167  types::global_vertex_index,std::string> > >::iterator
2168  vert_to_send_it = vertices_to_send.begin(),
2169  vert_to_send_end = vertices_to_send.end();
2170  for (unsigned int i=0; vert_to_send_it!=vert_to_send_end;
2171  ++vert_to_send_it, ++i)
2172  {
2173  int destination = vert_to_send_it->first;
2174  const unsigned int n_vertices = vert_to_send_it->second.size();
2175  const int buffer_size = 2*n_vertices;
2176  vertices_send_buffers[i].resize(buffer_size);
2177 
2178  // fill the buffer
2179  for (unsigned int j=0; j<n_vertices; ++j)
2180  {
2181  vertices_send_buffers[i][2*j] = std::get<0>(vert_to_send_it->second[j]);
2182  vertices_send_buffers[i][2*j+1] =
2183  local_to_global_vertex_index[std::get<1>(vert_to_send_it->second[j])];
2184  }
2185 
2186  // Send the message
2187  ierr = MPI_Isend(&vertices_send_buffers[i][0],buffer_size,DEAL_II_VERTEX_INDEX_MPI_TYPE,
2188  destination, 0, triangulation.get_communicator(), &first_requests[i]);
2189  AssertThrowMPI(ierr);
2190  }
2191 
2192  // Receive the first message
2193  std::vector<std::vector<types::global_vertex_index> > vertices_recv_buffers(
2194  vertices_to_recv.size());
2195  typename std::map<types::subdomain_id,std::set<unsigned int> >::iterator
2196  vert_to_recv_it = vertices_to_recv.begin(),
2197  vert_to_recv_end = vertices_to_recv.end();
2198  for (unsigned int i=0; vert_to_recv_it!=vert_to_recv_end; ++vert_to_recv_it, ++i)
2199  {
2200  int source = vert_to_recv_it->first;
2201  const unsigned int n_vertices = vert_to_recv_it->second.size();
2202  const int buffer_size = 2*n_vertices;
2203  vertices_recv_buffers[i].resize(buffer_size);
2204 
2205  // Receive the message
2206  ierr = MPI_Recv(&vertices_recv_buffers[i][0],buffer_size,DEAL_II_VERTEX_INDEX_MPI_TYPE,
2207  source, 0, triangulation.get_communicator(), MPI_STATUS_IGNORE);
2208  AssertThrowMPI(ierr);
2209  }
2210 
2211 
2212  // Send second message
2213  std::vector<std::vector<char> > cellids_send_buffers(vertices_to_send.size());
2214  std::vector<MPI_Request> second_requests(vertices_to_send.size());
2215  vert_to_send_it = vertices_to_send.begin();
2216  for (unsigned int i=0; vert_to_send_it!=vert_to_send_end;
2217  ++vert_to_send_it, ++i)
2218  {
2219  int destination = vert_to_send_it->first;
2220  const unsigned int n_vertices = vert_to_send_it->second.size();
2221  const int buffer_size = max_cellid_size*n_vertices;
2222  cellids_send_buffers[i].resize(buffer_size);
2223 
2224  // fill the buffer
2225  unsigned int pos = 0;
2226  for (unsigned int j=0; j<n_vertices; ++j)
2227  {
2228  std::string cell_id = std::get<2>(vert_to_send_it->second[j]);
2229  for (unsigned int k=0; k<max_cellid_size; ++k, ++pos)
2230  {
2231  if (k<cell_id.size())
2232  cellids_send_buffers[i][pos] = cell_id[k];
2233  // if necessary fill up the reserved part of the buffer with an
2234  // invalid value
2235  else
2236  cellids_send_buffers[i][pos] = '-';
2237  }
2238  }
2239 
2240  // Send the message
2241  ierr = MPI_Isend(&cellids_send_buffers[i][0], buffer_size, MPI_CHAR,
2242  destination, 0, triangulation.get_communicator(), &second_requests[i]);
2243  AssertThrowMPI(ierr);
2244  }
2245 
2246  // Receive the second message
2247  std::vector<std::vector<char> > cellids_recv_buffers(vertices_to_recv.size());
2248  vert_to_recv_it = vertices_to_recv.begin();
2249  for (unsigned int i=0; vert_to_recv_it!=vert_to_recv_end; ++vert_to_recv_it, ++i)
2250  {
2251  int source = vert_to_recv_it->first;
2252  const unsigned int n_vertices = vert_to_recv_it->second.size();
2253  const int buffer_size = max_cellid_size*n_vertices;
2254  cellids_recv_buffers[i].resize(buffer_size);
2255 
2256  // Receive the message
2257  ierr = MPI_Recv(&cellids_recv_buffers[i][0],buffer_size, MPI_CHAR,
2258  source, 0, triangulation.get_communicator(), MPI_STATUS_IGNORE);
2259  AssertThrowMPI(ierr);
2260  }
2261 
2262 
2263  // Match the data received with the required vertices
2264  vert_to_recv_it = vertices_to_recv.begin();
2265  for (unsigned int i=0; vert_to_recv_it!=vert_to_recv_end; ++i, ++vert_to_recv_it)
2266  {
2267  for (unsigned int j=0; j<vert_to_recv_it->second.size(); ++j)
2268  {
2269  const unsigned int local_pos_recv = vertices_recv_buffers[i][2*j];
2270  const types::global_vertex_index global_id_recv = vertices_recv_buffers[i][2*j+1];
2271  const std::string cellid_recv(&cellids_recv_buffers[i][max_cellid_size*j],
2272  &cellids_recv_buffers[i][max_cellid_size*(j+1)]);
2273  bool found = false;
2274  typename std::set<active_cell_iterator>::iterator
2275  cell_set_it = missing_vert_cells.begin(),
2276  end_cell_set = missing_vert_cells.end();
2277  for (; (found==false) && (cell_set_it!=end_cell_set); ++cell_set_it)
2278  {
2279  typename std::set<active_cell_iterator>::iterator
2280  candidate_cell = vertex_to_cell[(*cell_set_it)->vertex_index(i)].begin(),
2281  end_cell = vertex_to_cell[(*cell_set_it)->vertex_index(i)].end();
2282  for (; candidate_cell!=end_cell; ++candidate_cell)
2283  {
2284  std::string current_cellid = (*candidate_cell)->id().to_string();
2285  current_cellid.resize(max_cellid_size,'-');
2286  if (current_cellid.compare(cellid_recv)==0)
2287  {
2288  local_to_global_vertex_index[(*candidate_cell)->vertex_index(local_pos_recv)] =
2289  global_id_recv;
2290  found = true;
2291 
2292  break;
2293  }
2294  }
2295  }
2296  }
2297  }
2298 #endif
2299 
2300  return local_to_global_vertex_index;
2301  }
2302 
2303 
2304 
2305  template <int dim, int spacedim>
2306  void
2308  DynamicSparsityPattern &cell_connectivity)
2309  {
2310  cell_connectivity.reinit (triangulation.n_active_cells(),
2311  triangulation.n_active_cells());
2312 
2313  // create a map pair<lvl,idx> -> SparsityPattern index
2314  // TODO: we are no longer using user_indices for this because we can get
2315  // pointer/index clashes when saving/restoring them. The following approach
2316  // works, but this map can get quite big. Not sure about more efficient solutions.
2317  std::map< std::pair<unsigned int,unsigned int>, unsigned int >
2318  indexmap;
2319  for (typename ::internal::ActiveCellIterator<dim, spacedim, Triangulation<dim, spacedim> >::type
2320  cell = triangulation.begin_active();
2321  cell != triangulation.end(); ++cell)
2322  indexmap[std::pair<unsigned int,unsigned int>(cell->level(),cell->index())] = cell->active_cell_index();
2323 
2324  // next loop over all cells and their neighbors to build the sparsity
2325  // pattern. note that it's a bit hard to enter all the connections when a
2326  // neighbor has children since we would need to find out which of its
2327  // children is adjacent to the current cell. this problem can be omitted
2328  // if we only do something if the neighbor has no children -- in that case
2329  // it is either on the same or a coarser level than we are. in return, we
2330  // have to add entries in both directions for both cells
2331  for (typename ::internal::ActiveCellIterator<dim, spacedim, Triangulation<dim, spacedim> >::type
2332  cell = triangulation.begin_active();
2333  cell != triangulation.end(); ++cell)
2334  {
2335  const unsigned int index = cell->active_cell_index();
2336  cell_connectivity.add (index, index);
2337  for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
2338  if ((cell->at_boundary(f) == false)
2339  &&
2340  (cell->neighbor(f)->has_children() == false))
2341  {
2342  unsigned int other_index = indexmap.find(
2343  std::pair<unsigned int,unsigned int>(cell->neighbor(f)->level(),cell->neighbor(f)->index()))->second;
2344  cell_connectivity.add (index, other_index);
2345  cell_connectivity.add (other_index, index);
2346  }
2347  }
2348  }
2349 
2350 
2351 
2352  template <int dim, int spacedim>
2353  void
2355  DynamicSparsityPattern &cell_connectivity)
2356  {
2357  std::vector<std::vector<unsigned int> > vertex_to_cell(triangulation.n_vertices());
2359  triangulation.begin_active(); cell != triangulation.end(); ++cell)
2360  {
2361  for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
2362  vertex_to_cell[cell->vertex_index(v)].push_back(cell->active_cell_index());
2363  }
2364 
2365  cell_connectivity.reinit (triangulation.n_active_cells(),
2366  triangulation.n_active_cells());
2368  triangulation.begin_active(); cell != triangulation.end(); ++cell)
2369  {
2370  for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
2371  for (unsigned int n=0; n<vertex_to_cell[cell->vertex_index(v)].size(); ++n)
2372  cell_connectivity.add(cell->active_cell_index(), vertex_to_cell[cell->vertex_index(v)][n]);
2373  }
2374  }
2375 
2376 
2377  template <int dim, int spacedim>
2378  void
2380  const unsigned int level,
2381  DynamicSparsityPattern &cell_connectivity)
2382  {
2383  std::vector<std::vector<unsigned int> > vertex_to_cell(triangulation.n_vertices());
2384  for (typename Triangulation<dim,spacedim>::cell_iterator cell=
2385  triangulation.begin(level); cell != triangulation.end(level); ++cell)
2386  {
2387  for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
2388  vertex_to_cell[cell->vertex_index(v)].push_back(cell->index());
2389  }
2390 
2391  cell_connectivity.reinit (triangulation.n_cells(level),
2392  triangulation.n_cells(level));
2393  for (typename Triangulation<dim,spacedim>::cell_iterator cell=
2394  triangulation.begin(level); cell != triangulation.end(level); ++cell)
2395  {
2396  for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
2397  for (unsigned int n=0; n<vertex_to_cell[cell->vertex_index(v)].size(); ++n)
2398  cell_connectivity.add(cell->index(), vertex_to_cell[cell->vertex_index(v)][n]);
2399  }
2400  }
2401 
2402 
2403 
2404  template <int dim, int spacedim>
2405  void
2406  partition_triangulation (const unsigned int n_partitions,
2407  Triangulation<dim,spacedim> &triangulation,
2408  const SparsityTools::Partitioner partitioner
2409  )
2410  {
2411  std::vector<unsigned int> cell_weights;
2412 
2413  // Get cell weighting if a signal has been attached to the triangulation
2414  if (!triangulation.signals.cell_weight.empty())
2415  {
2416  cell_weights.resize(triangulation.n_active_cells(), std::numeric_limits<unsigned int>::max());
2417 
2418  unsigned int c = 0;
2420  cell = triangulation.begin_active(),
2421  endc = triangulation.end();
2422  for (; cell!=endc; ++cell, ++c)
2423  cell_weights[c] = triangulation.signals.cell_weight(cell, Triangulation<dim,spacedim>::CellStatus::CELL_PERSIST);
2424  }
2425 
2426  // Call the other more general function
2427  partition_triangulation(n_partitions, cell_weights,
2428  triangulation, partitioner);
2429  }
2430 
2431 
2432 
2433  template <int dim, int spacedim>
2434  void
2435  partition_triangulation (const unsigned int n_partitions,
2436  const std::vector<unsigned int> &cell_weights,
2437  Triangulation<dim,spacedim> &triangulation,
2438  const SparsityTools::Partitioner partitioner
2439  )
2440  {
2442  (&triangulation)
2443  == nullptr),
2444  ExcMessage ("Objects of type parallel::distributed::Triangulation "
2445  "are already partitioned implicitly and can not be "
2446  "partitioned again explicitly."));
2447  Assert (n_partitions > 0, ExcInvalidNumberOfPartitions(n_partitions));
2448 
2449  // check for an easy return
2450  if (n_partitions == 1)
2451  {
2452  for (typename ::internal::ActiveCellIterator<dim, spacedim, Triangulation<dim, spacedim> >::type
2453  cell = triangulation.begin_active();
2454  cell != triangulation.end(); ++cell)
2455  cell->set_subdomain_id (0);
2456  return;
2457  }
2458 
2459  // we decompose the domain by first
2460  // generating the connection graph of all
2461  // cells with their neighbors, and then
2462  // passing this graph off to METIS.
2463  // finally defer to the other function for
2464  // partitioning and assigning subdomain ids
2465  DynamicSparsityPattern cell_connectivity;
2466  get_face_connectivity_of_cells (triangulation, cell_connectivity);
2467 
2468  SparsityPattern sp_cell_connectivity;
2469  sp_cell_connectivity.copy_from(cell_connectivity);
2470  partition_triangulation (n_partitions,
2471  cell_weights,
2472  sp_cell_connectivity,
2473  triangulation,
2474  partitioner
2475  );
2476  }
2477 
2478 
2479 
2480  template <int dim, int spacedim>
2481  void
2482  partition_triangulation (const unsigned int n_partitions,
2483  const SparsityPattern &cell_connection_graph,
2484  Triangulation<dim,spacedim> &triangulation,
2485  const SparsityTools::Partitioner partitioner
2486  )
2487  {
2488  std::vector<unsigned int> cell_weights;
2489 
2490  // Get cell weighting if a signal has been attached to the triangulation
2491  if (!triangulation.signals.cell_weight.empty())
2492  {
2493  cell_weights.resize(triangulation.n_active_cells(), std::numeric_limits<unsigned int>::max());
2494 
2495  unsigned int c = 0;
2497  cell = triangulation.begin_active(),
2498  endc = triangulation.end();
2499  for (; cell!=endc; ++cell, ++c)
2500  cell_weights[c] = triangulation.signals.cell_weight(cell, Triangulation<dim,spacedim>::CellStatus::CELL_PERSIST);
2501  }
2502 
2503  // Call the other more general function
2504  partition_triangulation(n_partitions, cell_weights,
2505  cell_connection_graph,
2506  triangulation, partitioner);
2507  }
2508 
2509 
2510 
2511  template <int dim, int spacedim>
2512  void
2513  partition_triangulation (const unsigned int n_partitions,
2514  const std::vector<unsigned int> &cell_weights,
2515  const SparsityPattern &cell_connection_graph,
2516  Triangulation<dim,spacedim> &triangulation,
2517  const SparsityTools::Partitioner partitioner
2518  )
2519  {
2521  (&triangulation)
2522  == nullptr),
2523  ExcMessage ("Objects of type parallel::distributed::Triangulation "
2524  "are already partitioned implicitly and can not be "
2525  "partitioned again explicitly."));
2526  Assert (n_partitions > 0, ExcInvalidNumberOfPartitions(n_partitions));
2527  Assert (cell_connection_graph.n_rows() == triangulation.n_active_cells(),
2528  ExcMessage ("Connectivity graph has wrong size"));
2529  Assert (cell_connection_graph.n_cols() == triangulation.n_active_cells(),
2530  ExcMessage ("Connectivity graph has wrong size"));
2531 
2532  // check for an easy return
2533  if (n_partitions == 1)
2534  {
2535  for (typename ::internal::ActiveCellIterator<dim, spacedim, Triangulation<dim, spacedim> >::type
2536  cell = triangulation.begin_active();
2537  cell != triangulation.end(); ++cell)
2538  cell->set_subdomain_id (0);
2539  return;
2540  }
2541 
2542  // partition this connection graph and get
2543  // back a vector of indices, one per degree
2544  // of freedom (which is associated with a
2545  // cell)
2546  std::vector<unsigned int> partition_indices (triangulation.n_active_cells());
2547  SparsityTools::partition (cell_connection_graph, cell_weights, n_partitions,
2548  partition_indices, partitioner);
2549 
2550  // finally loop over all cells and set the
2551  // subdomain ids
2552  for (typename ::internal::ActiveCellIterator<dim, spacedim, Triangulation<dim, spacedim> >::type
2553  cell = triangulation.begin_active();
2554  cell != triangulation.end(); ++cell)
2555  cell->set_subdomain_id (partition_indices[cell->active_cell_index()]);
2556  }
2557 
2558 
2559  namespace
2560  {
2564  template <class IT>
2565  void set_subdomain_id_in_zorder_recursively(IT cell,
2566  unsigned int &current_proc_idx,
2567  unsigned int &current_cell_idx,
2568  const unsigned int n_active_cells,
2569  const unsigned int n_partitions)
2570  {
2571  if (cell->active())
2572  {
2573  while (current_cell_idx >= floor((long)n_active_cells*(current_proc_idx+1)/n_partitions))
2574  ++current_proc_idx;
2575  cell->set_subdomain_id(current_proc_idx);
2576  ++current_cell_idx;
2577  }
2578  else
2579  {
2580  for (unsigned int n=0; n<cell->n_children(); ++n)
2581  set_subdomain_id_in_zorder_recursively(cell->child(n),
2582  current_proc_idx,
2583  current_cell_idx,
2584  n_active_cells,
2585  n_partitions);
2586  }
2587  }
2588  }
2589 
2590  template <int dim, int spacedim>
2591  void
2592  partition_triangulation_zorder (const unsigned int n_partitions,
2593  Triangulation<dim,spacedim> &triangulation)
2594  {
2596  (&triangulation)
2597  == nullptr),
2598  ExcMessage ("Objects of type parallel::distributed::Triangulation "
2599  "are already partitioned implicitly and can not be "
2600  "partitioned again explicitly."));
2601  Assert (n_partitions > 0, ExcInvalidNumberOfPartitions(n_partitions));
2602 
2603  // check for an easy return
2604  if (n_partitions == 1)
2605  {
2606  for (typename ::internal::ActiveCellIterator<dim, spacedim, Triangulation<dim, spacedim> >::type
2607  cell = triangulation.begin_active();
2608  cell != triangulation.end(); ++cell)
2609  cell->set_subdomain_id (0);
2610  return;
2611  }
2612 
2613  // Duplicate the coarse cell reordoring
2614  // as done in p4est
2615  std::vector<types::global_dof_index> coarse_cell_to_p4est_tree_permutation;
2616  std::vector<types::global_dof_index> p4est_tree_to_coarse_cell_permutation;
2617 
2618  DynamicSparsityPattern cell_connectivity;
2619  GridTools::get_vertex_connectivity_of_cells_on_level (triangulation, 0, cell_connectivity);
2620  coarse_cell_to_p4est_tree_permutation.resize (triangulation.n_cells(0));
2621  SparsityTools::reorder_hierarchical (cell_connectivity,
2622  coarse_cell_to_p4est_tree_permutation);
2623 
2624  p4est_tree_to_coarse_cell_permutation
2625  = Utilities::invert_permutation (coarse_cell_to_p4est_tree_permutation);
2626 
2627  unsigned int current_proc_idx=0;
2628  unsigned int current_cell_idx=0;
2629  const unsigned int n_active_cells = triangulation.n_active_cells();
2630 
2631  // set subdomain id for active cell descendants
2632  // of each coarse cell in permuted order
2633  for (unsigned int idx=0; idx<triangulation.n_cells(0); ++idx)
2634  {
2635  const unsigned int coarse_cell_idx = p4est_tree_to_coarse_cell_permutation[idx];
2637  coarse_cell (&triangulation, 0, coarse_cell_idx);
2638 
2639  set_subdomain_id_in_zorder_recursively(coarse_cell,
2640  current_proc_idx,
2641  current_cell_idx,
2642  n_active_cells,
2643  n_partitions);
2644  }
2645 
2646  // if all children of a cell are active (e.g. we
2647  // have a cell that is refined once and no part
2648  // is refined further), p4est places all of them
2649  // on the same processor. The new owner will be
2650  // the processor with the largest number of children
2651  // (ties are broken by picking the lower rank).
2652  // Duplicate this logic here.
2653  {
2655  cell = triangulation.begin(),
2656  endc = triangulation.end();
2657  for (; cell!=endc; ++cell)
2658  {
2659  if (cell->active())
2660  continue;
2661  bool all_children_active = true;
2662  std::map<unsigned int, unsigned int> map_cpu_n_cells;
2663  for (unsigned int n=0; n<cell->n_children(); ++n)
2664  if (!cell->child(n)->active())
2665  {
2666  all_children_active = false;
2667  break;
2668  }
2669  else
2670  ++map_cpu_n_cells[cell->child(n)->subdomain_id()];
2671 
2672  if (!all_children_active)
2673  continue;
2674 
2675  unsigned int new_owner = cell->child(0)->subdomain_id();
2676  for (std::map<unsigned int, unsigned int>::iterator it = map_cpu_n_cells.begin();
2677  it != map_cpu_n_cells.end();
2678  ++it)
2679  if (it->second > map_cpu_n_cells[new_owner])
2680  new_owner = it->first;
2681 
2682  for (unsigned int n=0; n<cell->n_children(); ++n)
2683  cell->child(n)->set_subdomain_id(new_owner);
2684  }
2685  }
2686  }
2687 
2688 
2689  template <int dim, int spacedim>
2690  void
2692  {
2693  unsigned int n_levels = triangulation.n_levels();
2694  for (int lvl = n_levels-1; lvl>=0; --lvl)
2695  {
2697  cell = triangulation.begin(lvl),
2698  endc = triangulation.end(lvl);
2699  for (; cell!=endc; ++cell)
2700  {
2701  if (!cell->has_children())
2702  cell->set_level_subdomain_id(cell->subdomain_id());
2703  else
2704  {
2705  Assert(cell->child(0)->level_subdomain_id()
2707  cell->set_level_subdomain_id(cell->child(0)->level_subdomain_id());
2708  }
2709  }
2710  }
2711  }
2712 
2713 
2714  template <int dim, int spacedim>
2715  void
2717  std::vector<types::subdomain_id> &subdomain)
2718  {
2719  Assert (subdomain.size() == triangulation.n_active_cells(),
2720  ExcDimensionMismatch (subdomain.size(),
2721  triangulation.n_active_cells()));
2723  cell = triangulation.begin_active(); cell!=triangulation.end(); ++cell)
2724  subdomain[cell->active_cell_index()] = cell->subdomain_id();
2725  }
2726 
2727 
2728 
2729  template <int dim, int spacedim>
2730  unsigned int
2732  const types::subdomain_id subdomain)
2733  {
2734  unsigned int count = 0;
2736  cell = triangulation.begin_active();
2737  cell!=triangulation.end(); ++cell)
2738  if (cell->subdomain_id() == subdomain)
2739  ++count;
2740 
2741  return count;
2742  }
2743 
2744 
2745 
2746  template <int dim, int spacedim>
2747  std::vector<bool>
2749  {
2750  // start with all vertices
2751  std::vector<bool> locally_owned_vertices = triangulation.get_used_vertices();
2752 
2753  // if the triangulation is distributed, eliminate those that
2754  // are owned by other processors -- either because the vertex is
2755  // on an artificial cell, or because it is on a ghost cell with
2756  // a smaller subdomain
2759  (&triangulation))
2760  for (typename ::internal::ActiveCellIterator<dim, spacedim, Triangulation<dim, spacedim> >::type
2761  cell = triangulation.begin_active();
2762  cell != triangulation.end(); ++cell)
2763  if (cell->is_artificial()
2764  ||
2765  (cell->is_ghost() &&
2766  (cell->subdomain_id() < tr->locally_owned_subdomain())))
2767  for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
2768  locally_owned_vertices[cell->vertex_index(v)] = false;
2769 
2770  return locally_owned_vertices;
2771  }
2772 
2773 
2774 
2775  namespace
2776  {
2777  template <int dim, int spacedim>
2778  double diameter(const typename Triangulation<dim, spacedim>::cell_iterator &cell,
2779  const Mapping<dim,spacedim> &mapping)
2780  {
2781  const auto vertices = mapping.get_vertices(cell);
2782  switch (dim)
2783  {
2784  case 1:
2785  return (vertices[1]-vertices[0]).norm();
2786  case 2:
2787  return std::max((vertices[3]-vertices[0]).norm(),
2788  (vertices[2]-vertices[1]).norm());
2789  case 3:
2790  return std::max( std::max((vertices[7]-vertices[0]).norm(),
2791  (vertices[6]-vertices[1]).norm()),
2792  std::max((vertices[2]-vertices[5]).norm(),
2793  (vertices[3]-vertices[4]).norm()) );
2794  default:
2795  Assert (false, ExcNotImplemented());
2796  return -1e10;
2797  }
2798  }
2799  }
2800 
2801 
2802  template <int dim, int spacedim>
2803  double
2805  const Mapping<dim,spacedim> &mapping)
2806  {
2807  double min_diameter = std::numeric_limits<double>::max();
2808  for (const auto &cell: triangulation.active_cell_iterators())
2809  if (!cell->is_artificial())
2810  min_diameter = std::min (min_diameter,
2811  diameter<dim,spacedim>(cell, mapping));
2812 
2813  double global_min_diameter = 0;
2814 
2815 #ifdef DEAL_II_WITH_MPI
2816  if (const parallel::Triangulation<dim,spacedim> *p_tria
2817  = dynamic_cast<const parallel::Triangulation<dim,spacedim>*>(&triangulation))
2818  global_min_diameter = Utilities::MPI::min (min_diameter, p_tria->get_communicator());
2819  else
2820 #endif
2821  global_min_diameter = min_diameter;
2822 
2823  return global_min_diameter;
2824  }
2825 
2826 
2827 
2828  template <int dim, int spacedim>
2829  double
2831  const Mapping<dim, spacedim> &mapping)
2832  {
2833  double max_diameter = 0.;
2834  for (const auto &cell: triangulation.active_cell_iterators())
2835  if (!cell->is_artificial())
2836  max_diameter = std::max (max_diameter,
2837  diameter(cell, mapping));
2838 
2839  double global_max_diameter = 0;
2840 
2841 #ifdef DEAL_II_WITH_MPI
2842  if (const parallel::Triangulation<dim,spacedim> *p_tria
2843  = dynamic_cast<const parallel::Triangulation<dim,spacedim>*>(&triangulation))
2844  global_max_diameter = Utilities::MPI::max (max_diameter, p_tria->get_communicator());
2845  else
2846 #endif
2847  global_max_diameter = max_diameter;
2848 
2849  return global_max_diameter;
2850  }
2851 
2852 
2853 
2854  namespace internal
2855  {
2856  namespace FixUpDistortedChildCells
2857  {
2858  // compute the mean square
2859  // deviation of the alternating
2860  // forms of the children of the
2861  // given object from that of
2862  // the object itself. for
2863  // objects with
2864  // structdim==spacedim, the
2865  // alternating form is the
2866  // determinant of the jacobian,
2867  // whereas for faces with
2868  // structdim==spacedim-1, the
2869  // alternating form is the
2870  // (signed and scaled) normal
2871  // vector
2872  //
2873  // this average square
2874  // deviation is computed for an
2875  // object where the center node
2876  // has been replaced by the
2877  // second argument to this
2878  // function
2879  template <typename Iterator, int spacedim>
2880  double
2881  objective_function (const Iterator &object,
2882  const Point<spacedim> &object_mid_point)
2883  {
2884  const unsigned int structdim = Iterator::AccessorType::structure_dimension;
2885  Assert (spacedim == Iterator::AccessorType::dimension,
2886  ExcInternalError());
2887 
2888  // everything below is wrong
2889  // if not for the following
2890  // condition
2891  Assert (object->refinement_case() == RefinementCase<structdim>::isotropic_refinement,
2892  ExcNotImplemented());
2893  // first calculate the
2894  // average alternating form
2895  // for the parent cell/face
2896  Point<spacedim> parent_vertices
2898  Tensor<spacedim-structdim,spacedim> parent_alternating_forms
2900 
2901  for (unsigned int i=0; i<GeometryInfo<structdim>::vertices_per_cell; ++i)
2902  parent_vertices[i] = object->vertex(i);
2903 
2905  parent_alternating_forms);
2906 
2907  const Tensor<spacedim-structdim,spacedim>
2908  average_parent_alternating_form
2909  = std::accumulate (parent_alternating_forms,
2910  parent_alternating_forms + GeometryInfo<structdim>::vertices_per_cell,
2912 
2913  // now do the same
2914  // computation for the
2915  // children where we use the
2916  // given location for the
2917  // object mid point instead of
2918  // the one the triangulation
2919  // currently reports
2920  Point<spacedim> child_vertices
2923  Tensor<spacedim-structdim,spacedim> child_alternating_forms
2926 
2927  for (unsigned int c=0; c<object->n_children(); ++c)
2928  for (unsigned int i=0; i<GeometryInfo<structdim>::vertices_per_cell; ++i)
2929  child_vertices[c][i] = object->child(c)->vertex(i);
2930 
2931  // replace mid-object
2932  // vertex. note that for
2933  // child i, the mid-object
2934  // vertex happens to have the
2935  // number
2936  // max_children_per_cell-i
2937  for (unsigned int c=0; c<object->n_children(); ++c)
2938  child_vertices[c][GeometryInfo<structdim>::max_children_per_cell-c-1]
2939  = object_mid_point;
2940 
2941  for (unsigned int c=0; c<object->n_children(); ++c)
2943  child_alternating_forms[c]);
2944 
2945  // on a uniformly refined
2946  // hypercube object, the child
2947  // alternating forms should
2948  // all be smaller by a factor
2949  // of 2^structdim than the
2950  // ones of the parent. as a
2951  // consequence, we'll use the
2952  // squared deviation from
2953  // this ideal value as an
2954  // objective function
2955  double objective = 0;
2956  for (unsigned int c=0; c<object->n_children(); ++c)
2957  for (unsigned int i=0; i<GeometryInfo<structdim>::vertices_per_cell; ++i)
2958  objective += (child_alternating_forms[c][i] -
2959  average_parent_alternating_form/std::pow(2.,1.*structdim))
2960  .norm_square();
2961 
2962  return objective;
2963  }
2964 
2965 
2971  template <typename Iterator>
2973  get_face_midpoint (const Iterator &object,
2974  const unsigned int f,
2975  std::integral_constant<int, 1>)
2976  {
2977  return object->vertex(f);
2978  }
2979 
2980 
2981 
2987  template <typename Iterator>
2989  get_face_midpoint (const Iterator &object,
2990  const unsigned int f,
2991  std::integral_constant<int, 2>)
2992  {
2993  return object->line(f)->center();
2994  }
2995 
2996 
2997 
3003  template <typename Iterator>
3005  get_face_midpoint (const Iterator &object,
3006  const unsigned int f,
3007  std::integral_constant<int, 3>)
3008  {
3009  return object->face(f)->center();
3010  }
3011 
3012 
3013 
3014 
3037  template <typename Iterator>
3038  double
3039  minimal_diameter (const Iterator &object)
3040  {
3041  const unsigned int
3042  structdim = Iterator::AccessorType::structure_dimension;
3043 
3044  double diameter = object->diameter();
3045  for (unsigned int f=0;
3046  f<GeometryInfo<structdim>::faces_per_cell;
3047  ++f)
3048  for (unsigned int e=f+1;
3049  e<GeometryInfo<structdim>::faces_per_cell;
3050  ++e)
3051  diameter = std::min (diameter,
3052  get_face_midpoint
3053  (object, f,
3054  std::integral_constant<int, structdim>())
3055  .distance (get_face_midpoint
3056  (object,
3057  e,
3058  std::integral_constant<int, structdim>())));
3059 
3060  return diameter;
3061  }
3062 
3063 
3064 
3068  template <typename Iterator>
3069  bool
3070  fix_up_object (const Iterator &object)
3071  {
3072  const unsigned int structdim = Iterator::AccessorType::structure_dimension;
3073  const unsigned int spacedim = Iterator::AccessorType::space_dimension;
3074 
3075  // right now we can only deal with cells that have been refined
3076  // isotropically because that is the only case where we have a cell
3077  // mid-point that can be moved around without having to consider
3078  // boundary information
3079  Assert (object->has_children(), ExcInternalError());
3080  Assert (object->refinement_case() == RefinementCase<structdim>::isotropic_refinement,
3081  ExcNotImplemented());
3082 
3083  // get the current location of the object mid-vertex:
3084  Point<spacedim> object_mid_point
3085  = object->child(0)->vertex (GeometryInfo<structdim>::max_children_per_cell-1);
3086 
3087  // now do a few steepest descent steps to reduce the objective
3088  // function. compute the diameter in the helper function above
3089  unsigned int iteration = 0;
3090  const double diameter = minimal_diameter (object);
3091 
3092  // current value of objective function and initial delta
3093  double current_value = objective_function (object, object_mid_point);
3094  double initial_delta = 0;
3095 
3096  do
3097  {
3098  // choose a step length that is initially 1/4 of the child
3099  // objects' diameter, and a sequence whose sum does not converge
3100  // (to avoid premature termination of the iteration)
3101  const double step_length = diameter / 4 / (iteration + 1);
3102 
3103  // compute the objective function's derivative using a two-sided
3104  // difference formula with eps=step_length/10
3105  Tensor<1,spacedim> gradient;
3106  for (unsigned int d=0; d<spacedim; ++d)
3107  {
3108  const double eps = step_length/10;
3109 
3111  h[d] = eps/2;
3112 
3113  gradient[d] = (objective_function (object,
3114  project_to_object(object, object_mid_point + h))
3115  -
3116  objective_function (object,
3117  project_to_object(object, object_mid_point - h)))
3118  /eps;
3119  }
3120 
3121  // there is nowhere to go
3122  if (gradient.norm() == 0)
3123  break;
3124 
3125  // We need to go in direction -gradient. the optimal value of the
3126  // objective function is zero, so assuming that the model is
3127  // quadratic we would have to go -2*val/||gradient|| in this
3128  // direction, make sure we go at most step_length into this
3129  // direction
3130  object_mid_point -= std::min(2 * current_value / (gradient*gradient),
3131  step_length / gradient.norm()) * gradient;
3132  object_mid_point = project_to_object(object, object_mid_point);
3133 
3134  // compute current value of the objective function
3135  const double previous_value = current_value;
3136  current_value = objective_function (object, object_mid_point);
3137 
3138  if (iteration == 0)
3139  initial_delta = (previous_value - current_value);
3140 
3141  // stop if we aren't moving much any more
3142  if ((iteration >= 1) &&
3143  ((previous_value - current_value < 0)
3144  ||
3145  (std::fabs (previous_value - current_value)
3146  <
3147  0.001 * initial_delta)))
3148  break;
3149 
3150  ++iteration;
3151  }
3152  while (iteration < 20);
3153 
3154  // verify that the new
3155  // location is indeed better
3156  // than the one before. check
3157  // this by comparing whether
3158  // the minimum value of the
3159  // products of parent and
3160  // child alternating forms is
3161  // positive. for cells this
3162  // means that the
3163  // determinants have the same
3164  // sign, for faces that the
3165  // face normals of parent and
3166  // children point in the same
3167  // general direction
3168  double old_min_product, new_min_product;
3169 
3170  Point<spacedim> parent_vertices
3172  for (unsigned int i=0; i<GeometryInfo<structdim>::vertices_per_cell; ++i)
3173  parent_vertices[i] = object->vertex(i);
3174 
3175  Tensor<spacedim-structdim,spacedim> parent_alternating_forms
3178  parent_alternating_forms);
3179 
3180  Point<spacedim> child_vertices
3183 
3184  for (unsigned int c=0; c<object->n_children(); ++c)
3185  for (unsigned int i=0; i<GeometryInfo<structdim>::vertices_per_cell; ++i)
3186  child_vertices[c][i] = object->child(c)->vertex(i);
3187 
3188  Tensor<spacedim-structdim,spacedim> child_alternating_forms
3191 
3192  for (unsigned int c=0; c<object->n_children(); ++c)
3194  child_alternating_forms[c]);
3195 
3196  old_min_product = child_alternating_forms[0][0] * parent_alternating_forms[0];
3197  for (unsigned int c=0; c<object->n_children(); ++c)
3198  for (unsigned int i=0; i<GeometryInfo<structdim>::vertices_per_cell; ++i)
3199  for (unsigned int j=0; j<GeometryInfo<structdim>::vertices_per_cell; ++j)
3200  old_min_product =
3201  std::min<double> (old_min_product,
3202  child_alternating_forms[c][i] *
3203  parent_alternating_forms[j]);
3204 
3205  // for the new minimum value,
3206  // replace mid-object
3207  // vertex. note that for child
3208  // i, the mid-object vertex
3209  // happens to have the number
3210  // max_children_per_cell-i
3211  for (unsigned int c=0; c<object->n_children(); ++c)
3212  child_vertices[c][GeometryInfo<structdim>::max_children_per_cell-c-1]
3213  = object_mid_point;
3214 
3215  for (unsigned int c=0; c<object->n_children(); ++c)
3217  child_alternating_forms[c]);
3218 
3219  new_min_product = child_alternating_forms[0][0] * parent_alternating_forms[0];
3220  for (unsigned int c=0; c<object->n_children(); ++c)
3221  for (unsigned int i=0; i<GeometryInfo<structdim>::vertices_per_cell; ++i)
3222  for (unsigned int j=0; j<GeometryInfo<structdim>::vertices_per_cell; ++j)
3223  new_min_product =
3224  std::min<double> (new_min_product,
3225  child_alternating_forms[c][i] *
3226  parent_alternating_forms[j]);
3227 
3228  // if new minimum value is
3229  // better than before, then set the
3230  // new mid point. otherwise
3231  // return this object as one of
3232  // those that can't apparently
3233  // be fixed
3234  if (new_min_product >= old_min_product)
3235  object->child(0)->vertex (GeometryInfo<structdim>::max_children_per_cell-1)
3236  = object_mid_point;
3237 
3238  // return whether after this
3239  // operation we have an object that
3240  // is well oriented
3241  return (std::max (new_min_product, old_min_product) > 0);
3242  }
3243 
3244 
3245 
3246  void fix_up_faces (const ::Triangulation<1,1>::cell_iterator &,
3247  std::integral_constant<int, 1>,
3248  std::integral_constant<int, 1>)
3249  {
3250  // nothing to do for the faces of cells in 1d
3251  }
3252 
3253 
3254 
3255  // possibly fix up the faces of a cell by moving around its mid-points
3256  template <int dim, int spacedim>
3257  void fix_up_faces (const typename ::Triangulation<dim,spacedim>::cell_iterator &cell,
3258  std::integral_constant<int, dim>,
3259  std::integral_constant<int, spacedim>)
3260  {
3261  // see if we first can fix up some of the faces of this object. We can
3262  // mess with faces if and only if the neighboring cell is not even
3263  // more refined than we are (since in that case the sub-faces have
3264  // themselves children that we can't move around any more). however,
3265  // the latter case shouldn't happen anyway: if the current face is
3266  // distorted but the neighbor is even more refined, then the face had
3267  // been deformed before already, and had been ignored at the time; we
3268  // should then also be able to ignore it this time as well
3269  for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
3270  {
3271  Assert (cell->face(f)->has_children(), ExcInternalError());
3272  Assert (cell->face(f)->refinement_case() ==
3273  RefinementCase<dim - 1>::isotropic_refinement,
3274  ExcInternalError());
3275 
3276  bool subface_is_more_refined = false;
3277  for (unsigned int g=0; g<GeometryInfo<dim>::max_children_per_face; ++g)
3278  if (cell->face(f)->child(g)->has_children())
3279  {
3280  subface_is_more_refined = true;
3281  break;
3282  }
3283 
3284  if (subface_is_more_refined == true)
3285  continue;
3286 
3287  // we finally know that we can do something about this face
3288  fix_up_object (cell->face(f));
3289  }
3290  }
3291  } /* namespace FixUpDistortedChildCells */
3292  } /* namespace internal */
3293 
3294 
3295  template <int dim, int spacedim>
3298  (const typename Triangulation<dim,spacedim>::DistortedCellList &distorted_cells,
3299  Triangulation<dim,spacedim> &/*triangulation*/)
3300  {
3301  typename Triangulation<dim,spacedim>::DistortedCellList unfixable_subset;
3302 
3303  // loop over all cells that we have to fix up
3304  for (typename std::list<typename Triangulation<dim,spacedim>::cell_iterator>::const_iterator
3305  cell_ptr = distorted_cells.distorted_cells.begin();
3306  cell_ptr != distorted_cells.distorted_cells.end(); ++cell_ptr)
3307  {
3309  cell = *cell_ptr;
3310 
3311  Assert(!cell->active(),
3312  ExcMessage("This function is only valid for a list of cells that "
3313  "have children (i.e., no cell in the list may be active)."));
3314 
3315  internal::FixUpDistortedChildCells
3316  ::fix_up_faces (cell,
3317  std::integral_constant<int, dim>(),
3318  std::integral_constant<int, spacedim>());
3319 
3320  // If possible, fix up the object.
3321  if (!internal::FixUpDistortedChildCells::fix_up_object (cell))
3322  unfixable_subset.distorted_cells.push_back (cell);
3323  }
3324 
3325  return unfixable_subset;
3326  }
3327 
3328 
3329 
3330  template <int dim, int spacedim>
3332  const bool reset_boundary_ids)
3333  {
3334  const auto src_boundary_ids = tria.get_boundary_ids();
3335  std::vector<types::manifold_id> dst_manifold_ids(src_boundary_ids.size());
3336  auto m_it = dst_manifold_ids.begin();
3337  for (auto b : src_boundary_ids)
3338  {
3339  *m_it = static_cast<types::manifold_id>(b);
3340  ++m_it;
3341  }
3342  const std::vector<types::boundary_id> reset_boundary_id =
3343  reset_boundary_ids ?
3344  std::vector<types::boundary_id>(src_boundary_ids.size(), 0) : src_boundary_ids;
3345  map_boundary_to_manifold_ids(src_boundary_ids, dst_manifold_ids, tria, reset_boundary_id);
3346  }
3347 
3348 
3349 
3350  template <int dim, int spacedim>
3351  void map_boundary_to_manifold_ids(const std::vector<types::boundary_id> &src_boundary_ids,
3352  const std::vector<types::manifold_id> &dst_manifold_ids,
3354  const std::vector<types::boundary_id> &reset_boundary_ids_)
3355  {
3356  AssertDimension(src_boundary_ids.size(), dst_manifold_ids.size());
3357  const auto reset_boundary_ids = reset_boundary_ids_.size() ?
3358  reset_boundary_ids_ : src_boundary_ids;
3359  AssertDimension(reset_boundary_ids.size(), src_boundary_ids.size());
3360 
3361  // in 3d, we not only have to copy boundary ids of faces, but also of edges
3362  // because we see them twice (once from each adjacent boundary face),
3363  // we cannot immediately reset their boundary ids. thus, copy first
3364  // and reset later
3365  if (dim >= 3)
3367  cell=tria.begin_active();
3368  cell != tria.end(); ++cell)
3369  for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
3370  if (cell->face(f)->at_boundary())
3371  for (unsigned int e=0; e<GeometryInfo<dim>::lines_per_face; ++e)
3372  {
3373  const auto bid = cell->face(f)->line(e)->boundary_id();
3374  const auto ind = std::find(src_boundary_ids.begin(), src_boundary_ids.end(), bid)-
3375  src_boundary_ids.begin();
3376  if ((unsigned int)ind < src_boundary_ids.size())
3377  cell->face(f)->line(e)->set_manifold_id(dst_manifold_ids[ind]);
3378  }
3379 
3380  // now do cells
3382  cell=tria.begin_active();
3383  cell != tria.end(); ++cell)
3384  for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
3385  if (cell->face(f)->at_boundary())
3386  {
3387  const auto bid = cell->face(f)->boundary_id();
3388  const auto ind = std::find(src_boundary_ids.begin(), src_boundary_ids.end(), bid)-
3389  src_boundary_ids.begin();
3390 
3391  if ((unsigned int)ind < src_boundary_ids.size())
3392  {
3393  // assign the manifold id
3394  cell->face(f)->set_manifold_id(dst_manifold_ids[ind]);
3395  // then reset boundary id
3396  cell->face(f)->set_boundary_id(reset_boundary_ids[ind]);
3397  }
3398 
3399  if (dim >= 3)
3400  for (unsigned int e=0; e<GeometryInfo<dim>::lines_per_face; ++e)
3401  {
3402  const auto bid = cell->face(f)->line(e)->boundary_id();
3403  const auto ind = std::find(src_boundary_ids.begin(), src_boundary_ids.end(), bid)-
3404  src_boundary_ids.begin();
3405  if ((unsigned int)ind < src_boundary_ids.size())
3406  cell->face(f)->line(e)->set_boundary_id(reset_boundary_ids[ind]);
3407  }
3408  }
3409  }
3410 
3411 
3412  template <int dim, int spacedim>
3414  const bool compute_face_ids)
3415  {
3417  cell=tria.begin_active(), endc=tria.end();
3418 
3419  for (; cell != endc; ++cell)
3420  {
3421  cell->set_manifold_id(cell->material_id());
3422  if (compute_face_ids == true)
3423  {
3424  for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
3425  {
3426  if (cell->at_boundary(f) == false)
3427  cell->face(f)->set_manifold_id
3428  (std::min(cell->material_id(),
3429  cell->neighbor(f)->material_id()));
3430  else
3431  cell->face(f)->set_manifold_id(cell->material_id());
3432  }
3433  }
3434  }
3435  }
3436 
3437  template <int dim, int spacedim>
3438  std::pair<unsigned int, double>
3440  {
3441  double max_ratio = 1;
3442  unsigned int index = 0;
3443 
3444  for (unsigned int i = 0; i < dim; ++i)
3445  for (unsigned int j = i+1; j < dim; ++j)
3446  {
3447  unsigned int ax = i % dim;
3448  unsigned int next_ax = j % dim;
3449 
3450  double ratio = cell->extent_in_direction(ax) / cell->extent_in_direction(next_ax);
3451 
3452  if ( ratio > max_ratio )
3453  {
3454  max_ratio = ratio;
3455  index = ax;
3456  }
3457  else if ( 1.0 /ratio > max_ratio )
3458  {
3459  max_ratio = 1.0 /ratio;
3460  index = next_ax;
3461  }
3462  }
3463  return std::make_pair(index, max_ratio);
3464  }
3465 
3466 
3467  template <int dim, int spacedim>
3468  void
3470  const bool isotropic,
3471  const unsigned int max_iterations)
3472  {
3473  unsigned int iter = 0;
3474  bool continue_refinement = true;
3475 
3477  cell = tria.begin_active(),
3478  endc = tria.end();
3479 
3480  while ( continue_refinement && (iter < max_iterations) )
3481  {
3482  if (max_iterations != numbers::invalid_unsigned_int) iter++;
3483  continue_refinement = false;
3484 
3485  for (cell=tria.begin_active(); cell!= endc; ++cell)
3486  for (unsigned int j = 0; j < GeometryInfo<dim>::faces_per_cell; j++)
3487  if (cell->at_boundary(j)==false && cell->neighbor(j)->has_children())
3488  {
3489  if (isotropic)
3490  {
3491  cell->set_refine_flag();
3492  continue_refinement = true;
3493  }
3494  else
3495  continue_refinement |= cell->flag_for_face_refinement(j);
3496  }
3497 
3499  }
3500  }
3501 
3502  template <int dim, int spacedim>
3503  void
3505  const double max_ratio,
3506  const unsigned int max_iterations)
3507  {
3508  unsigned int iter = 0;
3509  bool continue_refinement = true;
3510 
3512  cell = tria.begin_active(),
3513  endc = tria.end();
3514 
3515  while ( continue_refinement && (iter<max_iterations) )
3516  {
3517  iter++;
3518  continue_refinement = false;
3519  for (cell=tria.begin_active(); cell!= endc; ++cell)
3520  {
3521  std::pair<unsigned int, double> info = GridTools::get_longest_direction<dim,spacedim>(cell);
3522  if (info.second > max_ratio)
3523  {
3524  cell->set_refine_flag(RefinementCase<dim>::cut_axis(info.first));
3525  continue_refinement = true;
3526  }
3527  }
3529  }
3530  }
3531 
3532 
3533  template <int dim, int spacedim>
3535  const double limit_angle_fraction)
3536  {
3537  if (dim == 1)
3538  return; // Nothing to do
3539 
3540  // Check that we don't have hanging nodes
3541  AssertThrow(!tria.has_hanging_nodes(), ExcMessage("The input Triangulation cannot "
3542  "have hanging nodes."));
3543 
3544 
3545  bool has_cells_with_more_than_dim_faces_on_boundary = true;
3546  bool has_cells_with_dim_faces_on_boundary = false;
3547 
3548  unsigned int refinement_cycles = 0;
3549 
3550  while (has_cells_with_more_than_dim_faces_on_boundary)
3551  {
3552  has_cells_with_more_than_dim_faces_on_boundary = false;
3553 
3554  for (auto cell: tria.active_cell_iterators())
3555  {
3556  unsigned int boundary_face_counter = 0;
3557  for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
3558  if (cell->face(f)->at_boundary())
3559  boundary_face_counter++;
3560  if (boundary_face_counter > dim)
3561  {
3562  has_cells_with_more_than_dim_faces_on_boundary = true;
3563  break;
3564  }
3565  else if (boundary_face_counter == dim)
3566  has_cells_with_dim_faces_on_boundary = true;
3567  }
3568  if (has_cells_with_more_than_dim_faces_on_boundary)
3569  {
3570  tria.refine_global(1);
3571  refinement_cycles++;
3572  }
3573  }
3574 
3575  if (has_cells_with_dim_faces_on_boundary)
3576  {
3577  tria.refine_global(1);
3578  refinement_cycles++;
3579  }
3580  else
3581  {
3582  while (refinement_cycles>0)
3583  {
3584  for (auto cell: tria.active_cell_iterators())
3585  cell->set_coarsen_flag();
3587  refinement_cycles--;
3588  }
3589  return;
3590  }
3591 
3592  std::vector<bool> cells_to_remove(tria.n_active_cells(), false);
3593  std::vector<Point<spacedim> > vertices = tria.get_vertices();
3594 
3595  std::vector<bool> faces_to_remove(tria.n_raw_faces(),false);
3596 
3597  std::vector<CellData<dim> > cells_to_add;
3598  SubCellData subcelldata_to_add;
3599 
3600  // Trick compiler for dimension independent things
3601  const unsigned int
3602  v0 = 0, v1 = 1,
3603  v2 = (dim > 1 ? 2:0), v3 = (dim > 1 ? 3:0);
3604 
3605  for (auto cell : tria.active_cell_iterators())
3606  {
3607  double angle_fraction = 0;
3608  unsigned int vertex_at_corner = numbers::invalid_unsigned_int;
3609 
3610  if (dim == 2)
3611  {
3612  Tensor<1,spacedim> p0;
3613  p0[spacedim > 1 ? 1 : 0] = 1;
3614  Tensor<1,spacedim> p1;
3615  p1[0] = 1;
3616 
3617  if (cell->face(v0)->at_boundary() && cell->face(v3)->at_boundary())
3618  {
3619  p0 = cell->vertex(v0) - cell->vertex(v2);
3620  p1 = cell->vertex(v3) - cell->vertex(v2);
3621  vertex_at_corner = v2;
3622  }
3623  else if (cell->face(v3)->at_boundary() && cell->face(v1)->at_boundary())
3624  {
3625  p0 = cell->vertex(v2) - cell->vertex(v3);
3626  p1 = cell->vertex(v1) - cell->vertex(v3);
3627  vertex_at_corner = v3;
3628  }
3629  else if (cell->face(1)->at_boundary() && cell->face(2)->at_boundary())
3630  {
3631  p0 = cell->vertex(v0) - cell->vertex(v1);
3632  p1 = cell->vertex(v3) - cell->vertex(v1);
3633  vertex_at_corner = v1;
3634  }
3635  else if (cell->face(2)->at_boundary() && cell->face(0)->at_boundary())
3636  {
3637  p0 = cell->vertex(v2) - cell->vertex(v0);
3638  p1 = cell->vertex(v1) - cell->vertex(v0);
3639  vertex_at_corner = v0;
3640  }
3641  p0 /= p0.norm();
3642  p1 /= p1.norm();
3643  angle_fraction = std::acos(p0*p1)/numbers::PI;
3644 
3645  }
3646  else
3647  {
3648  Assert(false, ExcNotImplemented());
3649  }
3650 
3651  if (angle_fraction > limit_angle_fraction)
3652  {
3653 
3654  auto flags_removal = [&](unsigned int f1, unsigned int f2,
3655  unsigned int n1, unsigned int n2) -> void
3656  {
3657  cells_to_remove[cell->active_cell_index()] = true;
3658  cells_to_remove[cell->neighbor(n1)->active_cell_index()] = true;
3659  cells_to_remove[cell->neighbor(n2)->active_cell_index()] = true;
3660 
3661  faces_to_remove[cell->face(f1)->index()] = true;
3662  faces_to_remove[cell->face(f2)->index()] = true;
3663 
3664  faces_to_remove[cell->neighbor(n1)->face(f1)->index()] = true;
3665  faces_to_remove[cell->neighbor(n2)->face(f2)->index()] = true;
3666  };
3667 
3668  auto cell_creation = [&](
3669  const unsigned int vv0,
3670  const unsigned int vv1,
3671  const unsigned int f0,
3672  const unsigned int f1,
3673 
3674  const unsigned int n0,
3675  const unsigned int v0n0,
3676  const unsigned int v1n0,
3677 
3678  const unsigned int n1,
3679  const unsigned int v0n1,
3680  const unsigned int v1n1)
3681  {
3682  CellData<dim> c1, c2;
3683  CellData<1> l1, l2;
3684 
3685  c1.vertices[v0] = cell->vertex_index(vv0);
3686  c1.vertices[v1] = cell->vertex_index(vv1);
3687  c1.vertices[v2] = cell->neighbor(n0)->vertex_index(v0n0);
3688  c1.vertices[v3] = cell->neighbor(n0)->vertex_index(v1n0);
3689 
3690  c1.manifold_id = cell->manifold_id();
3691  c1.material_id = cell->material_id();
3692 
3693  c2.vertices[v0] = cell->vertex_index(vv0);
3694  c2.vertices[v1] = cell->neighbor(n1)->vertex_index(v0n1);
3695  c2.vertices[v2] = cell->vertex_index(vv1);
3696  c2.vertices[v3] = cell->neighbor(n1)->vertex_index(v1n1);
3697 
3698  c2.manifold_id = cell->manifold_id();
3699  c2.material_id = cell->material_id();
3700 
3701  l1.vertices[0] = cell->vertex_index(vv0);
3702  l1.vertices[1] = cell->neighbor(n0)->vertex_index(v0n0);
3703 
3704  l1.boundary_id = cell->line(f0)->boundary_id();
3705  l1.manifold_id = cell->line(f0)->manifold_id();
3706  subcelldata_to_add.boundary_lines.push_back(l1);
3707 
3708  l2.vertices[0] = cell->vertex_index(vv0);
3709  l2.vertices[1] = cell->neighbor(n1)->vertex_index(v0n1);
3710 
3711  l2.boundary_id = cell->line(f1)->boundary_id();
3712  l2.manifold_id = cell->line(f1)->manifold_id();
3713  subcelldata_to_add.boundary_lines.push_back(l2);
3714 
3715  cells_to_add.push_back(c1);
3716  cells_to_add.push_back(c2);
3717  };
3718 
3719  if (dim == 2)
3720  {
3721  switch (vertex_at_corner)
3722  {
3723  case 0:
3724  flags_removal(0,2,3,1);
3725  cell_creation(0,3, 0,2, 3,2,3, 1,1,3);
3726  break;
3727  case 1:
3728  flags_removal(1,2,3,0);
3729  cell_creation(1,2, 2,1, 0,0,2, 3,3,2);
3730  break;
3731  case 2:
3732  flags_removal(3,0,1,2);
3733  cell_creation(2,1, 3,0, 1,3,1, 2,0,1);
3734  break;
3735  case 3:
3736  flags_removal(3,1,0,2);
3737  cell_creation(3,0, 1,3, 2,1,0, 0,2,0);
3738  break;
3739  }
3740  }
3741  else
3742  {
3743  Assert(false, ExcNotImplemented());
3744  }
3745  }
3746  }
3747 
3748  // if no cells need to be added, then no regularization is necessary. Restore things
3749  // as they were before this function was called.
3750  if (cells_to_add.size() == 0)
3751  {
3752  while (refinement_cycles>0)
3753  {
3754  for (auto cell: tria.active_cell_iterators())
3755  cell->set_coarsen_flag();
3757  refinement_cycles--;
3758  }
3759  return;
3760  }
3761 
3762  // add the cells that were not marked as skipped
3763  for (auto cell : tria.active_cell_iterators())
3764  {
3765  if (cells_to_remove[cell->active_cell_index()] == false)
3766  {
3767  CellData<dim> c;
3768  for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
3769  c.vertices[v] = cell->vertex_index(v);
3770  c.manifold_id = cell->manifold_id();
3771  c.material_id = cell->material_id();
3772  cells_to_add.push_back(c);
3773  }
3774  }
3775 
3776  // Face counter for both dim == 2 and dim == 3
3778  face = tria.begin_active_face(),
3779  endf = tria.end_face();
3780  for (; face != endf; ++face)
3781  if ( (face->at_boundary() || face->manifold_id() != numbers::invalid_manifold_id)
3782  && faces_to_remove[face->index()] == false)
3783  {
3784  for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_face; ++l)
3785  {
3786  CellData<1> line;
3787  if (dim == 2)
3788  {
3789  for (unsigned int v=0; v<GeometryInfo<1>::vertices_per_cell; ++v)
3790  line.vertices[v] = face->vertex_index(v);
3791  line.boundary_id = face->boundary_id();
3792  line.manifold_id = face->manifold_id();
3793  }
3794  else
3795  {
3796  for (unsigned int v=0; v<GeometryInfo<1>::vertices_per_cell; ++v)
3797  line.vertices[v] = face->line(l)->vertex_index(v);
3798  line.boundary_id = face->line(l)->boundary_id();
3799  line.manifold_id = face->line(l)->manifold_id();
3800  }
3801  subcelldata_to_add.boundary_lines.push_back(line);
3802  }
3803  if (dim == 3)
3804  {
3805  CellData<2> quad;
3806  for (unsigned int v=0; v<GeometryInfo<2>::vertices_per_cell; ++v)
3807  quad.vertices[v] = face->vertex_index(v);
3808  quad.boundary_id = face->boundary_id();
3809  quad.manifold_id = face->manifold_id();
3810  subcelldata_to_add.boundary_quads.push_back(quad);
3811  }
3812  }
3813  GridTools::delete_unused_vertices(vertices, cells_to_add, subcelldata_to_add);
3814  GridReordering<dim,spacedim>::reorder_cells(cells_to_add, true);
3815 
3816  // Save manifolds
3817  auto manifold_ids = tria.get_manifold_ids();
3818  std::map<types::manifold_id, std::unique_ptr<Manifold<dim,spacedim> > > manifolds;
3819  // Set manifolds in new Triangulation
3820  for (auto manifold_id: manifold_ids)
3821  if (manifold_id != numbers::invalid_manifold_id)
3822  manifolds[manifold_id] = tria.get_manifold(manifold_id).clone();
3823 
3824  tria.clear();
3825 
3826  tria.create_triangulation(vertices, cells_to_add, subcelldata_to_add);
3827 
3828  // Restore manifolds
3829  for (auto manifold_id: manifold_ids)
3830  if (manifold_id != numbers::invalid_manifold_id)
3831  tria.set_manifold(manifold_id, *manifolds[manifold_id]);
3832  }
3833 
3834 
3835 
3836  template <int dim, int spacedim>
3837  std::tuple<
3838  std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator >,
3839  std::vector< std::vector< Point<dim> > >,
3840  std::vector< std::vector<unsigned int> > >
3842  const std::vector<Point<spacedim> > &points,
3843  const typename Triangulation<dim, spacedim>::active_cell_iterator &cell_hint)
3844  {
3845  // How many points are here?
3846  const unsigned int np = points.size();
3847 
3848  std::tuple<
3849  std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator >,
3850  std::vector< std::vector< Point<dim> > >,
3851  std::vector< std::vector<unsigned int> > >
3852  cell_qpoint_map;
3853 
3854  // Now the easy case.
3855  if (np==0) return cell_qpoint_map;
3856 
3857  // We begin by finding the cell/transform of the first point
3858  std::pair<typename Triangulation<dim, spacedim>::active_cell_iterator, Point<dim> >
3859  my_pair;
3860  if (cell_hint.state() == IteratorState::valid)
3862  (cache, points[0],cell_hint);
3863  else
3865  (cache, points[0]);
3866 
3867  std::get<0>(cell_qpoint_map).emplace_back(my_pair.first);
3868  std::get<1>(cell_qpoint_map).emplace_back(1, my_pair.second);
3869  std::get<2>(cell_qpoint_map).emplace_back(1, 0);
3870 
3871  // Now the second easy case.
3872  if (np==1) return cell_qpoint_map;
3873  // Computing the cell center and diameter
3874  Point<spacedim> cell_center = std::get<0>(cell_qpoint_map)[0]->center();
3875  double cell_diameter = std::get<0>(cell_qpoint_map)[0]->diameter()*
3876  (0.5 + std::numeric_limits<double>::epsilon() );
3877 
3878  // Cycle over all points left
3879  for (unsigned int p=1; p< np; ++p)
3880  {
3881  // Checking if the point is close to the cell center, in which
3882  // case calling find active cell with a cell hint
3883  if ( cell_center.distance(points[p]) < cell_diameter )
3885  (cache, points[p],std::get<0>(cell_qpoint_map).back());
3886  else
3888  (cache, points[p]);
3889 
3890  // Assuming the cell is probably the last cell added
3891  if ( my_pair.first == std::get<0>(cell_qpoint_map).back() )
3892  {
3893  // Found in the last cell: adding the data
3894  std::get<1>(cell_qpoint_map).back().emplace_back(my_pair.second);
3895  std::get<2>(cell_qpoint_map).back().emplace_back(p);
3896  }
3897  else
3898  {
3899  // Check if it is in another cell already found
3900  typename std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>::iterator
3901  cells_it = std::find(std::get<0>(cell_qpoint_map).begin(),std::get<0>(cell_qpoint_map).end()-1,my_pair.first);
3902 
3903  if ( cells_it == std::get<0>(cell_qpoint_map).end()-1 )
3904  {
3905  // Cell not found: adding a new cell
3906  std::get<0>(cell_qpoint_map).emplace_back(my_pair.first);
3907  std::get<1>(cell_qpoint_map).emplace_back(1, my_pair.second);
3908  std::get<2>(cell_qpoint_map).emplace_back(1, p);
3909  // Updating center and radius of the cell
3910  cell_center = std::get<0>(cell_qpoint_map).back()->center();
3911  cell_diameter = std::get<0>(cell_qpoint_map).back()->diameter()*
3912  (0.5 + std::numeric_limits<double>::epsilon() );
3913  }
3914  else
3915  {
3916  unsigned int current_cell = cells_it - std::get<0>(cell_qpoint_map).begin();
3917  // Cell found: just adding the point index and qpoint to the list
3918  std::get<1>(cell_qpoint_map)[current_cell].emplace_back(my_pair.second);
3919  std::get<2>(cell_qpoint_map)[current_cell].emplace_back(p);
3920  }
3921  }
3922  }
3923 
3924  // Debug Checking
3925  Assert(std::get<0>(cell_qpoint_map).size() == std::get<2>(cell_qpoint_map).size(),
3926  ExcDimensionMismatch(std::get<0>(cell_qpoint_map).size(), std::get<2>(cell_qpoint_map).size()));
3927 
3928  Assert(std::get<0>(cell_qpoint_map).size() == std::get<1>(cell_qpoint_map).size(),
3929  ExcDimensionMismatch(std::get<0>(cell_qpoint_map).size(), std::get<1>(cell_qpoint_map).size()));
3930 
3931 #ifdef DEBUG
3932  unsigned int c = std::get<0>(cell_qpoint_map).size();
3933  unsigned int qps = 0;
3934  // The number of points in all
3935  // the cells must be the same as
3936  // the number of points we
3937  // started off from.
3938  for (unsigned int n=0; n<c; ++n)
3939  {
3940  Assert(std::get<1>(cell_qpoint_map)[n].size() ==
3941  std::get<2>(cell_qpoint_map)[n].size(),
3942  ExcDimensionMismatch(std::get<1>(cell_qpoint_map)[n].size(),
3943  std::get<2>(cell_qpoint_map)[n].size()));
3944  qps += std::get<1>(cell_qpoint_map)[n].size();
3945  }
3946  Assert(qps == np,
3947  ExcDimensionMismatch(qps, np));
3948 #endif
3949 
3950  return cell_qpoint_map;
3951  }
3952 
3953 
3954 
3955  namespace internal
3956  {
3957  // Functions are needed for distributed compute point locations
3958  namespace distributed_cptloc
3959  {
3960  // Hash function for cells; needed for unordered maps/multimaps
3961  template < int dim, int spacedim>
3962  struct cell_hash
3963  {
3964  std::size_t operator()(const typename Triangulation<dim, spacedim>::active_cell_iterator &k) const
3965  {
3966  // Return active cell index, which is faster than CellId to compute
3967  return k->active_cell_index();
3968  }
3969  };
3970 
3971 
3972 
3973  // Compute point locations; internal version which returns an unordered map
3974  // The algorithm is the same as GridTools::compute_point_locations
3975  template <int dim, int spacedim>
3976  std::unordered_map< typename Triangulation<dim, spacedim>::active_cell_iterator,
3977  std::pair<std::vector<Point<dim> >,std::vector<unsigned int> >, cell_hash<dim,spacedim> >
3978  compute_point_locations_unmap(const GridTools::Cache<dim,spacedim> &cache,
3979  const std::vector<Point<spacedim> > &points)
3980  {
3981  // How many points are here?
3982  const unsigned int np = points.size();
3983  // Creating the output tuple
3984  std::unordered_map< typename Triangulation<dim, spacedim>::active_cell_iterator,
3985  std::pair<std::vector<Point<dim> >,std::vector<unsigned int> >, cell_hash<dim,spacedim> >
3986  cell_qpoint_map;
3987 
3988  // Now the easy case.
3989  if (np==0) return cell_qpoint_map;
3990  // We begin by finding the cell/transform of the first point
3992  (cache, points[0]);
3993 
3994  auto last_cell = cell_qpoint_map.emplace(
3995  std::make_pair(my_pair.first, std::make_pair(
3996  std::vector<Point<dim> > {my_pair.second},
3997  std::vector<unsigned int> {0})));
3998  // Now the second easy case.
3999  if (np==1) return cell_qpoint_map;
4000  // Computing the cell center and diameter
4001  Point<spacedim> cell_center = my_pair.first->center();
4002  double cell_diameter = my_pair.first->diameter()*
4003  (0.5 + std::numeric_limits<double>::epsilon() );
4004 
4005  // Cycle over all points left
4006  for (unsigned int p=1; p< np; ++p)
4007  {
4008  // Checking if the point is close to the cell center, in which
4009  // case calling find active cell with a cell hint
4010  if ( cell_center.distance(points[p]) < cell_diameter )
4012  (cache, points[p],last_cell.first->first);
4013  else
4015  (cache, points[p]);
4016 
4017  if ( last_cell.first->first == my_pair.first)
4018  {
4019  last_cell.first->second.first.emplace_back(my_pair.second);
4020  last_cell.first->second.second.emplace_back(p);
4021  }
4022  else
4023  {
4024  // Check if it is in another cell already found
4025  last_cell = cell_qpoint_map.emplace(std::make_pair(my_pair.first, std::make_pair(
4026  std::vector<Point<dim> > {my_pair.second},
4027  std::vector<unsigned int> {p})));
4028 
4029  if ( last_cell.second == false )
4030  {
4031  // Cell already present: adding the new point
4032  last_cell.first->second.first.emplace_back(my_pair.second);
4033  last_cell.first->second.second.emplace_back(p);
4034  }
4035  else
4036  {
4037  // New cell was added, updating center and diameter
4038  cell_center = my_pair.first->center();
4039  cell_diameter = my_pair.first->diameter()*
4040  (0.5 + std::numeric_limits<double>::epsilon() );
4041  }
4042  }
4043  }
4044 
4045 #ifdef DEBUG
4046  unsigned int qps = 0;
4047  // The number of points in all
4048  // the cells must be the same as
4049  // the number of points we
4050  // started off from.
4051  for (const auto &m: cell_qpoint_map)
4052  {
4053  Assert(m.second.second.size() ==
4054  m.second.first.size(),
4055  ExcDimensionMismatch(m.second.second.size(),
4056  m.second.first.size()));
4057  qps += m.second.second.size();
4058  }
4059  Assert(qps == np,
4060  ExcDimensionMismatch(qps, np));
4061 #endif
4062  return cell_qpoint_map;
4063  }
4064 
4065 
4066 
4067  // Merging the output means to add data to a previous output, here contained
4068  // in output unmap:
4069  // if the cell is already present: add information about new points
4070  // if the cell is not present: add the cell with all information
4071  //
4072  // Notice we call "information" the data associated with a point of the sort:
4073  // cell containing it, transformed point on reference cell, index,
4074  // rank of the owner etc.
4075  template <int dim, int spacedim>
4076  void
4077  merge_cptloc_outputs(
4078  std::unordered_map< typename Triangulation<dim, spacedim>::active_cell_iterator,
4079  std::tuple<
4080  std::vector< Point<dim> >,
4081  std::vector< unsigned int >,
4082  std::vector< Point<spacedim> >,
4083  std::vector< unsigned int >
4084  >,
4085  cell_hash<dim,spacedim>> &output_unmap,
4086  const std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator > &in_cells,
4087  const std::vector< std::vector< Point<dim> > > &in_qpoints,
4088  const std::vector< std::vector<unsigned int> > &in_maps,
4089  const std::vector< std::vector< Point<spacedim> > > &in_points,
4090  const unsigned int in_rank
4091  )
4092  {
4093  // Adding cells, one by one
4094  for (unsigned int c=0; c< in_cells.size(); ++c)
4095  {
4096  // Attempt to add a new cell with its relative data
4097  auto current_c = output_unmap.emplace(
4098  std::make_pair(in_cells[c],
4099  std::make_tuple(in_qpoints[c],
4100  in_maps[c],
4101  in_points[c],
4102  std::vector<unsigned int>
4103  (in_points[c].size(),in_rank))));
4104  // If the flag is false no new cell was added:
4105  if ( current_c.second == false )
4106  {
4107  // Cell in output map at current_c.first:
4108  // Adding the information to it
4109  auto &cell_qpts = std::get<0>(current_c.first->second);
4110  auto &cell_maps = std::get<1>(current_c.first->second);
4111  auto &cell_pts = std::get<2>(current_c.first->second);
4112  auto &cell_ranks = std::get<3>(current_c.first->second);
4113  cell_qpts.insert(cell_qpts.end(),
4114  in_qpoints[c].begin(),
4115  in_qpoints[c].end());
4116  cell_maps.insert(cell_maps.end(),
4117  in_maps[c].begin(),
4118  in_maps[c].end());
4119  cell_pts.insert(cell_pts.end(),
4120  in_points[c].begin(),
4121  in_points[c].end());
4122  std::vector< unsigned int > ranks_tmp(in_points[c].size(),in_rank);
4123  cell_ranks.insert(cell_ranks.end(),
4124  ranks_tmp.begin(),
4125  ranks_tmp.end());
4126  }
4127  }
4128  }
4129 
4130 
4131 
4132  // This function initializes the output by calling compute point locations
4133  // on local points; vector containing points which are probably local.
4134  // Its output is then sorted in the following manner:
4135  // - output unmap: points, with relative information, inside locally onwed cells,
4136  // - ghost loc pts: points, with relative information, inside ghost cells,
4137  // - classified pts: vector of all points returned in output map and ghost loc pts
4138  // (these are stored as indices)
4139  template <int dim, int spacedim>
4140  void
4141  compute_and_classify_points(
4142  const GridTools::Cache<dim,spacedim> &cache,
4143  const std::vector<Point<spacedim> > &local_points,
4144  const std::vector< unsigned int > &local_points_idx,
4145  std::unordered_map<
4147  std::tuple<
4148  std::vector< Point<dim> >,
4149  std::vector< unsigned int >,
4150  std::vector< Point<spacedim> >,
4151  std::vector< unsigned int >
4152  >,
4153  cell_hash<dim,spacedim>> &output_unmap,
4154  std::map< unsigned int,
4155  std::tuple<
4156  std::vector< CellId >,
4157  std::vector< std::vector< Point<dim> > >,
4158  std::vector< std::vector< unsigned int > >,
4159  std::vector< std::vector< Point<spacedim> > >
4160  > > &ghost_loc_pts,
4161  std::vector< unsigned int > &classified_pts
4162  )
4163  {
4164  auto cpt_loc_pts = compute_point_locations_unmap(cache,local_points);
4165 
4166  // Alayzing the output discarding artificial cell
4167  // and storing in the proper container locally owned and ghost cells
4168  for (auto const &cell_tuples : cpt_loc_pts)
4169  {
4170  auto &cell_loc = cell_tuples.first;
4171  auto &q_loc = std::get<0>(cell_tuples.second);
4172  auto &indices_loc = std::get<1>(cell_tuples.second);
4173  if (cell_loc->is_locally_owned() )
4174  {
4175  // Point inside locally owned cell: storing all its data
4176  std::vector < Point<spacedim> > cell_points(indices_loc.size());
4177  std::vector < unsigned int > cell_points_idx(indices_loc.size());
4178  for (unsigned int i=0; i< indices_loc.size(); ++i)
4179  {
4180  // Adding the point to the cell points
4181  cell_points[i] = local_points[indices_loc[i]];
4182 
4183  // Storing the index: notice indices loc refer to the local points
4184  // vector, but we need to return the index with respect of
4185  // the points owned by the current process
4186  cell_points_idx[i] = local_points_idx[indices_loc[i]];
4187  classified_pts.emplace_back(local_points_idx[indices_loc[i]]);
4188  }
4189  output_unmap.emplace(std::make_pair(cell_loc,
4190  std::make_tuple(q_loc,
4191  cell_points_idx,
4192  cell_points,
4193  std::vector<unsigned int>
4194  (indices_loc.size(),cell_loc->subdomain_id()))));
4195  }
4196  else if ( cell_loc->is_ghost() )
4197  {
4198  // Point inside ghost cell: storing all its information and preparing
4199  // it to be sent
4200  std::vector < Point<spacedim> > cell_points(indices_loc.size());
4201  std::vector < unsigned int > cell_points_idx(indices_loc.size());
4202  for (unsigned int i=0; i< indices_loc.size(); ++i)
4203  {
4204  cell_points[i] = local_points[indices_loc[i]];
4205  cell_points_idx[i] = local_points_idx[indices_loc[i]];
4206  classified_pts.emplace_back(local_points_idx[indices_loc[i]]);
4207  }
4208  // Each key of the following map represent a process,
4209  // each mapped value is a tuple containing the information to be sent:
4210  // preparing the output for the owner, which has rank subdomain id
4211  auto &map_tuple_owner = ghost_loc_pts[cell_loc->subdomain_id()];
4212  // To identify the cell on the other process we use the cell id
4213  std::get<0>(map_tuple_owner).emplace_back(cell_loc->id());
4214  std::get<1>(map_tuple_owner).emplace_back(q_loc);
4215  std::get<2>(map_tuple_owner).emplace_back(cell_points_idx);
4216  std::get<3>(map_tuple_owner).emplace_back(cell_points);
4217  }
4218  // else: the cell is artificial, nothing to do
4219  }
4220  }
4221 
4222 
4223 
4224  // Given the map obtained from a communication, where the key is rank and the mapped
4225  // value is a pair of (points,indices), calls compute point locations; its output
4226  // is then merged with output tuple
4227  // if check_owned is set to true only points
4228  // lying inside locally onwed cells shall be merged, otherwise all points shall be merged.
4229  template <int dim, int spacedim>
4230  void
4231  compute_and_merge_from_map(
4232  const GridTools::Cache<dim,spacedim> &cache,
4233  const std::map< unsigned int,
4234  std::pair<
4235  std::vector < Point<spacedim> >,
4236  std::vector < unsigned int > >
4237  > &map_pts,
4238  std::unordered_map< typename Triangulation<dim, spacedim>::active_cell_iterator,
4239  std::tuple<
4240  std::vector< Point<dim> >,
4241  std::vector< unsigned int >,
4242  std::vector< Point<spacedim> >,
4243  std::vector< unsigned int >
4244  >,
4245  cell_hash<dim,spacedim>> &output_unmap,
4246  const bool &check_owned
4247  )
4248  {
4249  bool no_check = !check_owned;
4250 
4251  // rank and points is a pair: first rank, then a pair of vectors (points, indices)
4252  for (auto const &rank_and_points : map_pts)
4253  {
4254  // Rewriting the contents of the map in human readable format
4255  const auto &received_process = rank_and_points.first;
4256  const auto &received_points = rank_and_points.second.first;
4257  const auto &received_map = rank_and_points.second.second;
4258 
4259  // Initializing the vectors needed to store the result of compute point location
4260  std::vector< typename Triangulation<dim, spacedim>::active_cell_iterator > in_cell;
4261  std::vector< std::vector< Point<dim> > > in_qpoints;
4262  std::vector< std::vector< unsigned int > > in_maps;
4263  std::vector< std::vector< Point<spacedim> > > in_points;
4264 
4265  auto cpt_loc_pts = compute_point_locations_unmap(cache,rank_and_points.second.first);
4266  for (const auto &map_c_pt_idx: cpt_loc_pts)
4267  {
4268  // Human-readable variables:
4269  const auto &proc_cell = map_c_pt_idx.first;
4270  const auto &proc_qpoints = map_c_pt_idx.second.first;
4271  const auto &proc_maps = map_c_pt_idx.second.second;
4272 
4273  // This is stored either if we're not checking if the cell is owned or
4274  // if the cell is locally owned
4275  if ( no_check || proc_cell->is_locally_owned() )
4276  {
4277  in_cell.emplace_back(proc_cell);
4278  in_qpoints.emplace_back(proc_qpoints);
4279  // The other two vectors need to be built
4280  unsigned int loc_size = proc_qpoints.size();
4281  std::vector< unsigned int > cell_maps(loc_size);
4282  std::vector< Point<spacedim> > cell_points(loc_size);
4283  for (unsigned int pt=0; pt<loc_size; ++pt)
4284  {
4285  cell_maps[pt] = received_map[proc_maps[pt]];
4286  cell_points[pt] = received_points[proc_maps[pt]];
4287  }
4288  in_maps.emplace_back(cell_maps);
4289  in_points.emplace_back(cell_points);
4290  }
4291  }
4292 
4293  // Merge everything from the current process
4294  internal::distributed_cptloc::merge_cptloc_outputs(output_unmap,
4295  in_cell,
4296  in_qpoints,
4297  in_maps,
4298  in_points,
4299  received_process);
4300  }
4301  }
4302  } // namespace distributed_cptloc
4303  } // namespace internal
4304 
4305 
4306 
4307  template <int dim, int spacedim>
4308  std::tuple<
4309  std::vector< typename Triangulation<dim, spacedim>::active_cell_iterator >,
4310  std::vector< std::vector< Point<dim> > >,
4311  std::vector< std::vector< unsigned int > >,
4312  std::vector< std::vector< Point<spacedim> > >,
4313  std::vector< std::vector< unsigned int > >
4314  >
4317  const std::vector<Point<spacedim> > &local_points,
4318  const std::vector< std::vector< BoundingBox<spacedim> > > &global_bboxes)
4319  {
4320 #ifndef DEAL_II_WITH_MPI
4321  (void)cache;
4322  (void)local_points;
4323  (void)global_bboxes;
4324  Assert(false, ExcMessage("GridTools::distributed_compute_point_locations() requires MPI."));
4325  std::tuple<
4326  std::vector< typename Triangulation<dim, spacedim>::active_cell_iterator >,
4327  std::vector< std::vector< Point<dim> > >,
4328  std::vector< std::vector< unsigned int > >,
4329  std::vector< std::vector< Point<spacedim> > >,
4330  std::vector< std::vector< unsigned int > >
4331  > tup;
4332  return tup;
4333 #else
4334  // Recovering the mpi communicator used to create the triangulation
4335  const auto &tria_mpi =
4336  dynamic_cast< const parallel::Triangulation< dim, spacedim >*>(&cache.get_triangulation());
4337  // If the dynamic cast failed we can't recover the mpi communicator: throwing an assertion error
4338  Assert(tria_mpi, ExcMessage("GridTools::distributed_compute_point_locations() requires a parallel triangulation."));
4339  auto mpi_communicator = tria_mpi->get_communicator();
4340  // Preparing the output tuple
4341  std::tuple<
4342  std::vector< typename Triangulation<dim, spacedim>::active_cell_iterator >,
4343  std::vector< std::vector< Point<dim> > >,
4344  std::vector< std::vector< unsigned int > >,
4345  std::vector< std::vector< Point<spacedim> > >,
4346  std::vector< std::vector< unsigned int > >
4347  > output_tuple;
4348 
4349  // Preparing the temporary unordered map
4350  std::unordered_map< typename Triangulation<dim, spacedim>::active_cell_iterator,
4351  std::tuple<
4352  std::vector< Point<dim> >,
4353  std::vector< unsigned int >,
4354  std::vector< Point<spacedim> >,
4355  std::vector< unsigned int >
4356  >,
4357  internal::distributed_cptloc::cell_hash<dim,spacedim> >
4358  temporary_unmap;
4359 
4360  // Step 1 (part 1): Using the bounding boxes to guess the owner of each points
4361  // in local_points
4362  unsigned int my_rank = Utilities::MPI::this_mpi_process(mpi_communicator);
4363 
4364  // Using global bounding boxes to guess/find owner/s of each point
4365  std::tuple< std::vector< std::vector< unsigned int > >, std::map< unsigned int, unsigned int >,
4366  std::map< unsigned int, std::vector< unsigned int > > > guessed_points;
4367  guessed_points =
4368  GridTools::guess_point_owner(global_bboxes, local_points);
4369 
4370  // Preparing to call compute point locations on points which are/might be
4371  // local
4372  const auto &guess_loc_idx = std::get<0>(guessed_points)[my_rank];
4373  const unsigned int n_local_guess = guess_loc_idx.size();
4374  // Vector containing points which are probably local
4375  std::vector< Point<spacedim> > guess_local_pts(n_local_guess);
4376  for (unsigned int i=0; i<n_local_guess; ++i)
4377  guess_local_pts[i] = local_points[ guess_loc_idx[i] ];
4378 
4379  // Preparing the map with data on points lying on locally owned cells
4380  std::map< unsigned int,
4381  std::tuple<
4382  std::vector< CellId >,
4383  std::vector< std::vector< Point<dim> > >,
4384  std::vector< std::vector< unsigned int > >,
4385  std::vector< std::vector< Point<spacedim> > > > > ghost_loc_pts;
4386  // Vector containing indices of points lying either on locally owned
4387  // cells or ghost cells, to avoid computing them more than once
4388  std::vector< unsigned int > classified_pts;
4389 
4390  // Thread used to call compute point locations on guess local pts
4392  cpt_loc_tsk
4393  = Threads::new_task (
4394  &internal::distributed_cptloc::compute_and_classify_points<dim,spacedim>,
4395  cache,
4396  guess_local_pts,
4397  guess_loc_idx,
4398  temporary_unmap,
4399  ghost_loc_pts,
4400  classified_pts);
4401 
4402  // Step 1 (part 2): communicate point which are owned by a certain process
4403  // Preparing the map with points whose owner is known with certainty:
4404  const auto &other_owned_idx = std::get<1>(guessed_points);
4405  std::map<
4406  unsigned int,
4407  std::pair< std::vector<Point<spacedim>> , std::vector<unsigned int > > >
4408  other_owned_pts;
4409 
4410  for (const auto &indices: other_owned_idx)
4411  if (indices.second != my_rank)
4412  {
4413  // Finding/adding in the map the current process
4414  auto &current_pts = other_owned_pts[indices.second];
4415  // Indices.first is the index of the considered point in local points
4416  current_pts.first.emplace_back(local_points[indices.first]);
4417  current_pts.second.emplace_back(indices.first);
4418  }
4419 
4420  // Communicating the points whose owner is sure
4421  auto owned_rank_pts = Utilities::MPI::some_to_some(mpi_communicator,other_owned_pts);
4422  // Waiting for part 1 to finish to avoid concurrency problems
4423  cpt_loc_tsk.join();
4424 
4425  // Step 2 (part 1): compute received points which are owned
4427  owned_pts_tsk
4428  = Threads::new_task (&internal::distributed_cptloc::compute_and_merge_from_map<dim,spacedim>,
4429  cache,
4430  owned_rank_pts,
4431  temporary_unmap,
4432  false);
4433 
4434  // Step 2 (part 2): communicate info on points lying on ghost cells
4435  auto cpt_ghost = Utilities::MPI::some_to_some(mpi_communicator,ghost_loc_pts);
4436 
4437  // Step 3: construct vectors containing uncertain points i.e. those whose owner
4438  // is known among few guesses
4439  // The maps goes from rank of the probable owner to a pair of vectors: the first
4440  // containing the points, the second containing the ranks in the current process
4441  std::map<
4442  unsigned int,
4443  std::pair< std::vector < Point<spacedim> >,
4444  std::vector< unsigned int > > >
4445  other_check_pts;
4446 
4447  // This map goes from the point index to a vector of
4448  // ranks probable owners
4449  const std::map< unsigned int, std::vector< unsigned int > >
4450  &other_check_idx = std::get<2>(guessed_points);
4451 
4452  // Points in classified pts need not to be communicated;
4453  // sorting the array classified pts in order to use
4454  // binary search when checking if the points needs to be
4455  // communicated
4456  // Notice classified pts is a vector of integer indexes
4457  std::sort (classified_pts.begin(), classified_pts.end());
4458 
4459  for (const auto &pt_to_guesses: other_check_idx)
4460  {
4461  const auto &point_idx = pt_to_guesses.first;
4462  const auto &probable_owners_rks = pt_to_guesses.second;
4463  if ( !std::binary_search(
4464  classified_pts.begin(), classified_pts.end(), point_idx) )
4465  // The point wasn't found in ghost or locally owned cells: adding it to the map
4466  for (unsigned int i=0; i<probable_owners_rks.size(); ++i)
4467  if (probable_owners_rks[i] != my_rank)
4468  {
4469  // add to the data for process probable_owners_rks[i]
4470  auto &current_pts = other_check_pts[probable_owners_rks[i]];
4471  // The point local_points[point_idx]
4472  current_pts.first.emplace_back(local_points[point_idx]);
4473  // and its index in the current process
4474  current_pts.second.emplace_back(point_idx);
4475  }
4476  }
4477 
4478  // Step 4: send around uncertain points
4479  auto check_pts = Utilities::MPI::some_to_some(mpi_communicator,other_check_pts);
4480  // Before proceeding, merging threads to avoid concurrency problems
4481  owned_pts_tsk.join();
4482 
4483  // Step 5: add the received ghost cell data to output
4484  for ( const auto &rank_vals: cpt_ghost)
4485  {
4486  // Transforming CellsIds into Tria iterators
4487  const auto &cell_ids = std::get<0>(rank_vals.second);
4488  unsigned int n_cells = cell_ids.size();
4489  std::vector< typename Triangulation<dim, spacedim>::active_cell_iterator >
4490  cell_iter(n_cells);
4491  for (unsigned int c=0; c<n_cells; ++c)
4492  cell_iter[c] = cell_ids[c].to_cell(cache.get_triangulation());
4493 
4494  internal::distributed_cptloc::merge_cptloc_outputs(temporary_unmap,
4495  cell_iter,
4496  std::get<1>(rank_vals.second),
4497  std::get<2>(rank_vals.second),
4498  std::get<3>(rank_vals.second),
4499  rank_vals.first);
4500  }
4501 
4502  // Step 6: use compute point locations on the uncertain points and
4503  // merge output
4504  internal::distributed_cptloc::compute_and_merge_from_map(
4505  cache,
4506  check_pts,
4507  temporary_unmap,
4508  true);
4509 
4510  // Copying data from the unordered map to the tuple
4511  // and returning output
4512  unsigned int size_output = temporary_unmap.size();
4513  auto &out_cells = std::get<0>(output_tuple);
4514  auto &out_qpoints = std::get<1>(output_tuple);
4515  auto &out_maps = std::get<2>(output_tuple);
4516  auto &out_points = std::get<3>(output_tuple);
4517  auto &out_ranks = std::get<4>(output_tuple);
4518 
4519  out_cells.resize(size_output);
4520  out_qpoints.resize(size_output);
4521  out_maps.resize(size_output);
4522  out_points.resize(size_output);
4523  out_ranks.resize(size_output);
4524 
4525  unsigned int c = 0;
4526  for (const auto &rank_and_tuple: temporary_unmap)
4527  {
4528  out_cells[c] = rank_and_tuple.first;
4529  out_qpoints[c] = std::get<0>(rank_and_tuple.second);
4530  out_maps[c] = std::get<1>(rank_and_tuple.second);
4531  out_points[c] = std::get<2>(rank_and_tuple.second);
4532  out_ranks[c] = std::get<3>(rank_and_tuple.second);
4533  ++c;
4534  }
4535 
4536  return output_tuple;
4537 #endif
4538  }
4539 
4540 
4541  template<int dim, int spacedim>
4542  std::map<unsigned int, Point<spacedim> >
4544  const Mapping<dim,spacedim> &mapping)
4545  {
4546  std::map<unsigned int, Point<spacedim> > result;
4547  for (const auto &cell : container.active_cell_iterators())
4548  {
4549  const auto vs = mapping.get_vertices(cell);
4550  for (unsigned int i=0; i<vs.size(); ++i)
4551  result[cell->vertex_index(i)]=vs[i];
4552  }
4553  Assert(result.size() == container.n_used_vertices(),
4554  ExcInternalError());
4555  return result;
4556  }
4557 
4558 
4559  template<int spacedim>
4560  unsigned int
4561  find_closest_vertex(const std::map<unsigned int,Point<spacedim> > &vertices,
4562  const Point<spacedim> &p)
4563  {
4564  auto id_and_v = std::min_element(vertices.begin(), vertices.end(),
4565  [&](const std::pair<const unsigned int, Point<spacedim>> &p1,
4566  const std::pair<const unsigned int, Point<spacedim>> &p2) -> bool
4567  {
4568  return p1.second.distance(p) < p2.second.distance(p);
4569  }
4570  );
4571  return id_and_v->first;
4572  }
4573 
4574 
4575  template<int dim, int spacedim>
4576  std::pair<typename Triangulation<dim,spacedim>::active_cell_iterator, Point<dim> >
4578  const Point<spacedim> &p,
4579  const typename Triangulation<dim,spacedim>::active_cell_iterator &cell_hint,
4580  const std::vector<bool> &marked_vertices)
4581  {
4582  const auto &mesh = cache.get_triangulation();
4583  const auto &mapping = cache.get_mapping();
4584  const auto &vertex_to_cells = cache.get_vertex_to_cell_map();
4585  const auto &vertex_to_cell_centers = cache.get_vertex_to_cell_centers_directions();
4586 
4587  return find_active_cell_around_point(mapping, mesh, p,
4588  vertex_to_cells,
4589  vertex_to_cell_centers,
4590  cell_hint,
4591  marked_vertices);
4592  }
4593 
4594  template<int spacedim>
4595  std::vector< std::vector< BoundingBox<spacedim> > >
4596  exchange_local_bounding_boxes(const std::vector< BoundingBox<spacedim> > &local_bboxes,
4597  MPI_Comm mpi_communicator)
4598  {
4599 #ifndef DEAL_II_WITH_MPI
4600  (void)local_bboxes;
4601  (void)mpi_communicator;
4602  Assert(false, ExcMessage("GridTools::exchange_local_bounding_boxes() requires MPI."));
4603  return {};
4604 #else
4605  // Step 1: preparing data to be sent
4606  unsigned int n_bboxes = local_bboxes.size();
4607  // Dimension of the array to be exchanged (number of double)
4608  int n_local_data = 2*spacedim*n_bboxes;
4609  // data array stores each entry of each point describing the bounding boxes
4610  std::vector<double> loc_data_array(n_local_data);
4611  for (unsigned int i=0; i<n_bboxes; ++i)
4612  for (unsigned int d=0; d < spacedim; ++d)
4613  {
4614  // Extracting the coordinates of each boundary point
4615  loc_data_array[2*i*spacedim + d] = local_bboxes[i].get_boundary_points().first[d];
4616  loc_data_array[2*i*spacedim + spacedim + d] = local_bboxes[i].get_boundary_points().second[d];
4617  }
4618 
4619  // Step 2: exchanging the size of local data
4620  unsigned int n_procs = Utilities::MPI::n_mpi_processes(mpi_communicator);
4621 
4622  // Vector to store the size of loc_data_array for every process
4623  std::vector<int> size_all_data(n_procs);
4624 
4625  // Exchanging the number of bboxes
4626  int ierr = MPI_Allgather(&n_local_data, 1, MPI_INT,
4627  &(size_all_data[0]), 1, MPI_INT,
4628  mpi_communicator);
4629  AssertThrowMPI(ierr);
4630 
4631  // Now computing the the displacement, relative to recvbuf,
4632  // at which to store the incoming data
4633  std::vector<int> rdispls(n_procs);
4634  rdispls[0] = 0;
4635  for (unsigned int i=1; i < n_procs; ++i)
4636  rdispls[i] = rdispls[i-1] + size_all_data[i-1];
4637 
4638  // Step 3: exchange the data and bounding boxes:
4639  // Allocating a vector to contain all the received data
4640  std::vector<double> data_array(rdispls.back() + size_all_data.back());
4641 
4642  ierr = MPI_Allgatherv(&(loc_data_array[0]), n_local_data, MPI_DOUBLE,
4643  &(data_array[0]), &(size_all_data[0]),
4644  &(rdispls[0]), MPI_DOUBLE, mpi_communicator);
4645  AssertThrowMPI(ierr);
4646 
4647  // Step 4: create the array of bboxes for output
4648  std::vector< std::vector< BoundingBox<spacedim> > > global_bboxes(n_procs);
4649  unsigned int begin_idx = 0;
4650  for (unsigned int i=0; i < n_procs; ++i)
4651  {
4652  // Number of local bounding boxes
4653  unsigned int n_bbox_i = size_all_data[i]/(spacedim*2);
4654  global_bboxes[i].resize(n_bbox_i);
4655  for (unsigned int bbox=0; bbox<n_bbox_i; ++bbox)
4656  {
4657  Point<spacedim> p1,p2; // boundary points for bbox
4658  for (unsigned int d=0; d<spacedim; ++d)
4659  {
4660  p1[d] = data_array[ begin_idx + 2*bbox*spacedim + d];
4661  p2[d] = data_array[ begin_idx + 2*bbox*spacedim + spacedim + d];
4662  }
4663  BoundingBox<spacedim> loc_bbox(std::make_pair(p1,p2));
4664  global_bboxes[i][bbox] = loc_bbox;
4665  }
4666  // Shifting the first index to the start of the next vector
4667  begin_idx += size_all_data[i];
4668  }
4669  return global_bboxes;
4670 #endif // DEAL_II_WITH_MPI
4671  }
4672 
4673 
4674 } /* namespace GridTools */
4675 
4676 
4677 // explicit instantiations
4678 #include "grid_tools.inst"
4679 
4680 DEAL_II_NAMESPACE_CLOSE
void remove_hanging_nodes(Triangulation< dim, spacedim > &tria, const bool isotropic=false, const unsigned int max_iterations=100)
Definition: grid_tools.cc:3469
void map_boundary_to_manifold_ids(const std::vector< types::boundary_id > &src_boundary_ids, const std::vector< types::manifold_id > &dst_manifold_ids, Triangulation< dim, spacedim > &tria, const std::vector< types::boundary_id > &reset_boundary_ids={})
Definition: grid_tools.cc:3351
std::vector< CellData< 1 > > boundary_lines
Definition: tria.h:249
Transformed quadrature weights.
static ::ExceptionBase & ExcScalingFactorNotPositive(double arg1)
unsigned int n_active_cells() const
Definition: tria.cc:11084
const Triangulation< dim, spacedim > & get_triangulation() const
unsigned int n_used_vertices() const
Definition: tria.cc:11612
static const unsigned int invalid_unsigned_int
Definition: types.h:173
std::map< unsigned int, Point< spacedim > > get_all_vertices_at_boundary(const Triangulation< dim, spacedim > &tria)
Definition: grid_tools.cc:826
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1248
void copy_boundary_to_manifold_id(Triangulation< dim, spacedim > &tria, const bool reset_boundary_ids=false)
Definition: grid_tools.cc:3331
active_face_iterator begin_active_face() const
Definition: tria.cc:10688
double diameter(const Triangulation< dim, spacedim > &tria)
Definition: grid_tools.cc:76
void distort_random(const double factor, Triangulation< dim, spacedim > &triangulation, const bool keep_boundary=true)
Definition: grid_tools.cc:858
cell_iterator begin(const unsigned int level=0) const
Definition: dof_handler.cc:723
void delete_duplicated_vertices(std::vector< Point< spacedim > > &all_vertices, std::vector< CellData< dim > > &cells, SubCellData &subcelldata, std::vector< unsigned int > &considered_vertices, const double tol=1e-12)
Definition: grid_tools.cc:491
virtual bool has_hanging_nodes() const
Definition: tria.cc:11206
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
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
std::pair< unsigned int, double > get_longest_direction(typename Triangulation< dim, spacedim >::active_cell_iterator cell)
Definition: grid_tools.cc:3439
const Mapping< dim, spacedim > & get_mapping() const
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)
Task< RT > new_task(const std::function< RT()> &function)
std::list< typename Triangulation< dim, spacedim >::cell_iterator > distorted_cells
Definition: tria.h:1623
unsigned int find_closest_vertex_of_cell(const typename Triangulation< dim, spacedim >::active_cell_iterator &cell, const Point< spacedim > &position)
Definition: grid_tools.cc:1731
void regularize_corner_cells(Triangulation< dim, spacedim > &tria, const double limit_angle_fraction=.75)
Definition: grid_tools.cc:3534
void add(const size_type i, const size_type j)
void scale(const double scaling_factor, Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:680
double volume(const Triangulation< dim, spacedim > &tria, const Mapping< dim, spacedim > &mapping=(StaticMappingQ1< dim, spacedim >::mapping))
Definition: grid_tools.cc:131
IteratorRange< active_cell_iterator > active_cell_iterators() const
Definition: tria.cc:10632
std::vector< std::set< typename Triangulation< dim, spacedim >::active_cell_iterator > > vertex_to_cell_map(const Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:1978
virtual std::array< Point< spacedim >, GeometryInfo< dim >::vertices_per_cell > get_vertices(const typename Triangulation< dim, spacedim >::cell_iterator &cell) const
Definition: mapping.cc:25
void join() const
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: tria.cc:10508
std::map< unsigned int, types::global_vertex_index > compute_local_to_global_vertex_index_map(const parallel::distributed::Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:2022
void create_laplace_matrix(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const Quadrature< dim > &q, SparseMatrix< double > &matrix, const Function< spacedim > *const a=nullptr, const ConstraintMatrix &constraints=ConstraintMatrix())
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
numbers::NumberTraits< Number >::real_type norm() const
Definition: tensor.h:1273
types::boundary_id boundary_id
Definition: tria.h:162
virtual Point< dim > transform_real_to_unit_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< spacedim > &p) const =0
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
double maximal_cell_diameter(const Triangulation< dim, spacedim > &triangulation, const Mapping< dim, spacedim > &mapping=(StaticMappingQ1< dim, spacedim >::mapping))
Definition: grid_tools.cc:2830
void partition_multigrid_levels(Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:2691
double minimal_cell_diameter(const Triangulation< dim, spacedim > &triangulation, const Mapping< dim, spacedim > &mapping=(StaticMappingQ1< dim, spacedim >::mapping))
Definition: grid_tools.cc:2804
void partition_triangulation_zorder(const unsigned int n_partitions, Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:2592
size_type n_cols() const
void partition_triangulation(const unsigned int n_partitions, Triangulation< dim, spacedim > &triangulation, const SparsityTools::Partitioner partitioner=SparsityTools::Partitioner::metis)
Definition: grid_tools.cc:2406
void set_manifold(const types::manifold_id number, const Manifold< dim, spacedim > &manifold_object)
Definition: tria.cc:8955
static double distance_to_unit_cell(const Point< dim > &p)
size_type n_rows() const
void get_vertex_connectivity_of_cells(const Triangulation< dim, spacedim > &triangulation, DynamicSparsityPattern &connectivity)
Definition: grid_tools.cc:2354
cell_iterator end() const
Definition: tria.cc:10576
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: dof_handler.cc:735
size_type n() const
static const double PI
Definition: numbers.h:127
virtual void execute_coarsening_and_refinement()
Definition: tria.cc:11739
Definition: tria.h:76
static ::ExceptionBase & ExcInvalidNumberOfPartitions(int arg1)
static ::ExceptionBase & ExcMessage(std::string arg1)
bool check_consistency(const unsigned int dim) const
Definition: tria.cc:47
return_type guess_point_owner(const std::vector< std::vector< BoundingBox< spacedim > > > &global_bboxes, const std::vector< Point< spacedim > > &points)
Definition: grid_tools.cc:1928
void laplace_transform(const std::map< unsigned int, Point< dim > > &new_points, Triangulation< dim > &tria, const Function< dim, double > *coefficient=nullptr, const bool solve_for_absolute_positions=false)
T sum(const T &t, const MPI_Comm &mpi_communicator)
unsigned int global_dof_index
Definition: types.h:88
void get_vertex_connectivity_of_cells_on_level(const Triangulation< dim, spacedim > &triangulation, const unsigned int level, DynamicSparsityPattern &connectivity)
Definition: grid_tools.cc:2379
void partition(const SparsityPattern &sparsity_pattern, const unsigned int n_partitions, std::vector< unsigned int > &partition_indices, const Partitioner partitioner=Partitioner::metis)
#define Assert(cond, exc)
Definition: exceptions.h:1142
void reinit(const size_type m, const size_type n, const IndexSet &rowset=IndexSet())
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
Abstract base class for mapping classes.
Definition: dof_tools.h:46
std::vector< BoundingBox< MeshType::space_dimension > > compute_mesh_predicate_bounding_box(const MeshType &mesh, const std::function< bool(const typename MeshType::active_cell_iterator &)> &predicate, const unsigned int refinement_level=0, const bool allow_merge=false, const unsigned int max_boxes=numbers::invalid_unsigned_int)
Definition: grid_tools.cc:1808
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
Definition: tria.cc:9240
types::material_id material_id
Definition: tria.h:151
const std::vector< Point< spacedim > > & get_vertices() const
void remove_anisotropy(Triangulation< dim, spacedim > &tria, const double max_ratio=1.6180339887, const unsigned int max_iterations=5)
Definition: grid_tools.cc:3504
return_type distributed_compute_point_locations(const GridTools::Cache< dim, spacedim > &cache, const std::vector< Point< spacedim > > &local_points, const std::vector< std::vector< BoundingBox< spacedim > > > &global_bboxes)
Definition: grid_tools.cc:4316
void initialize(const MatrixType &A, const AdditionalData &parameters=AdditionalData())
static void reorder_cells(std::vector< CellData< dim > > &original_cells, const bool use_new_style_ordering=false)
unsigned long long int global_vertex_index
Definition: types.h:47
void copy_material_to_manifold_id(Triangulation< dim, spacedim > &tria, const bool compute_face_ids=false)
Definition: grid_tools.cc:3413
void rotate(const double angle, Triangulation< 2 > &triangulation)
Definition: grid_tools.cc:661
Triangulation< dim, spacedim >::DistortedCellList fix_up_distorted_child_cells(const typename Triangulation< dim, spacedim >::DistortedCellList &distorted_cells, Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:3298
void copy_from(const size_type n_rows, const size_type n_cols, const ForwardIterator begin, const ForwardIterator end)
return_type compute_point_locations(const Cache< dim, spacedim > &cache, const std::vector< Point< spacedim > > &points, const typename Triangulation< dim, spacedim >::active_cell_iterator &cell_hint=typename Triangulation< dim, spacedim >::active_cell_iterator())
Definition: grid_tools.cc:3841
std::vector< std::vector< Tensor< 1, spacedim > > > vertex_to_cell_centers_directions(const Triangulation< dim, spacedim > &mesh, const std::vector< std::set< typename Triangulation< dim, spacedim >::active_cell_iterator > > &vertex_to_cells)
Definition: grid_tools.cc:1557
std::vector< unsigned int > invert_permutation(const std::vector< unsigned int > &permutation)
Definition: utilities.cc:509
unsigned int subdomain_id
Definition: types.h:42
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:98
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
numbers::NumberTraits< Number >::real_type distance(const Point< dim, Number > &p) const
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
Definition: mpi.cc:65
unsigned int size() const
types::manifold_id manifold_id
Definition: tria.h:173
const std::vector< std::vector< Tensor< 1, spacedim > > > & get_vertex_to_cell_centers_directions() const
unsigned int n_raw_faces() const
Definition: tria.cc:11116
Point< Iterator::AccessorType::space_dimension > project_to_object(const Iterator &object, const Point< Iterator::AccessorType::space_dimension > &trial_point)
void swap(Vector< Number > &u, Vector< Number > &v)
Definition: vector.h:1312
void reorder_hierarchical(const DynamicSparsityPattern &sparsity, std::vector< DynamicSparsityPattern::size_type > &new_indices)
static void alternating_form_at_vertices(const Point< spacedim >(&vertices)[vertices_per_cell], Tensor< spacedim-dim, spacedim >(&forms)[vertices_per_cell])
const types::subdomain_id artificial_subdomain_id
Definition: types.h:264
std::vector< types::boundary_id > get_boundary_ids() const
Definition: tria.cc:9105
const types::manifold_id invalid_manifold_id
Definition: types.h:229
unsigned int manifold_id
Definition: types.h:122
#define AssertThrowMPI(error_code)
Definition: exceptions.h:1314
void make_sparsity_pattern(const DoFHandlerType &dof_handler, SparsityPatternType &sparsity_pattern, const ConstraintMatrix &constraints=ConstraintMatrix(), const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
void transform(const Transformation &transformation, Triangulation< dim, spacedim > &triangulation)
double JxW(const unsigned int quadrature_point) const
const std::vector< bool > & get_used_vertices() const
Definition: tria.cc:11622
T min(const T &t, const MPI_Comm &mpi_communicator)
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
std::vector< CellData< 2 > > boundary_quads
Definition: tria.h:257
numbers::NumberTraits< Number >::real_type square() const
void get_subdomain_association(const Triangulation< dim, spacedim > &triangulation, std::vector< types::subdomain_id > &subdomain)
Definition: grid_tools.cc:2716
void get_face_connectivity_of_cells(const Triangulation< dim, spacedim > &triangulation, DynamicSparsityPattern &connectivity)
Definition: grid_tools.cc:2307
Definition: fe.h:33
void refine_global(const unsigned int times=1)
Definition: tria.cc:9448
void delete_unused_vertices(std::vector< Point< spacedim > > &vertices, std::vector< CellData< dim > > &cells, SubCellData &subcelldata)
Definition: grid_tools.cc:395
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
Definition: mpi.cc:75
virtual bool preserves_vertex_locations() const =0
static ::ExceptionBase & ExcNotImplemented()
Iterator points to a valid object.
std::vector< bool > get_locally_owned_vertices(const Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:2748
static ::ExceptionBase & ExcVertexNotUsed(unsigned int arg1)
face_iterator end_face() const
Definition: tria.cc:10709
IteratorState::IteratorStates state() const
void reinit(const TriaIterator< DoFCellAccessor< DoFHandlerType< dim, spacedim >, level_dof_access > > &cell)
Definition: fe_values.cc:4106
std::map< unsigned int, T > some_to_some(const MPI_Comm &comm, const std::map< unsigned int, T > &objects_to_send)
std::vector< types::manifold_id > get_manifold_ids() const
Definition: tria.cc:9137
bool vertex_used(const unsigned int index) const
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
Definition: tria.cc:9083
T max(const T &t, const MPI_Comm &mpi_communicator)
numbers::NumberTraits< Number >::real_type distance_square(const Point< dim, Number > &p) const
void shift(const Tensor< 1, spacedim > &shift_vector, Triangulation< dim, spacedim > &triangulation)
Definition: grid_tools.cc:652
unsigned int count_cells_with_subdomain_association(const Triangulation< dim, spacedim > &triangulation, const types::subdomain_id subdomain)
Definition: grid_tools.cc:2731
unsigned int find_closest_vertex(const std::map< unsigned int, Point< spacedim >> &vertices, const Point< spacedim > &p)
virtual void clear()
Definition: tria.cc:8912
unsigned int vertices[GeometryInfo< structdim >::vertices_per_cell]
Definition: tria.h:132
static ::ExceptionBase & ExcInternalError()
Triangulation< dim, spacedim > & get_triangulation()
Definition: tria.cc:11695
const std::vector< std::set< typename Triangulation< dim, spacedim >::active_cell_iterator > > & get_vertex_to_cell_map() const