Reference documentation for deal.II version 9.1.0-pre
tria.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2008 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/base/logstream.h>
18 #include <deal.II/base/memory_consumption.h>
19 #include <deal.II/base/utilities.h>
20 
21 #include <deal.II/distributed/p4est_wrappers.h>
22 #include <deal.II/distributed/tria.h>
23 
24 #include <deal.II/grid/grid_tools.h>
25 #include <deal.II/grid/tria.h>
26 #include <deal.II/grid/tria_accessor.h>
27 #include <deal.II/grid/tria_iterator.h>
28 
29 #include <deal.II/lac/dynamic_sparsity_pattern.h>
30 #include <deal.II/lac/sparsity_tools.h>
31 
32 #include <algorithm>
33 #include <fstream>
34 #include <iostream>
35 #include <numeric>
36 
37 
38 DEAL_II_NAMESPACE_OPEN
39 
40 
41 #ifdef DEAL_II_WITH_P4EST
42 
43 namespace
44 {
45  template <int dim, int spacedim>
46  void
47  get_vertex_to_cell_mappings(
48  const Triangulation<dim, spacedim> &triangulation,
49  std::vector<unsigned int> & vertex_touch_count,
50  std::vector<std::list<
52  unsigned int>>> & vertex_to_cell)
53  {
54  vertex_touch_count.resize(triangulation.n_vertices());
55  vertex_to_cell.resize(triangulation.n_vertices());
56 
58  triangulation.begin_active();
59  cell != triangulation.end();
60  ++cell)
61  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
62  {
63  ++vertex_touch_count[cell->vertex_index(v)];
64  vertex_to_cell[cell->vertex_index(v)].emplace_back(cell, v);
65  }
66  }
67 
68 
69 
70  template <int dim, int spacedim>
71  void
72  get_edge_to_cell_mappings(
73  const Triangulation<dim, spacedim> &triangulation,
74  std::vector<unsigned int> & edge_touch_count,
75  std::vector<std::list<
77  unsigned int>>> & edge_to_cell)
78  {
79  Assert(triangulation.n_levels() == 1, ExcInternalError());
80 
81  edge_touch_count.resize(triangulation.n_active_lines());
82  edge_to_cell.resize(triangulation.n_active_lines());
83 
85  triangulation.begin_active();
86  cell != triangulation.end();
87  ++cell)
88  for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
89  {
90  ++edge_touch_count[cell->line(l)->index()];
91  edge_to_cell[cell->line(l)->index()].emplace_back(cell, l);
92  }
93  }
94 
95 
96 
101  template <int dim, int spacedim>
102  void
103  set_vertex_and_cell_info(
104  const Triangulation<dim, spacedim> &triangulation,
105  const std::vector<unsigned int> & vertex_touch_count,
106  const std::vector<std::list<
108  unsigned int>>> & vertex_to_cell,
109  const std::vector<types::global_dof_index>
110  & coarse_cell_to_p4est_tree_permutation,
111  const bool set_vertex_info,
112  typename internal::p4est::types<dim>::connectivity *connectivity)
113  {
114  // copy the vertices into the connectivity structure. the triangulation
115  // exports the array of vertices, but some of the entries are sometimes
116  // unused; this shouldn't be the case for a newly created triangulation,
117  // but make sure
118  //
119  // note that p4est stores coordinates as a triplet of values even in 2d
120  Assert(triangulation.get_used_vertices().size() ==
121  triangulation.get_vertices().size(),
122  ExcInternalError());
123  Assert(std::find(triangulation.get_used_vertices().begin(),
124  triangulation.get_used_vertices().end(),
125  false) == triangulation.get_used_vertices().end(),
126  ExcInternalError());
127  if (set_vertex_info == true)
128  for (unsigned int v = 0; v < triangulation.n_vertices(); ++v)
129  {
130  connectivity->vertices[3 * v] = triangulation.get_vertices()[v][0];
131  connectivity->vertices[3 * v + 1] =
132  triangulation.get_vertices()[v][1];
133  connectivity->vertices[3 * v + 2] =
134  (spacedim == 2 ? 0 : triangulation.get_vertices()[v][2]);
135  }
136 
137  // next store the tree_to_vertex indices (each tree is here only a single
138  // cell in the coarse mesh). p4est requires vertex numbering in clockwise
139  // orientation
140  //
141  // while we're at it, also copy the neighborship information between cells
143  cell = triangulation.begin_active(),
144  endc = triangulation.end();
145  for (; cell != endc; ++cell)
146  {
147  const unsigned int index =
148  coarse_cell_to_p4est_tree_permutation[cell->index()];
149 
150  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
151  {
152  if (set_vertex_info == true)
153  connectivity
154  ->tree_to_vertex[index * GeometryInfo<dim>::vertices_per_cell +
155  v] = cell->vertex_index(v);
156  connectivity
157  ->tree_to_corner[index * GeometryInfo<dim>::vertices_per_cell +
158  v] = cell->vertex_index(v);
159  }
160 
161  // neighborship information. if a cell is at a boundary, then enter
162  // the index of the cell itself here
163  for (unsigned int f = 0; f < GeometryInfo<dim>::faces_per_cell; ++f)
164  if (cell->face(f)->at_boundary() == false)
165  connectivity
166  ->tree_to_tree[index * GeometryInfo<dim>::faces_per_cell + f] =
167  coarse_cell_to_p4est_tree_permutation[cell->neighbor(f)->index()];
168  else
169  connectivity
170  ->tree_to_tree[index * GeometryInfo<dim>::faces_per_cell + f] =
171  coarse_cell_to_p4est_tree_permutation[cell->index()];
172 
173  // fill tree_to_face, which is essentially neighbor_to_neighbor;
174  // however, we have to remap the resulting face number as well
175  for (unsigned int f = 0; f < GeometryInfo<dim>::faces_per_cell; ++f)
176  if (cell->face(f)->at_boundary() == false)
177  {
178  switch (dim)
179  {
180  case 2:
181  {
182  connectivity->tree_to_face
183  [index * GeometryInfo<dim>::faces_per_cell + f] =
184  cell->neighbor_of_neighbor(f);
185  break;
186  }
187 
188  case 3:
189  {
190  /*
191  * The values for tree_to_face are in 0..23 where ttf % 6
192  * gives the face number and ttf / 4 the face orientation
193  * code. The orientation is determined as follows. Let
194  * my_face and other_face be the two face numbers of the
195  * connecting trees in 0..5. Then the first face vertex
196  * of the lower of my_face and other_face connects to a
197  * face vertex numbered 0..3 in the higher of my_face and
198  * other_face. The face orientation is defined as this
199  * number. If my_face == other_face, treating either of
200  * both faces as the lower one leads to the same result.
201  */
202 
203  connectivity->tree_to_face[index * 6 + f] =
204  cell->neighbor_of_neighbor(f);
205 
206  unsigned int face_idx_list[2] = {
207  f, cell->neighbor_of_neighbor(f)};
209  cell_list[2] = {cell, cell->neighbor(f)};
210  unsigned int smaller_idx = 0;
211 
212  if (f > cell->neighbor_of_neighbor(f))
213  smaller_idx = 1;
214 
215  unsigned int larger_idx = (smaller_idx + 1) % 2;
216  // smaller = *_list[smaller_idx]
217  // larger = *_list[larger_idx]
218 
219  unsigned int v = 0;
220 
221  // global vertex index of vertex 0 on face of cell with
222  // smaller local face index
223  unsigned int g_idx = cell_list[smaller_idx]->vertex_index(
225  face_idx_list[smaller_idx],
226  0,
227  cell_list[smaller_idx]->face_orientation(
228  face_idx_list[smaller_idx]),
229  cell_list[smaller_idx]->face_flip(
230  face_idx_list[smaller_idx]),
231  cell_list[smaller_idx]->face_rotation(
232  face_idx_list[smaller_idx])));
233 
234  // loop over vertices on face from other cell and compare
235  // global vertex numbers
236  for (unsigned int i = 0;
237  i < GeometryInfo<dim>::vertices_per_face;
238  ++i)
239  {
240  unsigned int idx =
241  cell_list[larger_idx]->vertex_index(
243  face_idx_list[larger_idx], i));
244 
245  if (idx == g_idx)
246  {
247  v = i;
248  break;
249  }
250  }
251 
252  connectivity->tree_to_face[index * 6 + f] += 6 * v;
253  break;
254  }
255 
256  default:
257  Assert(false, ExcNotImplemented());
258  }
259  }
260  else
261  connectivity
262  ->tree_to_face[index * GeometryInfo<dim>::faces_per_cell + f] = f;
263  }
264 
265  // now fill the vertex information
266  connectivity->ctt_offset[0] = 0;
267  std::partial_sum(vertex_touch_count.begin(),
268  vertex_touch_count.end(),
269  &connectivity->ctt_offset[1]);
270 
271  const typename internal::p4est::types<dim>::locidx num_vtt =
272  std::accumulate(vertex_touch_count.begin(), vertex_touch_count.end(), 0u);
273  (void)num_vtt;
274  Assert(connectivity->ctt_offset[triangulation.n_vertices()] == num_vtt,
275  ExcInternalError());
276 
277  for (unsigned int v = 0; v < triangulation.n_vertices(); ++v)
278  {
279  Assert(vertex_to_cell[v].size() == vertex_touch_count[v],
280  ExcInternalError());
281 
282  typename std::list<
283  std::pair<typename Triangulation<dim, spacedim>::active_cell_iterator,
284  unsigned int>>::const_iterator p =
285  vertex_to_cell[v].begin();
286  for (unsigned int c = 0; c < vertex_touch_count[v]; ++c, ++p)
287  {
288  connectivity->corner_to_tree[connectivity->ctt_offset[v] + c] =
289  coarse_cell_to_p4est_tree_permutation[p->first->index()];
290  connectivity->corner_to_corner[connectivity->ctt_offset[v] + c] =
291  p->second;
292  }
293  }
294  }
295 
296 
297 
298  template <int dim, int spacedim>
299  bool
300  tree_exists_locally(
301  const typename internal::p4est::types<dim>::forest *parallel_forest,
302  const typename internal::p4est::types<dim>::topidx coarse_grid_cell)
303  {
304  Assert(coarse_grid_cell < parallel_forest->connectivity->num_trees,
305  ExcInternalError());
306  return ((coarse_grid_cell >= parallel_forest->first_local_tree) &&
307  (coarse_grid_cell <= parallel_forest->last_local_tree));
308  }
309 
310 
311  template <int dim, int spacedim>
312  void
313  delete_all_children_and_self(
314  const typename Triangulation<dim, spacedim>::cell_iterator &cell)
315  {
316  if (cell->has_children())
317  for (unsigned int c = 0; c < cell->n_children(); ++c)
318  delete_all_children_and_self<dim, spacedim>(cell->child(c));
319  else
320  cell->set_coarsen_flag();
321  }
322 
323 
324 
325  template <int dim, int spacedim>
326  void
327  delete_all_children(
328  const typename Triangulation<dim, spacedim>::cell_iterator &cell)
329  {
330  if (cell->has_children())
331  for (unsigned int c = 0; c < cell->n_children(); ++c)
332  delete_all_children_and_self<dim, spacedim>(cell->child(c));
333  }
334 
335 
336  template <int dim, int spacedim>
337  void
338  determine_level_subdomain_id_recursively(
339  const typename internal::p4est::types<dim>::tree & tree,
340  const typename internal::p4est::types<dim>::locidx & tree_index,
341  const typename Triangulation<dim, spacedim>::cell_iterator &dealii_cell,
342  const typename internal::p4est::types<dim>::quadrant & p4est_cell,
343  typename internal::p4est::types<dim>::forest & forest,
344  const types::subdomain_id my_subdomain,
345  const std::vector<std::vector<bool>> & marked_vertices)
346  {
347  if (dealii_cell->level_subdomain_id() == numbers::artificial_subdomain_id)
348  {
349  // important: only assign the level_subdomain_id if it is a ghost cell
350  // even though we could fill in all.
351  bool used = false;
352  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
353  {
354  if (marked_vertices[dealii_cell->level()]
355  [dealii_cell->vertex_index(v)])
356  {
357  used = true;
358  break;
359  }
360  }
361 
362  // Special case: if this cell is active we might be a ghost neighbor
363  // to a locally owned cell across a vertex that is finer.
364  // Example (M= my, O=dealii_cell, owned by somebody else):
365  // *------*
366  // | |
367  // | O |
368  // | |
369  // *---*---*------*
370  // | M | M |
371  // *---*---*
372  // | | M |
373  // *---*---*
374  if (!used && dealii_cell->active() &&
375  dealii_cell->is_artificial() == false &&
376  dealii_cell->level() + 1 < static_cast<int>(marked_vertices.size()))
377  {
378  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
379  ++v)
380  {
381  if (marked_vertices[dealii_cell->level() + 1]
382  [dealii_cell->vertex_index(v)])
383  {
384  used = true;
385  break;
386  }
387  }
388  }
389 
390  // Like above, but now the other way around
391  if (!used && dealii_cell->active() &&
392  dealii_cell->is_artificial() == false && dealii_cell->level() > 0)
393  {
394  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
395  ++v)
396  {
397  if (marked_vertices[dealii_cell->level() - 1]
398  [dealii_cell->vertex_index(v)])
399  {
400  used = true;
401  break;
402  }
403  }
404  }
405 
406  if (used)
407  {
409  &forest, tree_index, &p4est_cell, my_subdomain);
410  Assert((owner != -2) && (owner != -1),
411  ExcMessage("p4est should know the owner."));
412  dealii_cell->set_level_subdomain_id(owner);
413  }
414  }
415 
416  if (dealii_cell->has_children())
417  {
420  for (unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
421  ++c)
422  switch (dim)
423  {
424  case 2:
425  P4EST_QUADRANT_INIT(&p4est_child[c]);
426  break;
427  case 3:
428  P8EST_QUADRANT_INIT(&p4est_child[c]);
429  break;
430  default:
431  Assert(false, ExcNotImplemented());
432  }
433 
434 
436  p4est_child);
437 
438  for (unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
439  ++c)
440  {
441  determine_level_subdomain_id_recursively<dim, spacedim>(
442  tree,
443  tree_index,
444  dealii_cell->child(c),
445  p4est_child[c],
446  forest,
447  my_subdomain,
448  marked_vertices);
449  }
450  }
451  }
452 
453 
454  template <int dim, int spacedim>
455  void
456  match_tree_recursively(
457  const typename internal::p4est::types<dim>::tree & tree,
458  const typename Triangulation<dim, spacedim>::cell_iterator &dealii_cell,
459  const typename internal::p4est::types<dim>::quadrant & p4est_cell,
460  const typename internal::p4est::types<dim>::forest & forest,
461  const types::subdomain_id my_subdomain)
462  {
463  // check if this cell exists in the local p4est cell
464  if (sc_array_bsearch(const_cast<sc_array_t *>(&tree.quadrants),
465  &p4est_cell,
467  -1)
468  {
469  // yes, cell found in local part of p4est
470  delete_all_children<dim, spacedim>(dealii_cell);
471  if (!dealii_cell->has_children())
472  dealii_cell->set_subdomain_id(my_subdomain);
473  }
474  else
475  {
476  // no, cell not found in local part of p4est. this means that the
477  // local part is more refined than the current cell. if this cell has
478  // no children of its own, we need to refine it, and if it does
479  // already have children then loop over all children and see if they
480  // are locally available as well
481  if (dealii_cell->has_children() == false)
482  dealii_cell->set_refine_flag();
483  else
484  {
487  for (unsigned int c = 0;
488  c < GeometryInfo<dim>::max_children_per_cell;
489  ++c)
490  switch (dim)
491  {
492  case 2:
493  P4EST_QUADRANT_INIT(&p4est_child[c]);
494  break;
495  case 3:
496  P8EST_QUADRANT_INIT(&p4est_child[c]);
497  break;
498  default:
499  Assert(false, ExcNotImplemented());
500  }
501 
502 
504  p4est_child);
505 
506  for (unsigned int c = 0;
507  c < GeometryInfo<dim>::max_children_per_cell;
508  ++c)
510  const_cast<typename internal::p4est::types<dim>::tree *>(
511  &tree),
512  &p4est_child[c]) == false)
513  {
514  // no, this child is locally not available in the p4est.
515  // delete all its children but, because this may not be
516  // successful, make sure to mark all children recursively
517  // as not local.
518  delete_all_children<dim, spacedim>(dealii_cell->child(c));
519  dealii_cell->child(c)->recursively_set_subdomain_id(
521  }
522  else
523  {
524  // at least some part of the tree rooted in this child is
525  // locally available
526  match_tree_recursively<dim, spacedim>(tree,
527  dealii_cell->child(c),
528  p4est_child[c],
529  forest,
530  my_subdomain);
531  }
532  }
533  }
534  }
535 
536 
537  template <int dim, int spacedim>
538  void
539  match_quadrant(
540  const ::Triangulation<dim, spacedim> * tria,
541  unsigned int dealii_index,
542  const typename internal::p4est::types<dim>::quadrant &ghost_quadrant,
543  types::subdomain_id ghost_owner)
544  {
545  const int l = ghost_quadrant.level;
546 
547  for (int i = 0; i < l; ++i)
548  {
550  i,
551  dealii_index);
552  if (cell->has_children() == false)
553  {
554  cell->clear_coarsen_flag();
555  cell->set_refine_flag();
556  return;
557  }
558 
559  const int child_id =
561  i + 1);
562  dealii_index = cell->child_index(child_id);
563  }
564 
566  l,
567  dealii_index);
568  if (cell->has_children())
569  delete_all_children<dim, spacedim>(cell);
570  else
571  {
572  cell->clear_coarsen_flag();
573  cell->set_subdomain_id(ghost_owner);
574  }
575  }
576 
577 
578 
584  template <int dim, int spacedim>
585  class RefineAndCoarsenList
586  {
587  public:
588  RefineAndCoarsenList(const Triangulation<dim, spacedim> &triangulation,
589  const std::vector<types::global_dof_index>
590  &p4est_tree_to_coarse_cell_permutation,
591  const types::subdomain_id my_subdomain);
592 
601  static int
602  refine_callback(
603  typename internal::p4est::types<dim>::forest * forest,
604  typename internal::p4est::types<dim>::topidx coarse_cell_index,
605  typename internal::p4est::types<dim>::quadrant *quadrant);
606 
611  static int
612  coarsen_callback(
613  typename internal::p4est::types<dim>::forest * forest,
614  typename internal::p4est::types<dim>::topidx coarse_cell_index,
615  typename internal::p4est::types<dim>::quadrant *children[]);
616 
617  bool
618  pointers_are_at_end() const;
619 
620  private:
621  std::vector<typename internal::p4est::types<dim>::quadrant> refine_list;
622  typename std::vector<typename internal::p4est::types<dim>::quadrant>::
623  const_iterator current_refine_pointer;
624 
625  std::vector<typename internal::p4est::types<dim>::quadrant> coarsen_list;
626  typename std::vector<typename internal::p4est::types<dim>::quadrant>::
627  const_iterator current_coarsen_pointer;
628 
629  void
630  build_lists(
631  const typename Triangulation<dim, spacedim>::cell_iterator &cell,
632  const typename internal::p4est::types<dim>::quadrant & p4est_cell,
633  const types::subdomain_id myid);
634  };
635 
636 
637 
638  template <int dim, int spacedim>
639  bool
640  RefineAndCoarsenList<dim, spacedim>::pointers_are_at_end() const
641  {
642  return ((current_refine_pointer == refine_list.end()) &&
643  (current_coarsen_pointer == coarsen_list.end()));
644  }
645 
646 
647 
648  template <int dim, int spacedim>
649  RefineAndCoarsenList<dim, spacedim>::RefineAndCoarsenList(
650  const Triangulation<dim, spacedim> &triangulation,
651  const std::vector<types::global_dof_index>
652  & p4est_tree_to_coarse_cell_permutation,
653  const types::subdomain_id my_subdomain)
654  {
655  // count how many flags are set and allocate that much memory
656  unsigned int n_refine_flags = 0, n_coarsen_flags = 0;
658  triangulation.begin_active();
659  cell != triangulation.end();
660  ++cell)
661  {
662  // skip cells that are not local
663  if (cell->subdomain_id() != my_subdomain)
664  continue;
665 
666  if (cell->refine_flag_set())
667  ++n_refine_flags;
668  else if (cell->coarsen_flag_set())
669  ++n_coarsen_flags;
670  }
671 
672  refine_list.reserve(n_refine_flags);
673  coarsen_list.reserve(n_coarsen_flags);
674 
675 
676  // now build the lists of cells that are flagged. note that p4est will
677  // traverse its cells in the order in which trees appear in the
678  // forest. this order is not the same as the order of coarse cells in the
679  // deal.II Triangulation because we have translated everything by the
680  // coarse_cell_to_p4est_tree_permutation permutation. in order to make
681  // sure that the output array is already in the correct order, traverse
682  // our coarse cells in the same order in which p4est will:
683  for (unsigned int c = 0; c < triangulation.n_cells(0); ++c)
684  {
685  unsigned int coarse_cell_index =
686  p4est_tree_to_coarse_cell_permutation[c];
687 
689  &triangulation, 0, coarse_cell_index);
690 
691  typename internal::p4est::types<dim>::quadrant p4est_cell;
693  /*level=*/0,
694  /*index=*/0);
695  p4est_cell.p.which_tree = c;
696  build_lists(cell, p4est_cell, my_subdomain);
697  }
698 
699 
700  Assert(refine_list.size() == n_refine_flags, ExcInternalError());
701  Assert(coarsen_list.size() == n_coarsen_flags, ExcInternalError());
702 
703  // make sure that our ordering in fact worked
704  for (unsigned int i = 1; i < refine_list.size(); ++i)
705  Assert(refine_list[i].p.which_tree >= refine_list[i - 1].p.which_tree,
706  ExcInternalError());
707  for (unsigned int i = 1; i < coarsen_list.size(); ++i)
708  Assert(coarsen_list[i].p.which_tree >= coarsen_list[i - 1].p.which_tree,
709  ExcInternalError());
710 
711  current_refine_pointer = refine_list.begin();
712  current_coarsen_pointer = coarsen_list.begin();
713  }
714 
715 
716 
717  template <int dim, int spacedim>
718  void
719  RefineAndCoarsenList<dim, spacedim>::build_lists(
720  const typename Triangulation<dim, spacedim>::cell_iterator &cell,
721  const typename internal::p4est::types<dim>::quadrant & p4est_cell,
722  const types::subdomain_id my_subdomain)
723  {
724  if (!cell->has_children())
725  {
726  if (cell->subdomain_id() == my_subdomain)
727  {
728  if (cell->refine_flag_set())
729  refine_list.push_back(p4est_cell);
730  else if (cell->coarsen_flag_set())
731  coarsen_list.push_back(p4est_cell);
732  }
733  }
734  else
735  {
738  for (unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
739  ++c)
740  switch (dim)
741  {
742  case 2:
743  P4EST_QUADRANT_INIT(&p4est_child[c]);
744  break;
745  case 3:
746  P8EST_QUADRANT_INIT(&p4est_child[c]);
747  break;
748  default:
749  Assert(false, ExcNotImplemented());
750  }
752  p4est_child);
753  for (unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
754  ++c)
755  {
756  p4est_child[c].p.which_tree = p4est_cell.p.which_tree;
757  build_lists(cell->child(c), p4est_child[c], my_subdomain);
758  }
759  }
760  }
761 
762 
763  template <int dim, int spacedim>
764  int
765  RefineAndCoarsenList<dim, spacedim>::refine_callback(
766  typename internal::p4est::types<dim>::forest * forest,
767  typename internal::p4est::types<dim>::topidx coarse_cell_index,
768  typename internal::p4est::types<dim>::quadrant *quadrant)
769  {
770  RefineAndCoarsenList<dim, spacedim> *this_object =
771  reinterpret_cast<RefineAndCoarsenList<dim, spacedim> *>(
772  forest->user_pointer);
773 
774  // if there are no more cells in our list the current cell can't be
775  // flagged for refinement
776  if (this_object->current_refine_pointer == this_object->refine_list.end())
777  return false;
778 
779  Assert(coarse_cell_index <=
780  this_object->current_refine_pointer->p.which_tree,
781  ExcInternalError());
782 
783  // if p4est hasn't yet reached the tree of the next flagged cell the
784  // current cell can't be flagged for refinement
785  if (coarse_cell_index < this_object->current_refine_pointer->p.which_tree)
786  return false;
787 
788  // now we're in the right tree in the forest
789  Assert(coarse_cell_index <=
790  this_object->current_refine_pointer->p.which_tree,
791  ExcInternalError());
792 
793  // make sure that the p4est loop over cells hasn't gotten ahead of our own
794  // pointer
796  quadrant, &*this_object->current_refine_pointer) <= 0,
797  ExcInternalError());
798 
799  // now, if the p4est cell is one in the list, it is supposed to be refined
801  quadrant, &*this_object->current_refine_pointer))
802  {
803  ++this_object->current_refine_pointer;
804  return true;
805  }
806 
807  // p4est cell is not in list
808  return false;
809  }
810 
811 
812 
813  template <int dim, int spacedim>
814  int
815  RefineAndCoarsenList<dim, spacedim>::coarsen_callback(
816  typename internal::p4est::types<dim>::forest * forest,
817  typename internal::p4est::types<dim>::topidx coarse_cell_index,
818  typename internal::p4est::types<dim>::quadrant *children[])
819  {
820  RefineAndCoarsenList<dim, spacedim> *this_object =
821  reinterpret_cast<RefineAndCoarsenList<dim, spacedim> *>(
822  forest->user_pointer);
823 
824  // if there are no more cells in our list the current cell can't be
825  // flagged for coarsening
826  if (this_object->current_coarsen_pointer == this_object->coarsen_list.end())
827  return false;
828 
829  Assert(coarse_cell_index <=
830  this_object->current_coarsen_pointer->p.which_tree,
831  ExcInternalError());
832 
833  // if p4est hasn't yet reached the tree of the next flagged cell the
834  // current cell can't be flagged for coarsening
835  if (coarse_cell_index < this_object->current_coarsen_pointer->p.which_tree)
836  return false;
837 
838  // now we're in the right tree in the forest
839  Assert(coarse_cell_index <=
840  this_object->current_coarsen_pointer->p.which_tree,
841  ExcInternalError());
842 
843  // make sure that the p4est loop over cells hasn't gotten ahead of our own
844  // pointer
846  children[0], &*this_object->current_coarsen_pointer) <= 0,
847  ExcInternalError());
848 
849  // now, if the p4est cell is one in the list, it is supposed to be
850  // coarsened
852  children[0], &*this_object->current_coarsen_pointer))
853  {
854  // move current pointer one up
855  ++this_object->current_coarsen_pointer;
856 
857  // note that the next 3 cells in our list need to correspond to the
858  // other siblings of the cell we have just found
859  for (unsigned int c = 1; c < GeometryInfo<dim>::max_children_per_cell;
860  ++c)
861  {
863  children[c], &*this_object->current_coarsen_pointer),
864  ExcInternalError());
865  ++this_object->current_coarsen_pointer;
866  }
867 
868  return true;
869  }
870 
871  // p4est cell is not in list
872  return false;
873  }
874 
875 
876 
883  template <int dim, int spacedim>
884  class PartitionWeights
885  {
886  public:
892  explicit PartitionWeights(const std::vector<unsigned int> &cell_weights);
893 
901  static int
902  cell_weight(typename internal::p4est::types<dim>::forest *forest,
903  typename internal::p4est::types<dim>::topidx coarse_cell_index,
904  typename internal::p4est::types<dim>::quadrant *quadrant);
905 
906  private:
907  std::vector<unsigned int> cell_weights_list;
908  std::vector<unsigned int>::const_iterator current_pointer;
909  };
910 
911 
912  template <int dim, int spacedim>
913  PartitionWeights<dim, spacedim>::PartitionWeights(
914  const std::vector<unsigned int> &cell_weights)
915  : cell_weights_list(cell_weights)
916  {
917  // set the current pointer to the first element of the list, given that
918  // we will walk through it sequentially
919  current_pointer = cell_weights_list.begin();
920  }
921 
922 
923  template <int dim, int spacedim>
924  int
925  PartitionWeights<dim, spacedim>::cell_weight(
926  typename internal::p4est::types<dim>::forest *forest,
929  {
930  // the function gets two additional arguments, but we don't need them
931  // since we know in which order p4est will walk through the cells
932  // and have already built our weight lists in this order
933 
934  PartitionWeights<dim, spacedim> *this_object =
935  reinterpret_cast<PartitionWeights<dim, spacedim> *>(forest->user_pointer);
936 
937  Assert(this_object->current_pointer >=
938  this_object->cell_weights_list.begin(),
939  ExcInternalError());
940  Assert(this_object->current_pointer < this_object->cell_weights_list.end(),
941  ExcInternalError());
942 
943  // get the weight, increment the pointer, and return the weight
944  return *this_object->current_pointer++;
945  }
946 
947 
948 
949  template <int dim, int spacedim>
950  using quadrant_cell_relation_t = typename std::tuple<
951  typename ::internal::p4est::types<dim>::quadrant *,
952  typename ::Triangulation<dim, spacedim>::CellStatus,
953  typename ::Triangulation<dim, spacedim>::cell_iterator>;
954 
955 
956 
966  template <int dim, int spacedim>
967  inline void
968  add_single_quadrant_cell_relation(
969  std::vector<quadrant_cell_relation_t<dim, spacedim>> & quad_cell_rel,
970  const typename ::internal::p4est::types<dim>::tree & tree,
971  const unsigned int idx,
972  const typename Triangulation<dim, spacedim>::cell_iterator &dealii_cell,
973  const typename Triangulation<dim, spacedim>::CellStatus status)
974  {
975  const unsigned int local_quadrant_index = tree.quadrants_offset + idx;
976 
977  const auto q =
978  static_cast<typename ::internal::p4est::types<dim>::quadrant *>(
979  sc_array_index(const_cast<sc_array_t *>(&tree.quadrants), idx));
980 
981  // check if we will be writing into valid memory
982  Assert(local_quadrant_index < quad_cell_rel.size(), ExcInternalError());
983 
984  // store relation
985  quad_cell_rel[local_quadrant_index] =
986  std::make_tuple(q, status, dealii_cell);
987  }
988 
989 
990 
1000  template <int dim, int spacedim>
1001  void
1002  update_quadrant_cell_relations_recursively(
1003  std::vector<quadrant_cell_relation_t<dim, spacedim>> & quad_cell_rel,
1004  const typename ::internal::p4est::types<dim>::tree & tree,
1005  const typename Triangulation<dim, spacedim>::cell_iterator & dealii_cell,
1006  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell)
1007  {
1008  // find index of p4est_cell in the quadrants array of the corresponding tree
1009  const int idx = sc_array_bsearch(
1010  const_cast<sc_array_t *>(&tree.quadrants),
1011  &p4est_cell,
1013  if (idx == -1 &&
1015  const_cast<typename ::internal::p4est::types<dim>::tree *>(
1016  &tree),
1017  &p4est_cell) == false))
1018  // this quadrant and none of its children belong to us.
1019  return;
1020 
1021  // recurse further if both p4est and dealii still have children
1022  const bool p4est_has_children = (idx == -1);
1023  if (p4est_has_children && dealii_cell->has_children())
1024  {
1025  // recurse further
1026  typename ::internal::p4est::types<dim>::quadrant
1028 
1029  for (unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
1030  ++c)
1031  switch (dim)
1032  {
1033  case 2:
1034  P4EST_QUADRANT_INIT(&p4est_child[c]);
1035  break;
1036  case 3:
1037  P8EST_QUADRANT_INIT(&p4est_child[c]);
1038  break;
1039  default:
1040  Assert(false, ExcNotImplemented());
1041  }
1042 
1044  &p4est_cell, p4est_child);
1045 
1046  for (unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
1047  ++c)
1048  {
1049  update_quadrant_cell_relations_recursively<dim, spacedim>(
1050  quad_cell_rel, tree, dealii_cell->child(c), p4est_child[c]);
1051  }
1052  }
1053  else if (!p4est_has_children && !dealii_cell->has_children())
1054  {
1055  // this active cell didn't change
1056  // save tuple into corresponding position
1057  add_single_quadrant_cell_relation<dim, spacedim>(
1058  quad_cell_rel,
1059  tree,
1060  idx,
1061  dealii_cell,
1063  }
1064  else if (p4est_has_children) // based on the conditions above, we know that
1065  // dealii_cell has no children
1066  {
1067  // this cell got refined in p4est, but the dealii_cell has not yet been
1068  // refined
1069 
1070  // this quadrant is not active
1071  // generate its children, and store information in those
1072  typename ::internal::p4est::types<dim>::quadrant
1074  for (unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
1075  ++c)
1076  switch (dim)
1077  {
1078  case 2:
1079  P4EST_QUADRANT_INIT(&p4est_child[c]);
1080  break;
1081  case 3:
1082  P8EST_QUADRANT_INIT(&p4est_child[c]);
1083  break;
1084  default:
1085  Assert(false, ExcNotImplemented());
1086  }
1087 
1089  &p4est_cell, p4est_child);
1090 
1091  // mark first child with CELL_REFINE and the remaining children with
1092  // CELL_INVALID, but associate them all with the parent cell unpack
1093  // algorithm will be called only on CELL_REFINE flagged quadrant
1094  int child_idx;
1095  typename Triangulation<dim, spacedim>::CellStatus cell_status;
1096  for (unsigned int i = 0; i < GeometryInfo<dim>::max_children_per_cell;
1097  ++i)
1098  {
1099  child_idx = sc_array_bsearch(
1100  const_cast<sc_array_t *>(&tree.quadrants),
1101  &p4est_child[i],
1103 
1104  cell_status = (i == 0) ? Triangulation<dim, spacedim>::CELL_REFINE :
1106 
1107  add_single_quadrant_cell_relation<dim, spacedim>(
1108  quad_cell_rel, tree, child_idx, dealii_cell, cell_status);
1109  }
1110  }
1111  else // based on the conditions above, we know that p4est_cell has no
1112  // children, and the dealii_cell does
1113  {
1114  // its children got coarsened into this cell in p4est,
1115  // but the dealii_cell still has its children
1116  add_single_quadrant_cell_relation<dim, spacedim>(
1117  quad_cell_rel,
1118  tree,
1119  idx,
1120  dealii_cell,
1122  }
1123  }
1124 } // namespace
1125 
1126 
1127 
1128 namespace parallel
1129 {
1130  namespace distributed
1131  {
1132  /* ------------------ class DataTransfer<dim,spacedim> ----------------- */
1133 
1134 
1135  template <int dim, int spacedim>
1137  MPI_Comm mpi_communicator)
1138  : mpi_communicator(mpi_communicator)
1139  , variable_size_data_stored(false)
1140  {}
1141 
1142 
1143 
1144  template <int dim, int spacedim>
1145  void
1147  const std::vector<quadrant_cell_relation_t> &quad_cell_relations,
1148  const std::vector<typename CellAttachedData::pack_callback_t>
1149  &pack_callbacks_fixed,
1150  const std::vector<typename CellAttachedData::pack_callback_t>
1151  &pack_callbacks_variable)
1152  {
1153  Assert(src_data_fixed.size() == 0,
1154  ExcMessage("Previously packed data has not been released yet!"));
1155  Assert(src_sizes_variable.size() == 0, ExcInternalError());
1156 
1157  const unsigned int n_callbacks_fixed = pack_callbacks_fixed.size();
1158  const unsigned int n_callbacks_variable = pack_callbacks_variable.size();
1159 
1160  // Store information that we packed variable size data in
1161  // a member variable for later.
1162  variable_size_data_stored = (n_callbacks_variable > 0);
1163 
1164  // If variable transfer is scheduled, we will store the data size that
1165  // each variable size callback function writes in this auxiliary
1166  // container. The information will be stored by each cell in this vector
1167  // temporarily.
1168  std::vector<unsigned int> cell_sizes_variable_cumulative(
1169  n_callbacks_variable);
1170 
1171  // Prepare the buffer structure, in which each callback function will
1172  // store its data for each active cell.
1173  // The outmost shell in this container construct corresponds to the
1174  // data packed per cell. The next layer resembles the data that
1175  // each callback function packs on the corresponding cell. These
1176  // buffers are chains of chars stored in an std::vector<char>.
1177  // A visualisation of the data structure:
1178  /* clang-format off */
1179  // | cell_1 | | cell_2 | ...
1180  // || callback_1 || callback_2 |...| || callback_1 || callback_2 |...| ...
1181  // |||char|char|...|||char|char|...|...| |||char|char|...|||char|char|...|...| ...
1182  /* clang-format on */
1183  std::vector<std::vector<std::vector<char>>> packed_fixed_size_data(
1184  quad_cell_relations.size());
1185  std::vector<std::vector<std::vector<char>>> packed_variable_size_data(
1186  variable_size_data_stored ? quad_cell_relations.size() : 0);
1187 
1188  //
1189  // --------- Pack data for fixed and variable size transfer ---------
1190  //
1191  // Iterate over all cells, call all callback functions on each cell,
1192  // and store their data in the corresponding buffer scope.
1193  {
1194  auto quad_cell_rel_it = quad_cell_relations.cbegin();
1195  auto data_cell_fixed_it = packed_fixed_size_data.begin();
1196  auto data_cell_variable_it = packed_variable_size_data.begin();
1197  for (; quad_cell_rel_it != quad_cell_relations.cend();
1198  ++quad_cell_rel_it, ++data_cell_fixed_it)
1199  {
1200  const auto &cell_status = std::get<1>(*quad_cell_rel_it);
1201  const auto &dealii_cell = std::get<2>(*quad_cell_rel_it);
1202 
1203  // Assertions about the tree structure.
1204  switch (cell_status)
1205  {
1207  CELL_PERSIST:
1209  CELL_REFINE:
1210  // double check the condition that we will only ever attach
1211  // data to active cells when we get here
1212  Assert(dealii_cell->active(), ExcInternalError());
1213  break;
1214 
1216  CELL_COARSEN:
1217  // double check the condition that we will only ever attach
1218  // data to cells with children when we get here. however, we
1219  // can only tolerate one level of coarsening at a time, so
1220  // check that the children are all active
1221  Assert(dealii_cell->active() == false, ExcInternalError());
1222  for (unsigned int c = 0;
1223  c < GeometryInfo<dim>::max_children_per_cell;
1224  ++c)
1225  Assert(dealii_cell->child(c)->active(), ExcInternalError());
1226  break;
1227 
1229  CELL_INVALID:
1230  // do nothing on invalid cells
1231  break;
1232 
1233  default:
1234  Assert(false, ExcInternalError());
1235  break;
1236  }
1237 
1238  // Reserve memory corresponding to the number of callback
1239  // functions that will be called.
1240  // If variable size transfer is scheduled, we need to leave
1241  // room for an array that holds information about how many
1242  // bytes each of the variable size callback functions will
1243  // write.
1244  // On cells flagged with CELL_INVALID, only its CellStatus
1245  // will be stored.
1246  const unsigned int n_fixed_size_data_sets_on_cell =
1247  1 +
1248  ((cell_status ==
1250  spacedim>::CELL_INVALID) ?
1251  0 :
1252  ((variable_size_data_stored ? 1 : 0) + n_callbacks_fixed));
1253  data_cell_fixed_it->resize(n_fixed_size_data_sets_on_cell);
1254 
1255  // We continue with packing all data on this specific cell.
1256  auto data_fixed_it = data_cell_fixed_it->begin();
1257 
1258  // First, we pack the CellStatus information.
1259  // to get consistent data sizes on each cell for the fixed size
1260  // transfer, we won't allow compression
1261  *data_fixed_it =
1262  Utilities::pack(cell_status, /*allow_compression=*/false);
1263  ++data_fixed_it;
1264 
1265  // Proceed with all registered callback functions.
1266  // Skip cells with the CELL_INVALID flag.
1267  if (cell_status !=
1269  spacedim>::CELL_INVALID)
1270  {
1271  // Pack fixed size data.
1272  for (auto callback_it = pack_callbacks_fixed.cbegin();
1273  callback_it != pack_callbacks_fixed.cend();
1274  ++callback_it, ++data_fixed_it)
1275  {
1276  *data_fixed_it = (*callback_it)(dealii_cell, cell_status);
1277  }
1278 
1279  // Pack variable size data.
1280  // If we store variable size data, we need to transfer
1281  // the sizes of each corresponding callback function
1282  // via fixed size transfer as well.
1283  if (variable_size_data_stored)
1284  {
1285  const unsigned int n_variable_size_data_sets_on_cell =
1286  ((cell_status ==
1288  CELL_INVALID) ?
1289  0 :
1290  n_callbacks_variable);
1291  data_cell_variable_it->resize(
1292  n_variable_size_data_sets_on_cell);
1293 
1294  auto callback_it = pack_callbacks_variable.cbegin();
1295  auto data_variable_it = data_cell_variable_it->begin();
1296  auto sizes_variable_it =
1297  cell_sizes_variable_cumulative.begin();
1298  for (; callback_it != pack_callbacks_variable.cend();
1299  ++callback_it, ++data_variable_it, ++sizes_variable_it)
1300  {
1301  *data_variable_it =
1302  (*callback_it)(dealii_cell, cell_status);
1303 
1304  // Store data sizes for each callback function first.
1305  // Make it cumulative below.
1306  *sizes_variable_it = data_variable_it->size();
1307  }
1308 
1309  // Turn size vector into its cumulative representation.
1310  std::partial_sum(cell_sizes_variable_cumulative.begin(),
1311  cell_sizes_variable_cumulative.end(),
1312  cell_sizes_variable_cumulative.begin());
1313 
1314  // Serialize cumulative variable size vector value-by-value.
1315  // This way we can circumvent the overhead of storing the
1316  // container object as a whole, since we know its size by
1317  // the number of registered callback functions.
1318  data_fixed_it->resize(n_callbacks_variable *
1319  sizeof(unsigned int));
1320  for (unsigned int i = 0; i < n_callbacks_variable; ++i)
1321  std::memcpy(&(data_fixed_it->at(i *
1322  sizeof(unsigned int))),
1323  &(cell_sizes_variable_cumulative.at(i)),
1324  sizeof(unsigned int));
1325 
1326  ++data_fixed_it;
1327  }
1328 
1329  // Double check that we packed everything we wanted
1330  // in the fixed size buffers.
1331  Assert(data_fixed_it == data_cell_fixed_it->end(),
1332  ExcInternalError());
1333  }
1334 
1335  // Increment the variable size data iterator
1336  // only if we actually pack this kind of data
1337  // to avoid getting out of bounds.
1338  if (variable_size_data_stored)
1339  ++data_cell_variable_it;
1340  } // loop over quad_cell_relations
1341  }
1342 
1343  //
1344  // ----------- Gather data sizes for fixed size transfer ------------
1345  //
1346  // Generate a vector which stores the sizes of each callback function,
1347  // including the packed CellStatus transfer.
1348  // Find the very first cell that we wrote to with all callback
1349  // functions (i.e. a cell that was not flagged with CELL_INVALID)
1350  // and store the sizes of each buffer.
1351  //
1352  // To deal with the case that at least one of the processors does not own
1353  // any cell at all, we will exchange the information about the data sizes
1354  // among them later. The code inbetween is still well-defined, since the
1355  // following loops will be skipped.
1356  std::vector<unsigned int> local_sizes_fixed(
1357  1 + n_callbacks_fixed + (variable_size_data_stored ? 1 : 0));
1358  for (auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
1359  data_cell_fixed_it != packed_fixed_size_data.cend();
1360  ++data_cell_fixed_it)
1361  {
1362  if (data_cell_fixed_it->size() == local_sizes_fixed.size())
1363  {
1364  auto sizes_fixed_it = local_sizes_fixed.begin();
1365  auto data_fixed_it = data_cell_fixed_it->cbegin();
1366  for (; data_fixed_it != data_cell_fixed_it->cend();
1367  ++data_fixed_it, ++sizes_fixed_it)
1368  {
1369  *sizes_fixed_it = data_fixed_it->size();
1370  }
1371 
1372  break;
1373  }
1374  }
1375 
1376  // Check if all cells have valid sizes.
1377  for (auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
1378  data_cell_fixed_it != packed_fixed_size_data.cend();
1379  ++data_cell_fixed_it)
1380  {
1381  Assert((data_cell_fixed_it->size() == 1) ||
1382  (data_cell_fixed_it->size() == local_sizes_fixed.size()),
1383  ExcInternalError());
1384  }
1385 
1386  // Share information about the packed data sizes
1387  // of all callback functions across all processors, in case one
1388  // of them does not own any cells at all.
1389  std::vector<unsigned int> global_sizes_fixed(local_sizes_fixed.size());
1390  Utilities::MPI::max(local_sizes_fixed,
1391  this->mpi_communicator,
1392  global_sizes_fixed);
1393 
1394  // Construct cumulative sizes, since this is the only information
1395  // we need from now on.
1396  sizes_fixed_cumulative.resize(global_sizes_fixed.size());
1397  std::partial_sum(global_sizes_fixed.begin(),
1398  global_sizes_fixed.end(),
1399  sizes_fixed_cumulative.begin());
1400 
1401  //
1402  // ---------- Gather data sizes for variable size transfer ----------
1403  //
1404  if (variable_size_data_stored)
1405  {
1406  src_sizes_variable.reserve(packed_variable_size_data.size());
1407  for (auto data_cell_variable_it = packed_variable_size_data.cbegin();
1408  data_cell_variable_it != packed_variable_size_data.cend();
1409  ++data_cell_variable_it)
1410  {
1411  int variable_data_size_on_cell = 0;
1412 
1413  for (auto data_variable_it = data_cell_variable_it->cbegin();
1414  data_variable_it != data_cell_variable_it->cend();
1415  ++data_variable_it)
1416  variable_data_size_on_cell += data_variable_it->size();
1417 
1418  src_sizes_variable.push_back(variable_data_size_on_cell);
1419  }
1420  }
1421 
1422  //
1423  // ------------------------ Build buffers ---------------------------
1424  //
1425  const unsigned int expected_size_fixed =
1426  quad_cell_relations.size() * sizes_fixed_cumulative.back();
1427  const unsigned int expected_size_variable =
1428  std::accumulate(src_sizes_variable.begin(),
1429  src_sizes_variable.end(),
1430  std::vector<int>::size_type(0));
1431 
1432  // Move every piece of packed fixed size data into the consecutive buffer.
1433  src_data_fixed.reserve(expected_size_fixed);
1434  for (auto data_cell_fixed_it = packed_fixed_size_data.begin();
1435  data_cell_fixed_it != packed_fixed_size_data.end();
1436  ++data_cell_fixed_it)
1437  {
1438  // Move every fraction of packed data into the buffer
1439  // reserved for this particular cell.
1440  for (auto data_fixed_it = data_cell_fixed_it->begin();
1441  data_fixed_it != data_cell_fixed_it->end();
1442  ++data_fixed_it)
1443  std::move(data_fixed_it->begin(),
1444  data_fixed_it->end(),
1445  std::back_inserter(src_data_fixed));
1446 
1447  // If we only packed the CellStatus information
1448  // (i.e. encountered a cell flagged CELL_INVALID),
1449  // fill the remaining space with invalid entries.
1450  // We can skip this if there is nothing else to pack.
1451  if ((data_cell_fixed_it->size() == 1) &&
1452  (sizes_fixed_cumulative.size() > 1))
1453  {
1454  const std::size_t bytes_skipped =
1455  sizes_fixed_cumulative.back() - sizes_fixed_cumulative.front();
1456 
1457  src_data_fixed.insert(src_data_fixed.end(),
1458  bytes_skipped,
1459  static_cast<char>(-1)); // invalid_char
1460  }
1461  }
1462 
1463  // Move every piece of packed variable size data into the consecutive
1464  // buffer.
1465  if (variable_size_data_stored)
1466  {
1467  src_data_variable.reserve(expected_size_variable);
1468  for (auto data_cell_variable_it = packed_variable_size_data.begin();
1469  data_cell_variable_it != packed_variable_size_data.end();
1470  ++data_cell_variable_it)
1471  {
1472  // Move every fraction of packed data into the buffer
1473  // reserved for this particular cell.
1474  for (auto data_variable_it = data_cell_variable_it->begin();
1475  data_variable_it != data_cell_variable_it->end();
1476  ++data_variable_it)
1477  std::move(data_variable_it->begin(),
1478  data_variable_it->end(),
1479  std::back_inserter(src_data_variable));
1480  }
1481  }
1482 
1483  // Double check that we packed everything correctly.
1484  Assert(src_data_fixed.size() == expected_size_fixed, ExcInternalError());
1485  Assert(src_data_variable.size() == expected_size_variable,
1486  ExcInternalError());
1487  }
1488 
1489 
1490 
1491  template <int dim, int spacedim>
1492  void
1494  const typename ::internal::p4est::types<dim>::forest
1495  *parallel_forest,
1496  const typename ::internal::p4est::types<dim>::gloidx
1497  *previous_global_first_quadrant)
1498  {
1499  Assert(sizes_fixed_cumulative.size() > 0,
1500  ExcMessage("No data has been packed!"));
1501 
1502  // Resize memory according to the data that we will receive.
1503  dest_data_fixed.resize(parallel_forest->local_num_quadrants *
1504  sizes_fixed_cumulative.back());
1505 
1506  // Execute non-blocking fixed size transfer.
1507  typename ::internal::p4est::types<dim>::transfer_context
1508  *tf_context;
1509  tf_context =
1511  parallel_forest->global_first_quadrant,
1512  previous_global_first_quadrant,
1513  parallel_forest->mpicomm,
1514  0,
1515  dest_data_fixed.data(),
1516  src_data_fixed.data(),
1517  sizes_fixed_cumulative.back());
1518 
1519  if (variable_size_data_stored)
1520  {
1521  // Resize memory according to the data that we will receive.
1522  dest_sizes_variable.resize(parallel_forest->local_num_quadrants);
1523 
1524  // Execute fixed size transfer of data sizes for variable size
1525  // transfer.
1527  parallel_forest->global_first_quadrant,
1528  previous_global_first_quadrant,
1529  parallel_forest->mpicomm,
1530  1,
1531  dest_sizes_variable.data(),
1532  src_sizes_variable.data(),
1533  sizeof(int));
1534  }
1535 
1537 
1538  // Release memory of previously packed data.
1539  src_data_fixed.clear();
1540  src_data_fixed.shrink_to_fit();
1541 
1542  if (variable_size_data_stored)
1543  {
1544  // Resize memory according to the data that we will receive.
1545  dest_data_variable.resize(
1546  std::accumulate(dest_sizes_variable.begin(),
1547  dest_sizes_variable.end(),
1548  std::vector<int>::size_type(0)));
1549 
1550  // ----- WORKAROUND -----
1551  // An assertion in p4est prevents us from sending/receiving no data
1552  // at all, which is mandatory if one of our processes does not own
1553  // any quadrant. This bypasses the assertion from being triggered.
1554  // - see: https://github.com/cburstedde/p4est/issues/48
1555  if (src_sizes_variable.size() == 0)
1556  src_sizes_variable.resize(1);
1557  if (dest_sizes_variable.size() == 0)
1558  dest_sizes_variable.resize(1);
1559 
1560  // Execute variable size transfer.
1562  parallel_forest->global_first_quadrant,
1563  previous_global_first_quadrant,
1564  parallel_forest->mpicomm,
1565  1,
1566  dest_data_variable.data(),
1567  dest_sizes_variable.data(),
1568  src_data_variable.data(),
1569  src_sizes_variable.data());
1570 
1571  // Release memory of previously packed data.
1572  src_sizes_variable.clear();
1573  src_sizes_variable.shrink_to_fit();
1574  src_data_variable.clear();
1575  src_data_variable.shrink_to_fit();
1576  }
1577  }
1578 
1579 
1580 
1581  template <int dim, int spacedim>
1582  void
1584  std::vector<quadrant_cell_relation_t> &quad_cell_relations) const
1585  {
1586  Assert(sizes_fixed_cumulative.size() > 0,
1587  ExcMessage("No data has been packed!"));
1588  if (quad_cell_relations.size() > 0)
1589  {
1590  Assert(dest_data_fixed.size() > 0,
1591  ExcMessage("No data has been received!"));
1592  }
1593 
1594  // Size of CellStatus object that will be unpacked on each cell.
1595  const unsigned int size = sizes_fixed_cumulative.front();
1596 
1597  // Iterate over all cells and overwrite the CellStatus
1598  // information from the transferred data.
1599  // Proceed buffer iterator position to next cell after
1600  // each iteration.
1601  auto quad_cell_rel_it = quad_cell_relations.begin();
1602  auto dest_fixed_it = dest_data_fixed.cbegin();
1603  for (; quad_cell_rel_it != quad_cell_relations.end();
1604  ++quad_cell_rel_it, dest_fixed_it += sizes_fixed_cumulative.back())
1605  {
1606  std::get<1>(*quad_cell_rel_it) = // cell_status
1607  Utilities::unpack<typename parallel::distributed::
1608  Triangulation<dim, spacedim>::CellStatus>(
1609  dest_fixed_it,
1610  dest_fixed_it + size,
1611  /*allow_compression=*/false);
1612  }
1613  }
1614 
1615 
1616 
1617  template <int dim, int spacedim>
1618  void
1620  const std::vector<quadrant_cell_relation_t> &quad_cell_relations,
1621  const unsigned int handle,
1622  const std::function<void(
1623  const typename ::Triangulation<dim, spacedim>::cell_iterator &,
1624  const typename ::Triangulation<dim, spacedim>::CellStatus &,
1625  const boost::iterator_range<std::vector<char>::const_iterator> &)>
1626  &unpack_callback) const
1627  {
1628  // We decode the handle returned by register_data_attach() back into
1629  // a format we can use. All even handles belong to those callback
1630  // functions which write/read variable size data, all odd handles interact
1631  // with fixed size buffers.
1632  const bool callback_variable_transfer = (handle % 2 == 0);
1633  const unsigned int callback_index = handle / 2;
1634 
1635  Assert(sizes_fixed_cumulative.size() > 0,
1636  ExcMessage("No data has been packed!"));
1637  if (quad_cell_relations.size() > 0)
1638  {
1639  Assert(dest_data_fixed.size() > 0,
1640  ExcMessage("No data has been received!"));
1641 
1642  if (callback_variable_transfer)
1643  Assert(dest_data_variable.size() > 0,
1644  ExcMessage("No data has been received!"));
1645  }
1646 
1647  std::vector<char>::const_iterator dest_data_it;
1648  std::vector<char>::const_iterator dest_sizes_cell_it;
1649 
1650  // Depending on whether our callback function unpacks fixed or
1651  // variable size data, we have to pursue different approaches
1652  // to localize the correct fraction of the buffer from which
1653  // we are allowed to read.
1654  unsigned int offset = numbers::invalid_unsigned_int;
1655  unsigned int size = numbers::invalid_unsigned_int;
1656  unsigned int data_increment = numbers::invalid_unsigned_int;
1657 
1658  if (callback_variable_transfer)
1659  {
1660  // For the variable size data, we need to extract the
1661  // data size from the fixed size buffer on each cell.
1662  //
1663  // We packed this information last, so the last packed
1664  // object in the fixed size buffer corresponds to the
1665  // variable data sizes.
1666  //
1667  // The last entry of sizes_fixed_cumulative corresponds
1668  // to the size of all fixed size data packed on the cell.
1669  // To get the offset for the last packed object, we need
1670  // to get the next-to-last entry.
1671  const unsigned int offset_variable_data_sizes =
1672  sizes_fixed_cumulative[sizes_fixed_cumulative.size() - 2];
1673 
1674  // This iterator points to the data size that the
1675  // callback_function packed for each specific cell.
1676  // Adjust buffer iterator to the offset of the callback
1677  // function so that we only have to advance its position
1678  // to the next cell after each iteration.
1679  dest_sizes_cell_it = dest_data_fixed.cbegin() +
1680  offset_variable_data_sizes +
1681  callback_index * sizeof(unsigned int);
1682 
1683  // Let the data iterator point to the correct buffer.
1684  dest_data_it = dest_data_variable.cbegin();
1685  }
1686  else
1687  {
1688  // For the fixed size data, we can get the information about
1689  // the buffer location on each cell directly from the
1690  // sizes_fixed_cumulative vector.
1691  offset = sizes_fixed_cumulative[callback_index];
1692  size = sizes_fixed_cumulative[callback_index + 1] - offset;
1693  data_increment = sizes_fixed_cumulative.back();
1694 
1695  // Let the data iterator point to the correct buffer.
1696  // Adjust buffer iterator to the offset of the callback
1697  // function so that we only have to advance its position
1698  // to the next cell after each iteration.
1699  dest_data_it = dest_data_fixed.cbegin() + offset;
1700  }
1701 
1702  // Iterate over all cells and unpack the transferred data.
1703  auto quad_cell_rel_it = quad_cell_relations.begin();
1704  auto dest_sizes_it = dest_sizes_variable.cbegin();
1705  for (; quad_cell_rel_it != quad_cell_relations.end();
1706  ++quad_cell_rel_it, dest_data_it += data_increment)
1707  {
1708  const auto &cell_status = std::get<1>(*quad_cell_rel_it);
1709  const auto &dealii_cell = std::get<2>(*quad_cell_rel_it);
1710 
1711  if (callback_variable_transfer)
1712  {
1713  // Update the increment according to the whole data size
1714  // of the current cell.
1715  data_increment = *dest_sizes_it;
1716 
1717  if (cell_status !=
1719  spacedim>::CELL_INVALID)
1720  {
1721  // Extract the corresponding values for offset and size from
1722  // the cumulative sizes array stored in the fixed size buffer.
1723  if (callback_index == 0)
1724  offset = 0;
1725  else
1726  std::memcpy(&offset,
1727  &(*(dest_sizes_cell_it - sizeof(unsigned int))),
1728  sizeof(unsigned int));
1729 
1730  std::memcpy(&size,
1731  &(*dest_sizes_cell_it),
1732  sizeof(unsigned int));
1733 
1734  size -= offset;
1735 
1736  // Move the data iterator to the corresponding position
1737  // of the callback function and adjust the increment
1738  // accordingly.
1739  dest_data_it += offset;
1740  data_increment -= offset;
1741  }
1742 
1743  // Advance data size iterators to the next cell.
1744  dest_sizes_cell_it += sizes_fixed_cumulative.back();
1745  ++dest_sizes_it;
1746  }
1747 
1748  switch (cell_status)
1749  {
1751  spacedim>::CELL_PERSIST:
1753  spacedim>::CELL_COARSEN:
1754  unpack_callback(dealii_cell,
1755  cell_status,
1756  boost::make_iterator_range(dest_data_it,
1757  dest_data_it +
1758  size));
1759  break;
1760 
1762  spacedim>::CELL_REFINE:
1763  unpack_callback(dealii_cell->parent(),
1764  cell_status,
1765  boost::make_iterator_range(dest_data_it,
1766  dest_data_it +
1767  size));
1768  break;
1769 
1771  spacedim>::CELL_INVALID:
1772  // Skip this cell.
1773  break;
1774 
1775  default:
1776  Assert(false, ExcInternalError());
1777  break;
1778  }
1779  }
1780  }
1781 
1782 
1783 
1784  template <int dim, int spacedim>
1785  void
1787  const typename ::internal::p4est::types<dim>::forest
1788  * parallel_forest,
1789  const char *filename) const
1790  {
1791  // Large fractions of this function have been copied from
1792  // DataOutInterface::write_vtu_in_parallel.
1793  // TODO: Write general MPIIO interface.
1794 
1795  Assert(sizes_fixed_cumulative.size() > 0,
1796  ExcMessage("No data has been packed!"));
1797 
1798  const int myrank = Utilities::MPI::this_mpi_process(mpi_communicator);
1799 
1800  //
1801  // ---------- Fixed size data ----------
1802  //
1803  {
1804  const std::string fname_fixed = std::string(filename) + "_fixed.data";
1805 
1806  MPI_Info info;
1807  int ierr = MPI_Info_create(&info);
1808  AssertThrowMPI(ierr);
1809 
1810  MPI_File fh;
1811  ierr = MPI_File_open(mpi_communicator,
1812  fname_fixed.c_str(),
1813  MPI_MODE_CREATE | MPI_MODE_WRONLY,
1814  info,
1815  &fh);
1816  AssertThrowMPI(ierr);
1817 
1818  ierr = MPI_File_set_size(fh, 0); // delete the file contents
1819  AssertThrowMPI(ierr);
1820  // this barrier is necessary, because otherwise others might already
1821  // write while one core is still setting the size to zero.
1822  ierr = MPI_Barrier(mpi_communicator);
1823  AssertThrowMPI(ierr);
1824  ierr = MPI_Info_free(&info);
1825  AssertThrowMPI(ierr);
1826  // ------------------
1827 
1828  // Check if number of processors is lined up with p4est partitioning.
1829  Assert(myrank < parallel_forest->mpisize, ExcInternalError());
1830 
1831  // Write cumulative sizes to file.
1832  // Since each processor owns the same information about the data sizes,
1833  // it is sufficient to let only the first processor perform this task.
1834  if (myrank == 0)
1835  {
1836  ierr = MPI_File_write_at(fh,
1837  0,
1838  sizes_fixed_cumulative.data(),
1839  sizes_fixed_cumulative.size(),
1840  MPI_UNSIGNED,
1841  MPI_STATUS_IGNORE);
1842  AssertThrowMPI(ierr);
1843  }
1844 
1845  // Write packed data to file simultaneously.
1846  const unsigned int offset_fixed =
1847  sizes_fixed_cumulative.size() * sizeof(unsigned int);
1848 
1849  ierr = MPI_File_write_at(
1850  fh,
1851  offset_fixed +
1852  parallel_forest->global_first_quadrant[myrank] *
1853  sizes_fixed_cumulative.back(), // global position in file
1854  src_data_fixed.data(),
1855  src_data_fixed.size(), // local buffer
1856  MPI_CHAR,
1857  MPI_STATUS_IGNORE);
1858  AssertThrowMPI(ierr);
1859 
1860  ierr = MPI_File_close(&fh);
1861  AssertThrowMPI(ierr);
1862  }
1863 
1864  //
1865  // ---------- Variable size data ----------
1866  //
1867  if (variable_size_data_stored)
1868  {
1869  const std::string fname_variable =
1870  std::string(filename) + "_variable.data";
1871 
1872  const int n_procs = Utilities::MPI::n_mpi_processes(mpi_communicator);
1873 
1874  MPI_Info info;
1875  int ierr = MPI_Info_create(&info);
1876  AssertThrowMPI(ierr);
1877 
1878  MPI_File fh;
1879  ierr = MPI_File_open(mpi_communicator,
1880  fname_variable.c_str(),
1881  MPI_MODE_CREATE | MPI_MODE_WRONLY,
1882  info,
1883  &fh);
1884  AssertThrowMPI(ierr);
1885 
1886  ierr = MPI_File_set_size(fh, 0); // delete the file contents
1887  AssertThrowMPI(ierr);
1888  // this barrier is necessary, because otherwise others might already
1889  // write while one core is still setting the size to zero.
1890  ierr = MPI_Barrier(mpi_communicator);
1891  AssertThrowMPI(ierr);
1892  ierr = MPI_Info_free(&info);
1893  AssertThrowMPI(ierr);
1894 
1895  // Write sizes of each cell into file simultaneously.
1896  ierr =
1897  MPI_File_write_at(fh,
1898  parallel_forest->global_first_quadrant[myrank] *
1899  sizeof(int), // global position in file
1900  src_sizes_variable.data(),
1901  src_sizes_variable.size(), // local buffer
1902  MPI_INT,
1903  MPI_STATUS_IGNORE);
1904  AssertThrowMPI(ierr);
1905 
1906  const unsigned int offset_variable =
1907  parallel_forest->global_num_quadrants * sizeof(int);
1908 
1909  // Gather size of data in bytes we want to store from this processor.
1910  const unsigned int size_on_proc = src_data_variable.size();
1911 
1912  // Share information among all processors.
1913  std::vector<unsigned int> sizes_on_all_procs(n_procs);
1914  ierr = MPI_Allgather(&size_on_proc,
1915  1,
1916  MPI_UNSIGNED,
1917  sizes_on_all_procs.data(),
1918  1,
1919  MPI_UNSIGNED,
1920  mpi_communicator);
1921  AssertThrowMPI(ierr);
1922 
1923  // Generate accumulated sum to get an offset for writing variable
1924  // size data.
1925  std::partial_sum(sizes_on_all_procs.begin(),
1926  sizes_on_all_procs.end(),
1927  sizes_on_all_procs.begin());
1928 
1929  // Write data consecutively into file.
1930  ierr = MPI_File_write_at(
1931  fh,
1932  offset_variable +
1933  ((myrank == 0) ?
1934  0 :
1935  sizes_on_all_procs[myrank - 1]), // global position in file
1936  src_data_variable.data(),
1937  src_data_variable.size(), // local buffer
1938  MPI_CHAR,
1939  MPI_STATUS_IGNORE);
1940  AssertThrowMPI(ierr);
1941 
1942  ierr = MPI_File_close(&fh);
1943  AssertThrowMPI(ierr);
1944  }
1945  }
1946 
1947 
1948 
1949  template <int dim, int spacedim>
1950  void
1952  const typename ::internal::p4est::types<dim>::forest
1953  * parallel_forest,
1954  const char * filename,
1955  const unsigned int n_attached_deserialize_fixed,
1956  const unsigned int n_attached_deserialize_variable)
1957  {
1958  // Large fractions of this function have been copied from
1959  // DataOutInterface::write_vtu_in_parallel.
1960  // TODO: Write general MPIIO interface.
1961 
1962  Assert(dest_data_fixed.size() == 0,
1963  ExcMessage("Previously loaded data has not been released yet!"));
1964 
1965  variable_size_data_stored = (n_attached_deserialize_variable > 0);
1966 
1967  const int myrank = Utilities::MPI::this_mpi_process(mpi_communicator);
1968 
1969  //
1970  // ---------- Fixed size data ----------
1971  //
1972  {
1973  const std::string fname_fixed = std::string(filename) + "_fixed.data";
1974 
1975  MPI_Info info;
1976  int ierr = MPI_Info_create(&info);
1977  AssertThrowMPI(ierr);
1978 
1979  MPI_File fh;
1980  ierr = MPI_File_open(
1981  mpi_communicator, fname_fixed.c_str(), MPI_MODE_RDONLY, info, &fh);
1982  AssertThrowMPI(ierr);
1983 
1984  ierr = MPI_Info_free(&info);
1985  AssertThrowMPI(ierr);
1986 
1987  // Check if number of processors is lined up with p4est partitioning.
1988  Assert(myrank < parallel_forest->mpisize, ExcInternalError());
1989 
1990  // Read cumulative sizes from file.
1991  // Since all processors need the same information about the data sizes,
1992  // let each of them retrieve it by reading from the same location in
1993  // the file.
1994  sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1995  (variable_size_data_stored ? 1 : 0));
1996  ierr = MPI_File_read_at(fh,
1997  0,
1998  sizes_fixed_cumulative.data(),
1999  sizes_fixed_cumulative.size(),
2000  MPI_UNSIGNED,
2001  MPI_STATUS_IGNORE);
2002  AssertThrowMPI(ierr);
2003 
2004  // Allocate sufficient memory.
2005  dest_data_fixed.resize(parallel_forest->local_num_quadrants *
2006  sizes_fixed_cumulative.back());
2007 
2008  // Read packed data from file simultaneously.
2009  const unsigned int offset =
2010  sizes_fixed_cumulative.size() * sizeof(unsigned int);
2011 
2012  ierr = MPI_File_read_at(
2013  fh,
2014  offset + parallel_forest->global_first_quadrant[myrank] *
2015  sizes_fixed_cumulative.back(), // global position in file
2016  dest_data_fixed.data(),
2017  dest_data_fixed.size(), // local buffer
2018  MPI_CHAR,
2019  MPI_STATUS_IGNORE);
2020  AssertThrowMPI(ierr);
2021 
2022  ierr = MPI_File_close(&fh);
2023  AssertThrowMPI(ierr);
2024  }
2025 
2026  //
2027  // ---------- Variable size data ----------
2028  //
2029  if (variable_size_data_stored)
2030  {
2031  const std::string fname_variable =
2032  std::string(filename) + "_variable.data";
2033 
2034  const int n_procs = Utilities::MPI::n_mpi_processes(mpi_communicator);
2035 
2036  MPI_Info info;
2037  int ierr = MPI_Info_create(&info);
2038  AssertThrowMPI(ierr);
2039 
2040  MPI_File fh;
2041  ierr = MPI_File_open(mpi_communicator,
2042  fname_variable.c_str(),
2043  MPI_MODE_RDONLY,
2044  info,
2045  &fh);
2046  AssertThrowMPI(ierr);
2047 
2048  ierr = MPI_Info_free(&info);
2049  AssertThrowMPI(ierr);
2050 
2051  // Read sizes of all locally owned cells.
2052  dest_sizes_variable.resize(parallel_forest->local_num_quadrants);
2053  ierr =
2054  MPI_File_read_at(fh,
2055  parallel_forest->global_first_quadrant[myrank] *
2056  sizeof(int),
2057  dest_sizes_variable.data(),
2058  dest_sizes_variable.size(),
2059  MPI_INT,
2060  MPI_STATUS_IGNORE);
2061  AssertThrowMPI(ierr);
2062 
2063  const unsigned int offset =
2064  parallel_forest->global_num_quadrants * sizeof(int);
2065 
2066  const unsigned int size_on_proc =
2067  std::accumulate(dest_sizes_variable.begin(),
2068  dest_sizes_variable.end(),
2069  0);
2070 
2071  // share information among all processors
2072  std::vector<unsigned int> sizes_on_all_procs(n_procs);
2073  ierr = MPI_Allgather(&size_on_proc,
2074  1,
2075  MPI_UNSIGNED,
2076  sizes_on_all_procs.data(),
2077  1,
2078  MPI_UNSIGNED,
2079  mpi_communicator);
2080  AssertThrowMPI(ierr);
2081 
2082  // generate accumulated sum
2083  std::partial_sum(sizes_on_all_procs.begin(),
2084  sizes_on_all_procs.end(),
2085  sizes_on_all_procs.begin());
2086 
2087  dest_data_variable.resize(size_on_proc);
2088  ierr = MPI_File_read_at(fh,
2089  offset + ((myrank == 0) ?
2090  0 :
2091  sizes_on_all_procs[myrank - 1]),
2092  dest_data_variable.data(),
2093  dest_data_variable.size(),
2094  MPI_CHAR,
2095  MPI_STATUS_IGNORE);
2096  AssertThrowMPI(ierr);
2097 
2098  ierr = MPI_File_close(&fh);
2099  AssertThrowMPI(ierr);
2100  }
2101  }
2102 
2103 
2104 
2105  template <int dim, int spacedim>
2106  void
2108  {
2109  variable_size_data_stored = false;
2110 
2111  // free information about data sizes
2112  sizes_fixed_cumulative.clear();
2113  sizes_fixed_cumulative.shrink_to_fit();
2114 
2115  // free fixed size transfer data
2116  src_data_fixed.clear();
2117  src_data_fixed.shrink_to_fit();
2118 
2119  dest_data_fixed.clear();
2120  dest_data_fixed.shrink_to_fit();
2121 
2122  // free variable size transfer data
2123  src_sizes_variable.clear();
2124  src_sizes_variable.shrink_to_fit();
2125 
2126  src_data_variable.clear();
2127  src_data_variable.shrink_to_fit();
2128 
2129  dest_sizes_variable.clear();
2130  dest_sizes_variable.shrink_to_fit();
2131 
2132  dest_data_variable.clear();
2133  dest_data_variable.shrink_to_fit();
2134  }
2135 
2136 
2137 
2138  /* ----------------- class Triangulation<dim,spacedim> ----------------- */
2139 
2140 
2141  template <int dim, int spacedim>
2143  MPI_Comm mpi_communicator,
2144  const typename ::Triangulation<dim, spacedim>::MeshSmoothing
2145  smooth_grid,
2146  const Settings settings_)
2147  : // Do not check for distorted cells.
2148  // For multigrid, we need limit_level_difference_at_vertices
2149  // to make sure the transfer operators only need to consider two levels.
2150  ::parallel::Triangulation<dim, spacedim>(
2151  mpi_communicator,
2152  (settings_ & construct_multigrid_hierarchy) ?
2153  static_cast<
2154  typename ::Triangulation<dim, spacedim>::MeshSmoothing>(
2155  smooth_grid |
2156  Triangulation<dim, spacedim>::limit_level_difference_at_vertices) :
2157  smooth_grid,
2158  false)
2159  , settings(settings_)
2160  , triangulation_has_content(false)
2161  , connectivity(nullptr)
2162  , parallel_forest(nullptr)
2163  , cell_attached_data({0, 0, {}, {}})
2164  , data_transfer(mpi_communicator)
2165  {
2166  parallel_ghost = nullptr;
2167  }
2168 
2169 
2170 
2171  template <int dim, int spacedim>
2173  {
2174  // virtual functions called in constructors and destructors never use the
2175  // override in a derived class
2176  // for clarity be explicit on which function is called
2177  try
2178  {
2180  }
2181  catch (...)
2182  {}
2183 
2185  AssertNothrow(connectivity == nullptr, ExcInternalError());
2186  AssertNothrow(parallel_forest == nullptr, ExcInternalError());
2187  }
2188 
2189 
2190 
2191  template <int dim, int spacedim>
2192  void
2194  const std::vector<Point<spacedim>> &vertices,
2195  const std::vector<CellData<dim>> & cells,
2196  const SubCellData & subcelldata)
2197  {
2198  try
2199  {
2201  vertices, cells, subcelldata);
2202  }
2203  catch (
2204  const typename ::Triangulation<dim, spacedim>::DistortedCellList
2205  &)
2206  {
2207  // the underlying triangulation should not be checking for distorted
2208  // cells
2209  Assert(false, ExcInternalError());
2210  }
2211 
2212  // note that now we have some content in the p4est objects and call the
2213  // functions that do the actual work (which are dimension dependent, so
2214  // separate)
2216 
2218 
2219  copy_new_triangulation_to_p4est(std::integral_constant<int, dim>());
2220 
2221  try
2222  {
2224  }
2225  catch (const typename Triangulation<dim>::DistortedCellList &)
2226  {
2227  // the underlying triangulation should not be checking for distorted
2228  // cells
2229  Assert(false, ExcInternalError());
2230  }
2231 
2232  this->update_number_cache();
2233  this->update_periodic_face_map();
2234  }
2235 
2236 
2237  // This anonymous namespace contains utility for
2238  // the function Triangulation::communicate_locally_moved_vertices
2239  namespace CommunicateLocallyMovedVertices
2240  {
2241  namespace
2242  {
2248  template <int dim, int spacedim>
2249  struct CellInfo
2250  {
2251  // store all the tree_indices we send/receive consecutively (n_cells
2252  // entries)
2253  std::vector<unsigned int> tree_index;
2254  // store all the quadrants we send/receive consecutively (n_cells
2255  // entries)
2256  std::vector<typename ::internal::p4est::types<dim>::quadrant>
2257  quadrants;
2258  // store for each cell the number of vertices we send/receive
2259  // and then the vertex indices (for each cell: n_vertices+1 entries)
2260  std::vector<unsigned int> vertex_indices;
2261  // store for each cell the vertices we send/receive
2262  // (for each cell n_vertices entries)
2263  std::vector<::Point<spacedim>> vertices;
2264  // for receiving and unpacking data we need to store pointers to the
2265  // first vertex and vertex_index on each cell additionally
2266  // both vectors have as many entries as there are cells
2267  std::vector<unsigned int *> first_vertex_indices;
2268  std::vector<::Point<spacedim> *> first_vertices;
2269 
2270  unsigned int
2271  bytes_for_buffer() const
2272  {
2273  return sizeof(unsigned int) +
2274  tree_index.size() * sizeof(unsigned int) +
2275  quadrants.size() *
2276  sizeof(typename ::internal::p4est ::types<
2277  dim>::quadrant) +
2278  vertex_indices.size() * sizeof(unsigned int) +
2279  vertices.size() * sizeof(::Point<spacedim>);
2280  }
2281 
2282  void
2283  pack_data(std::vector<char> &buffer) const
2284  {
2285  buffer.resize(bytes_for_buffer());
2286 
2287  char *ptr = buffer.data();
2288 
2289  const unsigned int num_cells = tree_index.size();
2290  std::memcpy(ptr, &num_cells, sizeof(unsigned int));
2291  ptr += sizeof(unsigned int);
2292 
2293  std::memcpy(ptr,
2294  tree_index.data(),
2295  num_cells * sizeof(unsigned int));
2296  ptr += num_cells * sizeof(unsigned int);
2297 
2298  std::memcpy(
2299  ptr,
2300  quadrants.data(),
2301  num_cells *
2302  sizeof(typename ::internal::p4est::types<dim>::quadrant));
2303  ptr +=
2304  num_cells *
2305  sizeof(typename ::internal::p4est::types<dim>::quadrant);
2306 
2307  std::memcpy(ptr,
2308  vertex_indices.data(),
2309  vertex_indices.size() * sizeof(unsigned int));
2310  ptr += vertex_indices.size() * sizeof(unsigned int);
2311  std::memcpy(ptr,
2312  vertices.data(),
2313  vertices.size() * sizeof(::Point<spacedim>));
2314  ptr += vertices.size() * sizeof(::Point<spacedim>);
2315 
2316  Assert(ptr == buffer.data() + buffer.size(), ExcInternalError());
2317  }
2318 
2319  void
2320  unpack_data(const std::vector<char> &buffer)
2321  {
2322  const char * ptr = buffer.data();
2323  unsigned int cells;
2324  memcpy(&cells, ptr, sizeof(unsigned int));
2325  ptr += sizeof(unsigned int);
2326 
2327  tree_index.resize(cells);
2328  memcpy(tree_index.data(), ptr, sizeof(unsigned int) * cells);
2329  ptr += sizeof(unsigned int) * cells;
2330 
2331  quadrants.resize(cells);
2332  memcpy(quadrants.data(),
2333  ptr,
2334  sizeof(
2335  typename ::internal::p4est::types<dim>::quadrant) *
2336  cells);
2337  ptr +=
2338  sizeof(typename ::internal::p4est::types<dim>::quadrant) *
2339  cells;
2340 
2341  vertex_indices.clear();
2342  first_vertex_indices.resize(cells);
2343  std::vector<unsigned int> n_vertices_on_cell(cells);
2344  std::vector<unsigned int> first_indices(cells);
2345  for (unsigned int c = 0; c < cells; ++c)
2346  {
2347  // The first 'vertex index' is the number of vertices.
2348  // Additionally, we need to store the pointer to this
2349  // vertex index with respect to the std::vector
2350  const unsigned int *const vertex_index =
2351  reinterpret_cast<const unsigned int *>(ptr);
2352  first_indices[c] = vertex_indices.size();
2353  vertex_indices.push_back(*vertex_index);
2354  n_vertices_on_cell[c] = *vertex_index;
2355  ptr += sizeof(unsigned int);
2356  // Now copy all the 'real' vertex_indices
2357  vertex_indices.resize(vertex_indices.size() +
2358  n_vertices_on_cell[c]);
2359  memcpy(&vertex_indices[vertex_indices.size() -
2360  n_vertices_on_cell[c]],
2361  ptr,
2362  n_vertices_on_cell[c] * sizeof(unsigned int));
2363  ptr += n_vertices_on_cell[c] * sizeof(unsigned int);
2364  }
2365  for (unsigned int c = 0; c < cells; ++c)
2366  first_vertex_indices[c] = &vertex_indices[first_indices[c]];
2367 
2368  vertices.clear();
2369  first_vertices.resize(cells);
2370  for (unsigned int c = 0; c < cells; ++c)
2371  {
2372  first_indices[c] = vertices.size();
2373  vertices.resize(vertices.size() + n_vertices_on_cell[c]);
2374  memcpy(&vertices[vertices.size() - n_vertices_on_cell[c]],
2375  ptr,
2376  n_vertices_on_cell[c] * sizeof(::Point<spacedim>));
2377  ptr += n_vertices_on_cell[c] * sizeof(::Point<spacedim>);
2378  }
2379  for (unsigned int c = 0; c < cells; ++c)
2380  first_vertices[c] = &vertices[first_indices[c]];
2381 
2382  Assert(ptr == buffer.data() + buffer.size(), ExcInternalError());
2383  }
2384  };
2385 
2386 
2387 
2388  // This function is responsible for gathering the information
2389  // we want to send to each process.
2390  // For each dealii cell on the coarsest level the corresponding
2391  // p4est_cell has to be provided when calling this function.
2392  // By recursing through all children we consider each active cell.
2393  // vertices_with_ghost_neighbors tells us which vertices
2394  // are in the ghost layer and for which processes they might
2395  // be interesting.
2396  // Whether a vertex has actually been updated locally is
2397  // stored in vertex_locally_moved. Only those are considered
2398  // for sending.
2399  // The gathered information is saved into needs_to_get_cell.
2400  template <int dim, int spacedim>
2401  void
2402  fill_vertices_recursively(
2404  & tria,
2405  const unsigned int tree_index,
2407  &dealii_cell,
2408  const typename ::internal::p4est::types<dim>::quadrant
2409  &p4est_cell,
2410  const std::map<unsigned int, std::set<::types::subdomain_id>>
2411  & vertices_with_ghost_neighbors,
2412  const std::vector<bool> &vertex_locally_moved,
2413  std::map<::types::subdomain_id, CellInfo<dim, spacedim>>
2414  &needs_to_get_cell)
2415  {
2416  // see if we have to
2417  // recurse...
2418  if (dealii_cell->has_children())
2419  {
2420  typename ::internal::p4est::types<dim>::quadrant
2422  ::internal::p4est::init_quadrant_children<dim>(p4est_cell,
2423  p4est_child);
2424 
2425 
2426  for (unsigned int c = 0;
2427  c < GeometryInfo<dim>::max_children_per_cell;
2428  ++c)
2429  fill_vertices_recursively<dim, spacedim>(
2430  tria,
2431  tree_index,
2432  dealii_cell->child(c),
2433  p4est_child[c],
2434  vertices_with_ghost_neighbors,
2435  vertex_locally_moved,
2436  needs_to_get_cell);
2437  return;
2438  }
2439 
2440  // We're at a leaf cell. If the cell is locally owned, we may
2441  // have to send its vertices to other processors if any of
2442  // its vertices is adjacent to a ghost cell and has been moved
2443  //
2444  // If one of the vertices of the cell is interesting,
2445  // send all moved vertices of the cell to all processors
2446  // adjacent to all cells adjacent to this vertex
2447  if (dealii_cell->is_locally_owned())
2448  {
2449  std::set<::types::subdomain_id> send_to;
2450  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
2451  ++v)
2452  {
2453  const std::map<unsigned int,
2454  std::set<::types::subdomain_id>>::
2455  const_iterator neighbor_subdomains_of_vertex =
2456  vertices_with_ghost_neighbors.find(
2457  dealii_cell->vertex_index(v));
2458 
2459  if (neighbor_subdomains_of_vertex !=
2460  vertices_with_ghost_neighbors.end())
2461  {
2462  Assert(neighbor_subdomains_of_vertex->second.size() != 0,
2463  ExcInternalError());
2464  send_to.insert(
2465  neighbor_subdomains_of_vertex->second.begin(),
2466  neighbor_subdomains_of_vertex->second.end());
2467  }
2468  }
2469 
2470  if (send_to.size() > 0)
2471  {
2472  std::vector<unsigned int> vertex_indices;
2473  std::vector<::Point<spacedim>> local_vertices;
2474  for (unsigned int v = 0;
2475  v < GeometryInfo<dim>::vertices_per_cell;
2476  ++v)
2477  if (vertex_locally_moved[dealii_cell->vertex_index(v)])
2478  {
2479  vertex_indices.push_back(v);
2480  local_vertices.push_back(dealii_cell->vertex(v));
2481  }
2482 
2483  if (vertex_indices.size() > 0)
2484  for (std::set<::types::subdomain_id>::iterator it =
2485  send_to.begin();
2486  it != send_to.end();
2487  ++it)
2488  {
2489  const ::types::subdomain_id subdomain = *it;
2490 
2491  // get an iterator to what needs to be sent to that
2492  // subdomain (if already exists), or create such an
2493  // object
2494  const typename std::map<
2496  CellInfo<dim, spacedim>>::iterator p =
2497  needs_to_get_cell
2498  .insert(std::make_pair(subdomain,
2499  CellInfo<dim, spacedim>()))
2500  .first;
2501 
2502  p->second.tree_index.push_back(tree_index);
2503  p->second.quadrants.push_back(p4est_cell);
2504 
2505  p->second.vertex_indices.push_back(
2506  vertex_indices.size());
2507  p->second.vertex_indices.insert(
2508  p->second.vertex_indices.end(),
2509  vertex_indices.begin(),
2510  vertex_indices.end());
2511 
2512  p->second.vertices.insert(p->second.vertices.end(),
2513  local_vertices.begin(),
2514  local_vertices.end());
2515  }
2516  }
2517  }
2518  }
2519 
2520 
2521 
2522  // After the cell data has been received this function is responsible
2523  // for moving the vertices in the corresponding ghost layer locally.
2524  // As in fill_vertices_recursively for each dealii cell on the
2525  // coarsest level the corresponding p4est_cell has to be provided
2526  // when calling this function. By recursing through through all
2527  // children we consider each active cell.
2528  // Additionally, we need to give a pointer to the first vertex indices
2529  // and vertices. Since the first information saved in vertex_indices
2530  // is the number of vertices this all the information we need.
2531  template <int dim, int spacedim>
2532  void
2533  set_vertices_recursively(
2535  const typename ::internal::p4est::types<dim>::quadrant
2536  &p4est_cell,
2538  &dealii_cell,
2539  const typename ::internal::p4est::types<dim>::quadrant
2540  & quadrant,
2541  const ::Point<spacedim> *const vertices,
2542  const unsigned int *const vertex_indices)
2543  {
2544  if (::internal::p4est::quadrant_is_equal<dim>(p4est_cell,
2545  quadrant))
2546  {
2547  Assert(!dealii_cell->is_artificial(), ExcInternalError());
2548  Assert(!dealii_cell->has_children(), ExcInternalError());
2549  Assert(!dealii_cell->is_locally_owned(), ExcInternalError());
2550 
2551  const unsigned int n_vertices = vertex_indices[0];
2552 
2553  // update dof indices of cell
2554  for (unsigned int i = 0; i < n_vertices; ++i)
2555  dealii_cell->vertex(vertex_indices[i + 1]) = vertices[i];
2556 
2557  return;
2558  }
2559 
2560  if (!dealii_cell->has_children())
2561  return;
2562 
2563  if (!::internal::p4est::quadrant_is_ancestor<dim>(p4est_cell,
2564  quadrant))
2565  return;
2566 
2567  typename ::internal::p4est::types<dim>::quadrant
2569  ::internal::p4est::init_quadrant_children<dim>(p4est_cell,
2570  p4est_child);
2571 
2572  for (unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell;
2573  ++c)
2574  set_vertices_recursively<dim, spacedim>(tria,
2575  p4est_child[c],
2576  dealii_cell->child(c),
2577  quadrant,
2578  vertices,
2579  vertex_indices);
2580  }
2581  } // namespace
2582  } // namespace CommunicateLocallyMovedVertices
2583 
2584 
2585 
2586  template <int dim, int spacedim>
2587  void
2589  {
2590  triangulation_has_content = false;
2591 
2592  cell_attached_data = {0, 0, {}, {}};
2593  data_transfer.clear();
2594 
2595  if (parallel_ghost != nullptr)
2596  {
2598  parallel_ghost);
2599  parallel_ghost = nullptr;
2600  }
2601 
2602  if (parallel_forest != nullptr)
2603  {
2605  parallel_forest = nullptr;
2606  }
2607 
2608  if (connectivity != nullptr)
2609  {
2611  connectivity);
2612  connectivity = nullptr;
2613  }
2614 
2615  coarse_cell_to_p4est_tree_permutation.resize(0);
2616  p4est_tree_to_coarse_cell_permutation.resize(0);
2617 
2619 
2620  this->update_number_cache();
2621  }
2622 
2623 
2624 
2625  template <int dim, int spacedim>
2626  bool
2628  {
2629  if (this->n_global_levels() <= 1)
2630  return false; // can not have hanging nodes without refined cells
2631 
2632  // if there are any active cells with level less than n_global_levels()-1,
2633  // then there is obviously also one with level n_global_levels()-1, and
2634  // consequently there must be a hanging node somewhere.
2635  //
2636  // The problem is that we cannot just ask for the first active cell, but
2637  // instead need to filter over locally owned cells.
2638  bool have_coarser_cell = false;
2640  this->begin_active(this->n_global_levels() - 2);
2641  cell != this->end(this->n_global_levels() - 2);
2642  ++cell)
2643  if (cell->is_locally_owned())
2644  {
2645  have_coarser_cell = true;
2646  break;
2647  }
2648 
2649  // return true if at least one process has a coarser cell
2650  return 0 < Utilities::MPI::max(have_coarser_cell ? 1 : 0,
2651  this->mpi_communicator);
2652  }
2653 
2654 
2655 
2656  template <int dim, int spacedim>
2657  void
2659  {
2660  DynamicSparsityPattern cell_connectivity;
2661  ::GridTools::get_vertex_connectivity_of_cells(*this,
2662  cell_connectivity);
2663  coarse_cell_to_p4est_tree_permutation.resize(this->n_cells(0));
2665  cell_connectivity, coarse_cell_to_p4est_tree_permutation);
2666 
2667  p4est_tree_to_coarse_cell_permutation =
2668  Utilities::invert_permutation(coarse_cell_to_p4est_tree_permutation);
2669  }
2670 
2671 
2672 
2673  template <int dim, int spacedim>
2674  void
2676  const char *file_basename) const
2677  {
2678  Assert(parallel_forest != nullptr,
2679  ExcMessage("Can't produce output when no forest is created yet."));
2681  nullptr,
2682  file_basename);
2683  }
2684 
2685 
2686 
2687  template <int dim, int spacedim>
2688  void
2689  Triangulation<dim, spacedim>::save(const char *filename) const
2690  {
2691  Assert(
2692  cell_attached_data.n_attached_deserialize == 0,
2693  ExcMessage(
2694  "not all SolutionTransfer's got deserialized after the last load()"));
2695  Assert(this->n_cells() > 0,
2696  ExcMessage("Can not save() an empty Triangulation."));
2697 
2698  // signal that serialization is going to happen
2699  this->signals.pre_distributed_save();
2700 
2701  if (this->my_subdomain == 0)
2702  {
2703  std::string fname = std::string(filename) + ".info";
2704  std::ofstream f(fname.c_str());
2705  f << "version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_coarse_cells"
2706  << std::endl
2707  << 4 << " "
2709  << cell_attached_data.pack_callbacks_fixed.size() << " "
2710  << cell_attached_data.pack_callbacks_variable.size() << " "
2711  << this->n_cells(0) << std::endl;
2712  }
2713 
2714  // each cell should have been flagged `CELL_PERSIST`
2715  for (const auto &quad_cell_rel : local_quadrant_cell_relations)
2716  {
2717  (void)quad_cell_rel;
2718  Assert(
2719  (std::get<1>(quad_cell_rel) == // cell_status
2721  ExcInternalError());
2722  }
2723 
2724  if (cell_attached_data.n_attached_data_sets > 0)
2725  {
2726  // cast away constness
2727  auto tria = const_cast<
2729  this);
2730 
2731  // pack attached data first
2732  tria->data_transfer.pack_data(
2733  local_quadrant_cell_relations,
2734  cell_attached_data.pack_callbacks_fixed,
2735  cell_attached_data.pack_callbacks_variable);
2736 
2737  // then store buffers in file
2738  tria->data_transfer.save(parallel_forest, filename);
2739 
2740  // and release the memory afterwards
2741  tria->data_transfer.clear();
2742  }
2743 
2745  parallel_forest,
2746  false);
2747 
2748  // clear all of the callback data, as explained in the documentation of
2749  // register_data_attach()
2750  {
2752  const_cast<
2754  this);
2755 
2756  tria->cell_attached_data.n_attached_data_sets = 0;
2757  tria->cell_attached_data.pack_callbacks_fixed.clear();
2758  }
2759  }
2760 
2761 
2762 
2763  template <int dim, int spacedim>
2764  void
2766  const bool autopartition)
2767  {
2768  Assert(
2769  this->n_cells() > 0,
2770  ExcMessage(
2771  "load() only works if the Triangulation already contains a coarse mesh!"));
2772  Assert(
2773  this->n_levels() == 1,
2774  ExcMessage(
2775  "Triangulation may only contain coarse cells when calling load()."));
2776 
2777 
2778  if (parallel_ghost != nullptr)
2779  {
2781  parallel_ghost);
2782  parallel_ghost = nullptr;
2783  }
2785  parallel_forest = nullptr;
2787  connectivity);
2788  connectivity = nullptr;
2789 
2790  unsigned int version, numcpus, attached_count_fixed,
2791  attached_count_variable, n_coarse_cells;
2792  {
2793  std::string fname = std::string(filename) + ".info";
2794  std::ifstream f(fname.c_str());
2795  AssertThrow(f, ExcIO());
2796  std::string firstline;
2797  getline(f, firstline); // skip first line
2798  f >> version >> numcpus >> attached_count_fixed >>
2799  attached_count_variable >> n_coarse_cells;
2800  }
2801 
2802  AssertThrow(version == 4,
2803  ExcMessage("Incompatible version found in .info file."));
2804  Assert(this->n_cells(0) == n_coarse_cells,
2805  ExcMessage("Number of coarse cells differ!"));
2806 
2807  // clear all of the callback data, as explained in the documentation of
2808  // register_data_attach()
2809  cell_attached_data.n_attached_data_sets = 0;
2810  cell_attached_data.n_attached_deserialize =
2811  attached_count_fixed + attached_count_variable;
2812 
2814  filename,
2815  this->mpi_communicator,
2816  0,
2817  false,
2818  autopartition,
2819  0,
2820  this,
2821  &connectivity);
2822 
2823  if (numcpus != Utilities::MPI::n_mpi_processes(this->mpi_communicator))
2824  // We are changing the number of CPUs so we need to repartition.
2825  // Note that p4est actually distributes the cells between the changed
2826  // number of CPUs and so everything works without this call, but
2827  // this command changes the distribution for some reason, so we
2828  // will leave it in here.
2829  repartition();
2830 
2831  try
2832  {
2834  }
2835  catch (const typename Triangulation<dim>::DistortedCellList &)
2836  {
2837  // the underlying
2838  // triangulation should not
2839  // be checking for
2840  // distorted cells
2841  Assert(false, ExcInternalError());
2842  }
2843 
2844  // load saved data, if any was stored
2845  if (cell_attached_data.n_attached_deserialize > 0)
2846  {
2847  data_transfer.load(parallel_forest,
2848  filename,
2849  attached_count_fixed,
2850  attached_count_variable);
2851 
2852  data_transfer.unpack_cell_status(local_quadrant_cell_relations);
2853 
2854  // the CellStatus of all stored cells should always be CELL_PERSIST.
2855  for (const auto &quad_cell_rel : local_quadrant_cell_relations)
2856  {
2857  (void)quad_cell_rel;
2858  Assert(
2859  (std::get<1>(quad_cell_rel) == // cell_status
2861  spacedim>::CELL_PERSIST),
2862  ExcInternalError());
2863  }
2864  }
2865 
2866  this->update_number_cache();
2867 
2868  // signal that de-serialization is finished
2870 
2871  this->update_periodic_face_map();
2872  }
2873 
2874 
2875 
2876  template <int dim, int spacedim>
2877  unsigned int
2879  {
2880  Assert(parallel_forest != nullptr,
2881  ExcMessage(
2882  "Can't produce a check sum when no forest is created yet."));
2883  return ::internal::p4est::functions<dim>::checksum(parallel_forest);
2884  }
2885 
2886 
2887 
2888  template <int dim, int spacedim>
2889  void
2891  {
2893 
2896  }
2897 
2898 
2899 
2900  template <int dim, int spacedim>
2901  typename ::internal::p4est::types<dim>::tree *
2903  const int dealii_coarse_cell_index) const
2904  {
2905  const unsigned int tree_index =
2906  coarse_cell_to_p4est_tree_permutation[dealii_coarse_cell_index];
2907  typename ::internal::p4est::types<dim>::tree *tree =
2908  static_cast<typename ::internal::p4est::types<dim>::tree *>(
2909  sc_array_index(parallel_forest->trees, tree_index));
2910 
2911  return tree;
2912  }
2913 
2914 
2915 
2916  template <>
2917  void
2919  std::integral_constant<int, 2>)
2920  {
2921  const unsigned int dim = 2, spacedim = 2;
2922  Assert(this->n_cells(0) > 0, ExcInternalError());
2923  Assert(this->n_levels() == 1, ExcInternalError());
2924 
2925  // data structures that counts how many cells touch each vertex
2926  // (vertex_touch_count), and which cells touch a given vertex (together
2927  // with the local numbering of that vertex within the cells that touch
2928  // it)
2929  std::vector<unsigned int> vertex_touch_count;
2930  std::vector<
2931  std::list<std::pair<Triangulation<dim, spacedim>::active_cell_iterator,
2932  unsigned int>>>
2933  vertex_to_cell;
2934  get_vertex_to_cell_mappings(*this, vertex_touch_count, vertex_to_cell);
2935  const ::internal::p4est::types<2>::locidx num_vtt =
2936  std::accumulate(vertex_touch_count.begin(),
2937  vertex_touch_count.end(),
2938  0u);
2939 
2940  // now create a connectivity object with the right sizes for all
2941  // arrays. set vertex information only in debug mode (saves a few bytes
2942  // in optimized mode)
2943  const bool set_vertex_info
2944 # ifdef DEBUG
2945  = true
2946 # else
2947  = false
2948 # endif
2949  ;
2950 
2952  (set_vertex_info == true ? this->n_vertices() : 0),
2953  this->n_cells(0),
2954  this->n_vertices(),
2955  num_vtt);
2956 
2957  set_vertex_and_cell_info(*this,
2958  vertex_touch_count,
2959  vertex_to_cell,
2960  coarse_cell_to_p4est_tree_permutation,
2961  set_vertex_info,
2962  connectivity);
2963 
2964  Assert(p4est_connectivity_is_valid(connectivity) == 1,
2965  ExcInternalError());
2966 
2967  // now create a forest out of the connectivity data structure
2969  this->mpi_communicator,
2970  connectivity,
2971  /* minimum initial number of quadrants per tree */ 0,
2972  /* minimum level of upfront refinement */ 0,
2973  /* use uniform upfront refinement */ 1,
2974  /* user_data_size = */ 0,
2975  /* user_data_constructor = */ nullptr,
2976  /* user_pointer */ this);
2977  }
2978 
2979 
2980 
2981  // TODO: This is a verbatim copy of the 2,2 case. However, we can't just
2982  // specialize the dim template argument, but let spacedim open
2983  template <>
2984  void
2986  std::integral_constant<int, 2>)
2987  {
2988  const unsigned int dim = 2, spacedim = 3;
2989  Assert(this->n_cells(0) > 0, ExcInternalError());
2990  Assert(this->n_levels() == 1, ExcInternalError());
2991 
2992  // data structures that counts how many cells touch each vertex
2993  // (vertex_touch_count), and which cells touch a given vertex (together
2994  // with the local numbering of that vertex within the cells that touch
2995  // it)
2996  std::vector<unsigned int> vertex_touch_count;
2997  std::vector<
2998  std::list<std::pair<Triangulation<dim, spacedim>::active_cell_iterator,
2999  unsigned int>>>
3000  vertex_to_cell;
3001  get_vertex_to_cell_mappings(*this, vertex_touch_count, vertex_to_cell);
3002  const ::internal::p4est::types<2>::locidx num_vtt =
3003  std::accumulate(vertex_touch_count.begin(),
3004  vertex_touch_count.end(),
3005  0u);
3006 
3007  // now create a connectivity object with the right sizes for all
3008  // arrays. set vertex information only in debug mode (saves a few bytes
3009  // in optimized mode)
3010  const bool set_vertex_info
3011 # ifdef DEBUG
3012  = true
3013 # else
3014  = false
3015 # endif
3016  ;
3017 
3019  (set_vertex_info == true ? this->n_vertices() : 0),
3020  this->n_cells(0),
3021  this->n_vertices(),
3022  num_vtt);
3023 
3024  set_vertex_and_cell_info(*this,
3025  vertex_touch_count,
3026  vertex_to_cell,
3027  coarse_cell_to_p4est_tree_permutation,
3028  set_vertex_info,
3029  connectivity);
3030 
3031  Assert(p4est_connectivity_is_valid(connectivity) == 1,
3032  ExcInternalError());
3033 
3034  // now create a forest out of the connectivity data structure
3036  this->mpi_communicator,
3037  connectivity,
3038  /* minimum initial number of quadrants per tree */ 0,
3039  /* minimum level of upfront refinement */ 0,
3040  /* use uniform upfront refinement */ 1,
3041  /* user_data_size = */ 0,
3042  /* user_data_constructor = */ nullptr,
3043  /* user_pointer */ this);
3044  }
3045 
3046 
3047 
3048  template <>
3049  void
3051  std::integral_constant<int, 3>)
3052  {
3053  const int dim = 3, spacedim = 3;
3054  Assert(this->n_cells(0) > 0, ExcInternalError());
3055  Assert(this->n_levels() == 1, ExcInternalError());
3056 
3057  // data structures that counts how many cells touch each vertex
3058  // (vertex_touch_count), and which cells touch a given vertex (together
3059  // with the local numbering of that vertex within the cells that touch
3060  // it)
3061  std::vector<unsigned int> vertex_touch_count;
3062  std::vector<std::list<
3063  std::pair<Triangulation<3>::active_cell_iterator, unsigned int>>>
3064  vertex_to_cell;
3065  get_vertex_to_cell_mappings(*this, vertex_touch_count, vertex_to_cell);
3066  const ::internal::p4est::types<2>::locidx num_vtt =
3067  std::accumulate(vertex_touch_count.begin(),
3068  vertex_touch_count.end(),
3069  0u);
3070 
3071  std::vector<unsigned int> edge_touch_count;
3072  std::vector<std::list<
3073  std::pair<Triangulation<3>::active_cell_iterator, unsigned int>>>
3074  edge_to_cell;
3075  get_edge_to_cell_mappings(*this, edge_touch_count, edge_to_cell);
3076  const ::internal::p4est::types<2>::locidx num_ett =
3077  std::accumulate(edge_touch_count.begin(), edge_touch_count.end(), 0u);
3078 
3079  // now create a connectivity object with the right sizes for all arrays
3080  const bool set_vertex_info
3081 # ifdef DEBUG
3082  = true
3083 # else
3084  = false
3085 # endif
3086  ;
3087 
3089  (set_vertex_info == true ? this->n_vertices() : 0),
3090  this->n_cells(0),
3091  this->n_active_lines(),
3092  num_ett,
3093  this->n_vertices(),
3094  num_vtt);
3095 
3096  set_vertex_and_cell_info(*this,
3097  vertex_touch_count,
3098  vertex_to_cell,
3099  coarse_cell_to_p4est_tree_permutation,
3100  set_vertex_info,
3101  connectivity);
3102 
3103  // next to tree-to-edge
3104  // data. note that in p4est lines
3105  // are ordered as follows
3106  // *---3---* *---3---*
3107  // /| | / /|
3108  // 6 | 11 6 7 11
3109  // / 10 | / / |
3110  // * | | *---2---* |
3111  // | *---1---* | | *
3112  // | / / | 9 /
3113  // 8 4 5 8 | 5
3114  // |/ / | |/
3115  // *---0---* *---0---*
3116  // whereas in deal.II they are like this:
3117  // *---7---* *---7---*
3118  // /| | / /|
3119  // 4 | 11 4 5 11
3120  // / 10 | / / |
3121  // * | | *---6---* |
3122  // | *---3---* | | *
3123  // | / / | 9 /
3124  // 8 0 1 8 | 1
3125  // |/ / | |/
3126  // *---2---* *---2---*
3127 
3128  const unsigned int deal_to_p4est_line_index[12] = {
3129  4, 5, 0, 1, 6, 7, 2, 3, 8, 9, 10, 11};
3130 
3132  this->begin_active();
3133  cell != this->end();
3134  ++cell)
3135  {
3136  const unsigned int index =
3137  coarse_cell_to_p4est_tree_permutation[cell->index()];
3138  for (unsigned int e = 0; e < GeometryInfo<3>::lines_per_cell; ++e)
3139  connectivity->tree_to_edge[index * GeometryInfo<3>::lines_per_cell +
3140  deal_to_p4est_line_index[e]] =
3141  cell->line(e)->index();
3142  }
3143 
3144  // now also set edge-to-tree
3145  // information
3146  connectivity->ett_offset[0] = 0;
3147  std::partial_sum(edge_touch_count.begin(),
3148  edge_touch_count.end(),
3149  &connectivity->ett_offset[1]);
3150 
3151  Assert(connectivity->ett_offset[this->n_active_lines()] == num_ett,
3152  ExcInternalError());
3153 
3154  for (unsigned int v = 0; v < this->n_active_lines(); ++v)
3155  {
3156  Assert(edge_to_cell[v].size() == edge_touch_count[v],
3157  ExcInternalError());
3158 
3159  std::list<
3160  std::pair<Triangulation<dim, spacedim>::active_cell_iterator,
3161  unsigned int>>::const_iterator p =
3162  edge_to_cell[v].begin();
3163  for (unsigned int c = 0; c < edge_touch_count[v]; ++c, ++p)
3164  {
3165  connectivity->edge_to_tree[connectivity->ett_offset[v] + c] =
3166  coarse_cell_to_p4est_tree_permutation[p->first->index()];
3167  connectivity->edge_to_edge[connectivity->ett_offset[v] + c] =
3168  deal_to_p4est_line_index[p->second];
3169  }
3170  }
3171 
3172  Assert(p8est_connectivity_is_valid(connectivity) == 1,
3173  ExcInternalError());
3174 
3175  // now create a forest out of the connectivity data structure
3177  this->mpi_communicator,
3178  connectivity,
3179  /* minimum initial number of quadrants per tree */ 0,
3180  /* minimum level of upfront refinement */ 0,
3181  /* use uniform upfront refinement */ 1,
3182  /* user_data_size = */ 0,
3183  /* user_data_constructor = */ nullptr,
3184  /* user_pointer */ this);
3185  }
3186 
3187 
3188 
3189  namespace
3190  {
3191  // ensures the 2:1 mesh balance for periodic boundary conditions in the
3192  // artificial cell layer (the active cells are taken care of by p4est)
3193  template <int dim, int spacedim>
3194  bool
3195  enforce_mesh_balance_over_periodic_boundaries(
3197  {
3198  if (tria.get_periodic_face_map().size() == 0)
3199  return false;
3200 
3201  std::vector<bool> flags_before[2];
3202  tria.save_coarsen_flags(flags_before[0]);
3203  tria.save_refine_flags(flags_before[1]);
3204 
3205  std::vector<unsigned int> topological_vertex_numbering(
3206  tria.n_vertices());
3207  for (unsigned int i = 0; i < topological_vertex_numbering.size(); ++i)
3208  topological_vertex_numbering[i] = i;
3209  // combine vertices that have different locations (and thus, different
3210  // vertex_index) but represent the same topological entity over periodic
3211  // boundaries. The vector topological_vertex_numbering contains a linear
3212  // map from 0 to n_vertices at input and at output relates periodic
3213  // vertices with only one vertex index. The output is used to always
3214  // identify the same vertex according to the periodicity, e.g. when
3215  // finding the maximum cell level around a vertex.
3216  //
3217  // Example: On a 3D cell with vertices numbered from 0 to 7 and periodic
3218  // boundary conditions in x direction, the vector
3219  // topological_vertex_numbering will contain the numbers
3220  // {0,0,2,2,4,4,6,6} (because the vertex pairs {0,1}, {2,3}, {4,5},
3221  // {6,7} belong together, respectively). If periodicity is set in x and
3222  // z direction, the output is {0,0,2,2,0,0,2,2}, and if periodicity is
3223  // in all directions, the output is simply {0,0,0,0,0,0,0,0}.
3224  using cell_iterator =
3226  typename std::map<std::pair<cell_iterator, unsigned int>,
3227  std::pair<std::pair<cell_iterator, unsigned int>,
3228  std::bitset<3>>>::const_iterator it;
3229  for (it = tria.get_periodic_face_map().begin();
3230  it != tria.get_periodic_face_map().end();
3231  ++it)
3232  {
3233  const cell_iterator &cell_1 = it->first.first;
3234  const unsigned int face_no_1 = it->first.second;
3235  const cell_iterator &cell_2 = it->second.first.first;
3236  const unsigned int face_no_2 = it->second.first.second;
3237  const std::bitset<3> face_orientation = it->second.second;
3238 
3239  if (cell_1->level() == cell_2->level())
3240  {
3241  for (unsigned int v = 0;
3242  v < GeometryInfo<dim - 1>::vertices_per_cell;
3243  ++v)
3244  {
3245  // take possible non-standard orientation of face on cell[0]
3246  // into account
3247  const unsigned int vface0 =
3249  v,
3250  face_orientation[0],
3251  face_orientation[1],
3252  face_orientation[2]);
3253  const unsigned int vi0 =
3254  topological_vertex_numbering[cell_1->face(face_no_1)
3255  ->vertex_index(vface0)];
3256  const unsigned int vi1 =
3257  topological_vertex_numbering[cell_2->face(face_no_2)
3258  ->vertex_index(v)];
3259  const unsigned int min_index = std::min(vi0, vi1);
3260  topological_vertex_numbering[cell_1->face(face_no_1)
3261  ->vertex_index(vface0)] =
3262  topological_vertex_numbering[cell_2->face(face_no_2)
3263  ->vertex_index(v)] =
3264  min_index;
3265  }
3266  }
3267  }
3268 
3269  // There must not be any chains!
3270  for (unsigned int i = 0; i < topological_vertex_numbering.size(); ++i)
3271  {
3272  const unsigned int j = topological_vertex_numbering[i];
3273  if (j != i)
3274  Assert(topological_vertex_numbering[j] == j, ExcInternalError());
3275  }
3276 
3277 
3278  // this code is replicated from grid/tria.cc but using an indirection
3279  // for periodic boundary conditions
3280  bool continue_iterating = true;
3281  std::vector<int> vertex_level(tria.n_vertices());
3282  while (continue_iterating)
3283  {
3284  // store highest level one of the cells adjacent to a vertex
3285  // belongs to
3286  std::fill(vertex_level.begin(), vertex_level.end(), 0);
3288  cell = tria.begin_active(),
3289  endc = tria.end();
3290  for (; cell != endc; ++cell)
3291  {
3292  if (cell->refine_flag_set())
3293  for (unsigned int vertex = 0;
3294  vertex < GeometryInfo<dim>::vertices_per_cell;
3295  ++vertex)
3296  vertex_level[topological_vertex_numbering
3297  [cell->vertex_index(vertex)]] =
3298  std::max(vertex_level[topological_vertex_numbering
3299  [cell->vertex_index(vertex)]],
3300  cell->level() + 1);
3301  else if (!cell->coarsen_flag_set())
3302  for (unsigned int vertex = 0;
3303  vertex < GeometryInfo<dim>::vertices_per_cell;
3304  ++vertex)
3305  vertex_level[topological_vertex_numbering
3306  [cell->vertex_index(vertex)]] =
3307  std::max(vertex_level[topological_vertex_numbering
3308  [cell->vertex_index(vertex)]],
3309  cell->level());
3310  else
3311  {
3312  // if coarsen flag is set then tentatively assume
3313  // that the cell will be coarsened. this isn't
3314  // always true (the coarsen flag could be removed
3315  // again) and so we may make an error here. we try
3316  // to correct this by iterating over the entire
3317  // process until we are converged
3318  Assert(cell->coarsen_flag_set(), ExcInternalError());
3319  for (unsigned int vertex = 0;
3320  vertex < GeometryInfo<dim>::vertices_per_cell;
3321  ++vertex)
3322  vertex_level[topological_vertex_numbering
3323  [cell->vertex_index(vertex)]] =
3324  std::max(vertex_level[topological_vertex_numbering
3325  [cell->vertex_index(vertex)]],
3326  cell->level() - 1);
3327  }
3328  }
3329 
3330  continue_iterating = false;
3331 
3332  // loop over all cells in reverse order. do so because we
3333  // can then update the vertex levels on the adjacent
3334  // vertices and maybe already flag additional cells in this
3335  // loop
3336  //
3337  // note that not only may we have to add additional
3338  // refinement flags, but we will also have to remove
3339  // coarsening flags on cells adjacent to vertices that will
3340  // see refinement
3341  for (cell = tria.last_active(); cell != endc; --cell)
3342  if (cell->refine_flag_set() == false)
3343  {
3344  for (unsigned int vertex = 0;
3345  vertex < GeometryInfo<dim>::vertices_per_cell;
3346  ++vertex)
3347  if (vertex_level[topological_vertex_numbering
3348  [cell->vertex_index(vertex)]] >=
3349  cell->level() + 1)
3350  {
3351  // remove coarsen flag...
3352  cell->clear_coarsen_flag();
3353 
3354  // ...and if necessary also refine the current
3355  // cell, at the same time updating the level
3356  // information about vertices
3357  if (vertex_level[topological_vertex_numbering
3358  [cell->vertex_index(vertex)]] >
3359  cell->level() + 1)
3360  {
3361  cell->set_refine_flag();
3362  continue_iterating = true;
3363 
3364  for (unsigned int v = 0;
3365  v < GeometryInfo<dim>::vertices_per_cell;
3366  ++v)
3367  vertex_level[topological_vertex_numbering
3368  [cell->vertex_index(v)]] =
3369  std::max(
3370  vertex_level[topological_vertex_numbering
3371  [cell->vertex_index(v)]],
3372  cell->level() + 1);
3373  }
3374 
3375  // continue and see whether we may, for example,
3376  // go into the inner 'if' above based on a
3377  // different vertex
3378  }
3379  }
3380 
3381  // clear coarsen flag if not all children were marked
3382  for (typename Triangulation<dim, spacedim>::cell_iterator cell =
3383  tria.begin();
3384  cell != tria.end();
3385  ++cell)
3386  {
3387  // nothing to do if we are already on the finest level
3388  if (cell->active())
3389  continue;
3390 
3391  const unsigned int n_children = cell->n_children();
3392  unsigned int flagged_children = 0;
3393  for (unsigned int child = 0; child < n_children; ++child)
3394  if (cell->child(child)->active() &&
3395  cell->child(child)->coarsen_flag_set())
3396  ++flagged_children;
3397 
3398  // if not all children were flagged for coarsening, remove
3399  // coarsen flags
3400  if (flagged_children < n_children)
3401  for (unsigned int child = 0; child < n_children; ++child)
3402  if (cell->child(child)->active())
3403  cell->child(child)->clear_coarsen_flag();
3404  }
3405  }
3406  std::vector<bool> flags_after[2];
3407  tria.save_coarsen_flags(flags_after[0]);
3408  tria.save_refine_flags(flags_after[1]);
3409  return ((flags_before[0] != flags_after[0]) ||
3410  (flags_before[1] != flags_after[1]));
3411  }
3412  } // namespace
3413 
3414 
3415 
3416  template <int dim, int spacedim>
3417  bool
3419  {
3420  std::vector<bool> flags_before[2];
3421  this->save_coarsen_flags(flags_before[0]);
3422  this->save_refine_flags(flags_before[1]);
3423 
3424  bool mesh_changed = false;
3425  do
3426  {
3429  this->update_periodic_face_map();
3430  // enforce 2:1 mesh balance over periodic boundaries
3433  mesh_changed = enforce_mesh_balance_over_periodic_boundaries(*this);
3434  }
3435  while (mesh_changed);
3436 
3437  // check if any of the refinement flags were changed during this
3438  // function and return that value
3439  std::vector<bool> flags_after[2];
3440  this->save_coarsen_flags(flags_after[0]);
3441  this->save_refine_flags(flags_after[1]);
3442  return ((flags_before[0] != flags_after[0]) ||
3443  (flags_before[1] != flags_after[1]));
3444  }
3445 
3446 
3447 
3448  template <int dim, int spacedim>
3449  void
3451  {
3452  // disable mesh smoothing for recreating the deal.II triangulation,
3453  // otherwise we might not be able to reproduce the p4est mesh
3454  // exactly. We restore the original smoothing at the end of this
3455  // function. Note that the smoothing flag is used in the normal
3456  // refinement process.
3457  typename Triangulation<dim, spacedim>::MeshSmoothing save_smooth =
3458  this->smooth_grid;
3459 
3460  // We will refine manually to match the p4est further down, which
3461  // obeys a level difference of 2 at each vertex (see the balance call
3462  // to p4est). We can disable this here so we store fewer artificial
3463  // cells (in some cases).
3464  // For geometric multigrid it turns out that
3465  // we will miss level cells at shared vertices if we ignore this.
3466  // See tests/mpi/mg_06. In particular, the flag is still necessary
3467  // even though we force it for the original smooth_grid in the
3468  // constructor.
3470  this->smooth_grid =
3471  ::Triangulation<dim,
3473  else
3475 
3476  bool mesh_changed = false;
3477 
3478  // remove all deal.II refinements. Note that we could skip this and
3479  // start from our current state, because the algorithm later coarsens as
3480  // necessary. This has the advantage of being faster when large parts
3481  // of the local partition changes (likely) and gives a deterministic
3482  // ordering of the cells (useful for snapshot/resume).
3483  // TODO: is there a more efficient way to do this?
3485  while (this->begin_active()->level() > 0)
3486  {
3488  cell = this->begin_active();
3489  cell != this->end();
3490  ++cell)
3491  {
3492  cell->set_coarsen_flag();
3493  }
3494 
3496  try
3497  {
3500  }
3501  catch (
3503  {
3504  // the underlying triangulation should not be checking for
3505  // distorted cells
3506  Assert(false, ExcInternalError());
3507  }
3508  }
3509 
3510 
3511  // query p4est for the ghost cells
3512  if (parallel_ghost != nullptr)
3513  {
3515  parallel_ghost);
3516  parallel_ghost = nullptr;
3517  }
3519  parallel_forest,
3520  (dim == 2 ? typename ::internal::p4est::types<dim>::balance_type(
3521  P4EST_CONNECT_CORNER) :
3522  typename ::internal::p4est::types<dim>::balance_type(
3523  P8EST_CONNECT_CORNER)));
3524 
3526 
3527 
3528  // set all cells to artificial. we will later set it to the correct
3529  // subdomain in match_tree_recursively
3530  for (typename Triangulation<dim, spacedim>::cell_iterator cell =
3531  this->begin(0);
3532  cell != this->end(0);
3533  ++cell)
3534  cell->recursively_set_subdomain_id(numbers::artificial_subdomain_id);
3535 
3536  do
3537  {
3538  for (typename Triangulation<dim, spacedim>::cell_iterator cell =
3539  this->begin(0);
3540  cell != this->end(0);
3541  ++cell)
3542  {
3543  // if this processor stores no part of the forest that comes out
3544  // of this coarse grid cell, then we need to delete all children
3545  // of this cell (the coarse grid cell remains)
3546  if (tree_exists_locally<dim, spacedim>(
3547  parallel_forest,
3548  coarse_cell_to_p4est_tree_permutation[cell->index()]) ==
3549  false)
3550  {
3551  delete_all_children<dim, spacedim>(cell);
3552  if (!cell->has_children())
3553  cell->set_subdomain_id(numbers::artificial_subdomain_id);
3554  }
3555 
3556  else
3557  {
3558  // this processor stores at least a part of the tree that
3559  // comes out of this cell.
3560 
3561  typename ::internal::p4est::types<dim>::quadrant
3562  p4est_coarse_cell;
3563  typename ::internal::p4est::types<dim>::tree *tree =
3564  init_tree(cell->index());
3565 
3566  ::internal::p4est::init_coarse_quadrant<dim>(
3567  p4est_coarse_cell);
3568 
3569  match_tree_recursively<dim, spacedim>(*tree,
3570  cell,
3571  p4est_coarse_cell,
3572  *parallel_forest,
3573  this->my_subdomain);
3574  }
3575  }
3576 
3577  // check mesh for ghost cells, refine as necessary. iterate over
3578  // every ghostquadrant, find corresponding deal coarsecell and
3579  // recurse.
3580  typename ::internal::p4est::types<dim>::quadrant *quadr;
3581  types::subdomain_id ghost_owner = 0;
3582  typename ::internal::p4est::types<dim>::topidx ghost_tree = 0;
3583 
3584  for (unsigned int g_idx = 0;
3585  g_idx < parallel_ghost->ghosts.elem_count;
3586  ++g_idx)
3587  {
3588  while (
3589  g_idx >=
3590  (unsigned int)parallel_ghost->proc_offsets[ghost_owner + 1])
3591  ++ghost_owner;
3592  while (g_idx >=
3593  (unsigned int)parallel_ghost->tree_offsets[ghost_tree + 1])
3594  ++ghost_tree;
3595 
3596  quadr = static_cast<
3597  typename ::internal::p4est::types<dim>::quadrant *>(
3598  sc_array_index(&parallel_ghost->ghosts, g_idx));
3599 
3600  unsigned int coarse_cell_index =
3601  p4est_tree_to_coarse_cell_permutation[ghost_tree];
3602 
3603  match_quadrant<dim, spacedim>(this,
3604  coarse_cell_index,
3605  *quadr,
3606  ghost_owner);
3607  }
3608 
3609  // fix all the flags to make sure we have a consistent mesh
3611 
3612  // see if any flags are still set
3613  mesh_changed = false;
3615  cell = this->begin_active();
3616  cell != this->end();
3617  ++cell)
3618  if (cell->refine_flag_set() || cell->coarsen_flag_set())
3619  {
3620  mesh_changed = true;
3621  break;
3622  }
3623 
3624  // actually do the refinement to change the local mesh by
3625  // calling the base class refinement function directly
3626  try
3627  {
3630  }
3631  catch (
3633  {
3634  // the underlying triangulation should not be checking for
3635  // distorted cells
3636  Assert(false, ExcInternalError());
3637  }
3638  }
3639  while (mesh_changed);
3640 
3641 # ifdef DEBUG
3642  // check if correct number of ghosts is created
3643  unsigned int num_ghosts = 0;
3644 
3646  this->begin_active();
3647  cell != this->end();
3648  ++cell)
3649  {
3650  if (cell->subdomain_id() != this->my_subdomain &&
3651  cell->subdomain_id() != numbers::artificial_subdomain_id)
3652  ++num_ghosts;
3653  }
3654 
3655  Assert(num_ghosts == parallel_ghost->ghosts.elem_count,
3656  ExcInternalError());
3657 # endif
3658 
3659 
3660 
3661  // fill level_subdomain_ids for geometric multigrid
3662  // the level ownership of a cell is defined as the owner if the cell is
3663  // active or as the owner of child(0) we need this information for all our
3664  // ancestors and the same-level neighbors of our own cells (=level ghosts)
3665  if (settings & construct_multigrid_hierarchy)
3666  {
3667  // step 1: We set our own ids all the way down and all the others to
3668  // -1. Note that we do not fill other cells we could figure out the
3669  // same way, because we might accidentally set an id for a cell that
3670  // is not a ghost cell.
3671  for (unsigned int lvl = this->n_levels(); lvl > 0;)
3672  {
3673  --lvl;
3675  endc = this->end(lvl);
3676  for (cell = this->begin(lvl); cell != endc; ++cell)
3677  {
3678  if ((!cell->has_children() &&
3679  cell->subdomain_id() ==
3680  this->locally_owned_subdomain()) ||
3681  (cell->has_children() &&
3682  cell->child(0)->level_subdomain_id() ==
3683  this->locally_owned_subdomain()))
3684  cell->set_level_subdomain_id(
3685  this->locally_owned_subdomain());
3686  else
3687  {
3688  // not our cell
3689  cell->set_level_subdomain_id(
3691  }
3692  }
3693  }
3694 
3695  // step 2: make sure all the neighbors to our level_cells exist. Need
3696  // to look up in p4est...
3697  std::vector<std::vector<bool>> marked_vertices(this->n_levels());
3698  for (unsigned int lvl = 0; lvl < this->n_levels(); ++lvl)
3699  marked_vertices[lvl] = mark_locally_active_vertices_on_level(lvl);
3700 
3701  for (typename Triangulation<dim, spacedim>::cell_iterator cell =
3702  this->begin(0);
3703  cell != this->end(0);
3704  ++cell)
3705  {
3706  typename ::internal::p4est::types<dim>::quadrant
3707  p4est_coarse_cell;
3708  const unsigned int tree_index =
3709  coarse_cell_to_p4est_tree_permutation[cell->index()];
3710  typename ::internal::p4est::types<dim>::tree *tree =
3711  init_tree(cell->index());
3712 
3713  ::internal::p4est::init_coarse_quadrant<dim>(
3714  p4est_coarse_cell);
3715 
3716  determine_level_subdomain_id_recursively<dim, spacedim>(
3717  *tree,
3718  tree_index,
3719  cell,
3720  p4est_coarse_cell,
3721  *parallel_forest,
3722  this->my_subdomain,
3723  marked_vertices);
3724  }
3725 
3726  // step 3: make sure we have the parent of our level cells
3727  for (unsigned int lvl = this->n_levels(); lvl > 0;)
3728  {
3729  --lvl;
3731  endc = this->end(lvl);
3732  for (cell = this->begin(lvl); cell != endc; ++cell)
3733  {
3734  if (cell->has_children())
3735  for (unsigned int c = 0;
3736  c < GeometryInfo<dim>::max_children_per_cell;
3737  ++c)
3738  {
3739  if (cell->child(c)->level_subdomain_id() ==
3740  this->locally_owned_subdomain())
3741  {
3742  // at least one of the children belongs to us, so
3743  // make sure we set the level subdomain id
3744  const types::subdomain_id mark =
3745  cell->child(0)->level_subdomain_id();
3747  ExcInternalError()); // we should know the
3748  // child(0)
3749  cell->set_level_subdomain_id(mark);
3750  break;
3751  }
3752  }
3753  }
3754  }
3755  }
3756 
3757 
3758 
3759  // check that our local copy has exactly as many cells as the p4est
3760  // original (at least if we are on only one processor); for parallel
3761  // computations, we want to check that we have at least as many as p4est
3762  // stores locally (in the future we should check that we have exactly as
3763  // many non-artificial cells as parallel_forest->local_num_quadrants)
3764  {
3765  const unsigned int total_local_cells = this->n_active_cells();
3766  (void)total_local_cells;
3767 
3769  {
3770  Assert(static_cast<unsigned int>(
3771  parallel_forest->local_num_quadrants) == total_local_cells,
3772  ExcInternalError());
3773  }
3774  else
3775  {
3776  Assert(static_cast<unsigned int>(
3777  parallel_forest->local_num_quadrants) <= total_local_cells,
3778  ExcInternalError());
3779  }
3780 
3781  // count the number of owned, active cells and compare with p4est.
3782  unsigned int n_owned = 0;
3784  this->begin_active();
3785  cell != this->end();
3786  ++cell)
3787  {
3788  if (cell->subdomain_id() == this->my_subdomain)
3789  ++n_owned;
3790  }
3791 
3792  Assert(static_cast<unsigned int>(
3793  parallel_forest->local_num_quadrants) == n_owned,
3794  ExcInternalError());
3795  }
3796 
3797  this->smooth_grid = save_smooth;
3798 
3799  // finally, after syncing the parallel_forest with the triangulation,
3800  // also update the quadrant_cell_relations, which will be used for
3801  // repartitioning, further refinement/coarsening, and unpacking
3802  // of stored or transfered data.
3804  }
3805 
3806 
3807 
3808  template <int dim, int spacedim>
3809  void
3811  {
3812  // do not allow anisotropic refinement
3813 # ifdef DEBUG
3815  this->begin_active();
3816  cell != this->end();
3817  ++cell)
3818  if (cell->is_locally_owned() && cell->refine_flag_set())
3819  Assert(cell->refine_flag_set() ==
3821  ExcMessage(
3822  "This class does not support anisotropic refinement"));
3823 # endif
3824 
3825 
3826  // safety check: p4est has an upper limit on the level of a cell
3827  if (this->n_levels() ==
3829  {
3831  cell = this->begin_active(
3833  cell !=
3835  1);
3836  ++cell)
3837  {
3838  AssertThrow(
3839  !(cell->refine_flag_set()),
3840  ExcMessage(
3841  "Fatal Error: maximum refinement level of p4est reached."));
3842  }
3843  }
3844 
3845  // signal that refinement is going to happen
3847 
3848  // now do the work we're supposed to do when we are in charge
3850 
3851  // make sure all flags are cleared on cells we don't own, since nothing
3852  // good can come of that if they are still around
3854  this->begin_active();
3855  cell != this->end();
3856  ++cell)
3857  if (cell->is_ghost() || cell->is_artificial())
3858  {
3859  cell->clear_refine_flag();
3860  cell->clear_coarsen_flag();
3861  }
3862 
3863 
3864  // count how many cells will be refined and coarsened, and allocate that
3865  // much memory
3866  RefineAndCoarsenList<dim, spacedim> refine_and_coarsen_list(
3867  *this, p4est_tree_to_coarse_cell_permutation, this->my_subdomain);
3868 
3869  // copy refine and coarsen flags into p4est and execute the refinement
3870  // and coarsening. this uses the refine_and_coarsen_list just built,
3871  // which is communicated to the callback functions through
3872  // p4est's user_pointer object
3873  Assert(parallel_forest->user_pointer == this, ExcInternalError());
3874  parallel_forest->user_pointer = &refine_and_coarsen_list;
3875 
3876  if (parallel_ghost != nullptr)
3877  {
3879  parallel_ghost);
3880  parallel_ghost = nullptr;
3881  }
3883  parallel_forest,
3884  /* refine_recursive */ false,
3885  &RefineAndCoarsenList<dim, spacedim>::refine_callback,
3886  /*init_callback=*/nullptr);
3888  parallel_forest,
3889  /* coarsen_recursive */ false,
3890  &RefineAndCoarsenList<dim, spacedim>::coarsen_callback,
3891  /*init_callback=*/nullptr);
3892 
3893  // make sure all cells in the lists have been consumed
3894  Assert(refine_and_coarsen_list.pointers_are_at_end(), ExcInternalError());
3895 
3896  // reset the pointer
3897  parallel_forest->user_pointer = this;
3898 
3899  // enforce 2:1 hanging node condition
3901  parallel_forest,
3902  /* face and corner balance */
3903  (dim == 2 ? typename ::internal::p4est::types<dim>::balance_type(
3904  P4EST_CONNECT_FULL) :
3905  typename ::internal::p4est::types<dim>::balance_type(
3906  P8EST_CONNECT_FULL)),
3907  /*init_callback=*/nullptr);
3908 
3909  // since refinement and/or coarsening on the parallel forest
3910  // has happened, we need to update the quadrant cell relations
3912 
3913  // before repartitioning the mesh, store the current distribution
3914  // of the p4est quadrants and let others attach mesh related info
3915  // (such as SolutionTransfer data)
3916  std::vector<typename ::internal::p4est::types<dim>::gloidx>
3917  previous_global_first_quadrant;
3918 
3919  // pack data only if anything has been attached
3920  if (cell_attached_data.n_attached_data_sets > 0)
3921  {
3922  data_transfer.pack_data(local_quadrant_cell_relations,
3923  cell_attached_data.pack_callbacks_fixed,
3924  cell_attached_data.pack_callbacks_variable);
3925 
3926  // before repartitioning the p4est object, save a copy of the
3927  // positions of the global first quadrants for data transfer later
3928  previous_global_first_quadrant.resize(parallel_forest->mpisize + 1);
3929  std::memcpy(previous_global_first_quadrant.data(),
3930  parallel_forest->global_first_quadrant,
3931  sizeof(
3932  typename ::internal::p4est::types<dim>::gloidx) *
3933  (parallel_forest->mpisize + 1));
3934  }
3935 
3937  {
3938  // partition the new mesh between all processors. If cell weights have
3939  // not been given balance the number of cells.
3940  if (this->signals.cell_weight.num_slots() == 0)
3942  parallel_forest,
3943  /* prepare coarsening */ 1,
3944  /* weight_callback */ nullptr);
3945  else
3946  {
3947  // get cell weights for a weighted repartitioning.
3948  const std::vector<unsigned int> cell_weights = get_cell_weights();
3949 
3950  PartitionWeights<dim, spacedim> partition_weights(cell_weights);
3951 
3952  // attach (temporarily) a pointer to the cell weights through
3953  // p4est's user_pointer object
3954  Assert(parallel_forest->user_pointer == this, ExcInternalError());
3955  parallel_forest->user_pointer = &partition_weights;
3956 
3958  parallel_forest,
3959  /* prepare coarsening */ 1,
3960  /* weight_callback */
3961  &PartitionWeights<dim, spacedim>::cell_weight);
3962 
3963  // release data
3965  parallel_forest, 0, nullptr, nullptr);
3966  // reset the user pointer to its previous state
3967  parallel_forest->user_pointer = this;
3968  }
3969  }
3970 
3971  // finally copy back from local part of tree to deal.II
3972  // triangulation. before doing so, make sure there are no refine or
3973  // coarsen flags pending
3975  this->begin_active();
3976  cell != this->end();
3977  ++cell)
3978  {
3979  cell->clear_refine_flag();
3980  cell->clear_coarsen_flag();
3981  }
3982 
3983  try
3984  {
3986  }
3987  catch (const typename Triangulation<dim>::DistortedCellList &)
3988  {
3989  // the underlying triangulation should not be checking for distorted
3990  // cells
3991  Assert(false, ExcInternalError());
3992  }
3993 
3994  // transfer data
3995  // only if anything has been attached
3996  if (cell_attached_data.n_attached_data_sets > 0)
3997  {
3998  // execute transfer after triangulation got updated
3999  data_transfer.execute_transfer(parallel_forest,
4000  previous_global_first_quadrant.data());
4001 
4002  // also update the CellStatus information on the new mesh
4003  data_transfer.unpack_cell_status(local_quadrant_cell_relations);
4004  }
4005 
4006 # ifdef DEBUG
4007  // Check that we know the level subdomain ids of all our neighbors. This
4008  // also involves coarser cells that share a vertex if they are active.
4009  //
4010  // Example (M= my, O=other):
4011  // *------*
4012  // | |
4013  // | O |
4014  // | |
4015  // *---*---*------*
4016  // | M | M |
4017  // *---*---*
4018  // | | M |
4019  // *---*---*
4020  // ^- the parent can be owned by somebody else, so O is not a neighbor
4021  // one level coarser
4023  {
4024  for (unsigned int lvl = 0; lvl < this->n_global_levels(); ++lvl)
4025  {
4026  std::vector<bool> active_verts =
4028 
4029  const unsigned int maybe_coarser_lvl =
4030  (lvl > 0) ? (lvl - 1) : lvl;
4032  cell = this->begin(maybe_coarser_lvl),
4033  endc = this->end(lvl);
4034  for (; cell != endc; ++cell)
4035  if (cell->level() == static_cast<int>(lvl) || cell->active())
4036  {
4037  const bool is_level_artificial =
4038  (cell->level_subdomain_id() ==
4040  bool need_to_know = false;
4041  for (unsigned int vertex = 0;
4042  vertex < GeometryInfo<dim>::vertices_per_cell;
4043  ++vertex)
4044  if (active_verts[cell->vertex_index(vertex)])
4045  {
4046  need_to_know = true;
4047  break;
4048  }
4049 
4050  Assert(
4051  !need_to_know || !is_level_artificial,
4052  ExcMessage(
4053  "Internal error: the owner of cell" +
4054  cell->id().to_string() +
4055  " is unknown even though it is needed for geometric multigrid."));
4056  }
4057  }
4058  }
4059 # endif
4060 
4061  this->update_number_cache();
4062 
4063  // signal that refinement is finished,
4064  // this is triggered before update_periodic_face_map
4065  // to be consistent with the serial triangulation class
4067 
4068  this->update_periodic_face_map();
4069  }
4070 
4071 
4072 
4073  template <int dim, int spacedim>
4074  void
4076  {
4077 # ifdef DEBUG
4079  this->begin_active();
4080  cell != this->end();
4081  ++cell)
4082  if (cell->is_locally_owned())
4083  Assert(
4084  !cell->refine_flag_set() && !cell->coarsen_flag_set(),
4085  ExcMessage(
4086  "Error: There shouldn't be any cells flagged for coarsening/refinement when calling repartition()."));
4087 # endif
4088 
4089  // before repartitioning the mesh let others attach mesh related info
4090  // (such as SolutionTransfer data) to the p4est
4091  std::vector<typename ::internal::p4est::types<dim>::gloidx>
4092  previous_global_first_quadrant;
4093 
4094  // pack data only if anything has been attached
4095  if (cell_attached_data.n_attached_data_sets > 0)
4096  {
4097  data_transfer.pack_data(local_quadrant_cell_relations,
4098  cell_attached_data.pack_callbacks_fixed,
4099  cell_attached_data.pack_callbacks_variable);
4100 
4101  // before repartitioning the p4est object, save a copy of the
4102  // positions of quadrant for data transfer later
4103  previous_global_first_quadrant.resize(parallel_forest->mpisize + 1);
4104  std::memcpy(previous_global_first_quadrant.data(),
4105  parallel_forest->global_first_quadrant,
4106  sizeof(
4107  typename ::internal::p4est::types<dim>::gloidx) *
4108  (parallel_forest->mpisize + 1));
4109  }
4110 
4111  if (this->signals.cell_weight.num_slots() == 0)
4112  {
4113  // no cell weights given -- call p4est's 'partition' without a
4114  // callback for cell weights
4116  parallel_forest,
4117  /* prepare coarsening */ 1,
4118  /* weight_callback */ nullptr);
4119  }
4120  else
4121  {
4122  // get cell weights for a weighted repartitioning.
4123  const std::vector<unsigned int> cell_weights = get_cell_weights();
4124 
4125  PartitionWeights<dim, spacedim> partition_weights(cell_weights);
4126 
4127  // attach (temporarily) a pointer to the cell weights through p4est's
4128  // user_pointer object
4129  Assert(parallel_forest->user_pointer == this, ExcInternalError());
4130  parallel_forest->user_pointer = &partition_weights;
4131 
4133  parallel_forest,
4134  /* prepare coarsening */ 1,
4135  /* weight_callback */
4136  &PartitionWeights<dim, spacedim>::cell_weight);
4137 
4138  // reset the user pointer to its previous state
4139  parallel_forest->user_pointer = this;
4140  }
4141 
4142  try
4143  {
4145  }
4146  catch (const typename Triangulation<dim>::DistortedCellList &)
4147  {
4148  // the underlying triangulation should not be checking for distorted
4149  // cells
4150  Assert(false, ExcInternalError());
4151  }
4152 
4153  // transfer data
4154  // only if anything has been attached
4155  if (cell_attached_data.n_attached_data_sets > 0)
4156  {
4157  // execute transfer after triangulation got updated
4158  data_transfer.execute_transfer(parallel_forest,
4159  previous_global_first_quadrant.data());
4160  }
4161 
4162  // update how many cells, edges, etc, we store locally
4163  this->update_number_cache();
4164  this->update_periodic_face_map();
4165  }
4166 
4167 
4168 
4169  template <int dim, int spacedim>
4170  void
4172  const std::vector<bool> &vertex_locally_moved)
4173  {
4174  Assert(vertex_locally_moved.size() == this->n_vertices(),
4175  ExcDimensionMismatch(vertex_locally_moved.size(),
4176  this->n_vertices()));
4177 # ifdef DEBUG
4178  {
4179  const std::vector<bool> locally_owned_vertices =
4180  ::GridTools::get_locally_owned_vertices(*this);
4181  for (unsigned int i = 0; i < locally_owned_vertices.size(); ++i)
4182  Assert((vertex_locally_moved[i] == false) ||
4183  (locally_owned_vertices[i] == true),
4184  ExcMessage("The vertex_locally_moved argument must not "
4185  "contain vertices that are not locally owned"));
4186  }
4187 # endif
4188 
4189  // First find out which process should receive which vertices.
4190  // These are specifically the ones that are located on cells at the
4191  // boundary of the subdomain this process owns and the receiving
4192  // process taking periodic faces into account.
4193  // Here, it is sufficient to collect all vertices that are located
4194  // at that boundary.
4195  const std::map<unsigned int, std::set<::types::subdomain_id>>
4196  vertices_with_ghost_neighbors = compute_vertices_with_ghost_neighbors();
4197 
4198  // now collect cells and their vertices
4199  // for the interested neighbors
4200  using cellmap_t =
4201  std::map<::types::subdomain_id,
4202  CommunicateLocallyMovedVertices::CellInfo<dim, spacedim>>;
4203  cellmap_t needs_to_get_cells;
4204 
4205  for (typename Triangulation<dim, spacedim>::cell_iterator cell =
4206  this->begin(0);
4207  cell != this->end(0);
4208  ++cell)
4209  {
4210  typename ::internal::p4est::types<dim>::quadrant
4211  p4est_coarse_cell;
4212  ::internal::p4est::init_coarse_quadrant<dim>(p4est_coarse_cell);
4213 
4214  CommunicateLocallyMovedVertices::fill_vertices_recursively<dim,
4215  spacedim>(
4216  *this,
4217  this->get_coarse_cell_to_p4est_tree_permutation()[cell->index()],
4218  cell,
4219  p4est_coarse_cell,
4220  vertices_with_ghost_neighbors,
4221  vertex_locally_moved,
4222  needs_to_get_cells);
4223  }
4224 
4225  // sending
4226  std::vector<std::vector<char>> sendbuffers(needs_to_get_cells.size());
4227  std::vector<std::vector<char>>::iterator buffer = sendbuffers.begin();
4228  std::vector<MPI_Request> requests(needs_to_get_cells.size());
4229  std::vector<unsigned int> destinations;
4230 
4231  unsigned int idx = 0;
4232 
4233  for (typename cellmap_t::iterator it = needs_to_get_cells.begin();
4234  it != needs_to_get_cells.end();
4235  ++it, ++buffer, ++idx)
4236  {
4237  const unsigned int num_cells = it->second.tree_index.size();
4238  (void)num_cells;
4239  destinations.push_back(it->first);
4240 
4241  Assert(num_cells == it->second.quadrants.size(), ExcInternalError());
4242  Assert(num_cells > 0, ExcInternalError());
4243 
4244  // pack all the data into
4245  // the buffer for this
4246  // recipient and send
4247  // it. keep data around
4248  // till we can make sure
4249  // that the packet has been
4250  // received
4251  it->second.pack_data(*buffer);
4252  const int ierr = MPI_Isend(&(*buffer)[0],
4253  buffer->size(),
4254  MPI_BYTE,
4255  it->first,
4256  123,
4257  this->get_communicator(),
4258  &requests[idx]);
4259  AssertThrowMPI(ierr);
4260  }
4261 
4262  Assert(destinations.size() == needs_to_get_cells.size(),
4263  ExcInternalError());
4264 
4265  // collect the neighbors
4266  // that are going to send stuff to us
4267  const std::vector<unsigned int> senders =
4269  this->get_communicator(), destinations);
4270 
4271  // receive ghostcelldata
4272  std::vector<char> receive;
4273  CommunicateLocallyMovedVertices::CellInfo<dim, spacedim> cellinfo;
4274  for (unsigned int i = 0; i < senders.size(); ++i)
4275  {
4276  MPI_Status status;
4277  int len;
4278  int ierr =
4279  MPI_Probe(MPI_ANY_SOURCE, 123, this->get_communicator(), &status);
4280  AssertThrowMPI(ierr);
4281  ierr = MPI_Get_count(&status, MPI_BYTE, &len);
4282  AssertThrowMPI(ierr);
4283  receive.resize(len);
4284 
4285  char *ptr = receive.data();
4286  ierr = MPI_Recv(ptr,
4287  len,
4288  MPI_BYTE,
4289  status.MPI_SOURCE,
4290  status.MPI_TAG,
4291  this->get_communicator(),
4292  &status);
4293  AssertThrowMPI(ierr);
4294 
4295  cellinfo.unpack_data(receive);
4296  const unsigned int cells = cellinfo.tree_index.size();
4297  for (unsigned int c = 0; c < cells; ++c)
4298  {
4299  typename ::parallel::distributed::
4300  Triangulation<dim, spacedim>::cell_iterator cell(
4301  this,
4302  0,
4304  [cellinfo.tree_index[c]]);
4305 
4306  typename ::internal::p4est::types<dim>::quadrant
4307  p4est_coarse_cell;
4308  ::internal::p4est::init_coarse_quadrant<dim>(
4309  p4est_coarse_cell);
4310 
4311  CommunicateLocallyMovedVertices::set_vertices_recursively<
4312  dim,
4313  spacedim>(*this,
4314  p4est_coarse_cell,
4315  cell,
4316  cellinfo.quadrants[c],
4317  cellinfo.first_vertices[c],
4318  cellinfo.first_vertex_indices[c]);
4319  }
4320  }
4321 
4322  // complete all sends, so that we can
4323  // safely destroy the buffers.
4324  if (requests.size() > 0)
4325  {
4326  const int ierr =
4327  MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
4328  AssertThrowMPI(ierr);
4329  }
4330 
4331  // check all msgs got sent and received
4332  Assert(Utilities::MPI::sum(needs_to_get_cells.size(),
4333  this->get_communicator()) ==
4334  Utilities::MPI::sum(senders.size(), this->get_communicator()),
4335  ExcInternalError());
4336  }
4337 
4338 
4339 
4340  template <int dim, int spacedim>
4341  unsigned int
4343  const std::function<std::vector<char>(const cell_iterator &,
4344  const CellStatus)> &pack_callback,
4345  const bool returns_variable_size_data)
4346  {
4347  unsigned int handle = numbers::invalid_unsigned_int;
4348 
4349  // Add new callback function to the corresponding register.
4350  // Encode handles according to returns_variable_size_data.
4351  if (returns_variable_size_data)
4352  {
4353  handle = 2 * cell_attached_data.pack_callbacks_variable.size();
4354  cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
4355  }
4356  else
4357  {
4358  handle = 2 * cell_attached_data.pack_callbacks_fixed.size() + 1;
4359  cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
4360  }
4361 
4362  // Increase overall counter.
4363  ++cell_attached_data.n_attached_data_sets;
4364 
4365  return handle;
4366  }
4367 
4368 
4369 
4370  template <int dim, int spacedim>
4371  void
4373  const unsigned int handle,
4374  const std::function<
4375  void(const cell_iterator &,
4376  const CellStatus,
4377  const boost::iterator_range<std::vector<char>::const_iterator> &)>
4378  &unpack_callback)
4379  {
4380  Assert(cell_attached_data.n_attached_data_sets > 0,
4381  ExcMessage("The notify_ready_to_unpack() has already been called "
4382  "once for each registered callback."));
4383 
4384  // check if local_quadrant_cell_relations have been previously gathered
4385  // correctly
4387  static_cast<unsigned int>(parallel_forest->local_num_quadrants),
4388  ExcInternalError());
4389 
4390 # ifdef DEBUG
4391  // check validity of handle and deregister pack_callback function.
4392  // first reset with invalid entries to preserve ambiguity of
4393  // handles, then free memory when all were unpacked (see below).
4394  const unsigned int callback_index = handle / 2;
4395  if (handle % 2 == 0)
4396  {
4397  Assert(callback_index <
4398  cell_attached_data.pack_callbacks_variable.size(),
4399  ExcMessage("Invalid handle."));
4400 
4401  Assert(cell_attached_data.pack_callbacks_variable[callback_index] !=
4402  nullptr,
4403  ExcInternalError());
4404  cell_attached_data.pack_callbacks_variable[callback_index] = nullptr;
4405  }
4406  else
4407  {
4408  Assert(callback_index <
4409  cell_attached_data.pack_callbacks_fixed.size(),
4410  ExcMessage("Invalid handle."));
4411 
4412  Assert(cell_attached_data.pack_callbacks_fixed[callback_index] !=
4413  nullptr,
4414  ExcInternalError());
4415  cell_attached_data.pack_callbacks_fixed[callback_index] = nullptr;
4416  }
4417 # endif
4418 
4419  // perform unpacking
4420  data_transfer.unpack_data(local_quadrant_cell_relations,
4421  handle,
4422  unpack_callback);
4423 
4424  // decrease counters
4425  --cell_attached_data.n_attached_data_sets;
4426  if (cell_attached_data.n_attached_deserialize > 0)
4427  --cell_attached_data.n_attached_deserialize;
4428 
4429  // important: only remove data if we are not in the deserialization
4430  // process. There, each SolutionTransfer registers and unpacks before
4431  // the next one does this, so n_attached_data_sets is only 1 here. This
4432  // would destroy the saved data before the second SolutionTransfer can
4433  // get it. This created a bug that is documented in
4434  // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
4435  if (cell_attached_data.n_attached_data_sets == 0 &&
4436  cell_attached_data.n_attached_deserialize == 0)
4437  {
4438  // everybody got their data, time for cleanup!
4439  cell_attached_data.pack_callbacks_fixed.clear();
4440  cell_attached_data.pack_callbacks_variable.clear();
4441  data_transfer.clear();
4442 
4443  // reset all cell_status entries after coarsening/refinement
4444  for (auto &quad_cell_rel : local_quadrant_cell_relations)
4445  std::get<1>(quad_cell_rel) =
4447  }
4448  }
4449 
4450 
4451 
4452  template <int dim, int spacedim>
4453  const std::vector<types::global_dof_index> &
4455  const
4456  {
4457  return p4est_tree_to_coarse_cell_permutation;
4458  }
4459 
4460 
4461 
4462  template <int dim, int spacedim>
4463  const std::vector<types::global_dof_index> &
4465  const
4466  {
4468  }
4469 
4470 
4471 
4472  template <int dim, int spacedim>
4473  std::map<unsigned int, std::set<::types::subdomain_id>>
4475  {
4476  Assert(dim > 1, ExcNotImplemented());
4477 
4478  return ::internal::p4est::compute_vertices_with_ghost_neighbors<
4479  dim,
4480  spacedim>(*this, this->parallel_forest, this->parallel_ghost);
4481  }
4482 
4483 
4484 
4485  template <int dim, int spacedim>
4486  std::vector<bool>
4488  const int level) const
4489  {
4490  Assert(dim > 1, ExcNotImplemented());
4491 
4492  std::vector<bool> marked_vertices(this->n_vertices(), false);
4493  cell_iterator cell = this->begin(level), endc = this->end(level);
4494  for (; cell != endc; ++cell)
4495  if (cell->level_subdomain_id() == this->locally_owned_subdomain())
4496  for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell;
4497  ++v)
4498  marked_vertices[cell->vertex_index(v)] = true;
4499 
4505  typename std::map<std::pair<cell_iterator, unsigned int>,
4506  std::pair<std::pair<cell_iterator, unsigned int>,
4507  std::bitset<3>>>::const_iterator it;
4508 
4509  // When a connectivity in the code below is detected, the assignment
4510  // 'marked_vertices[v1] = marked_vertices[v2] = true' makes sure that
4511  // the information about the periodicity propagates back to vertices on
4512  // cells that are not owned locally. However, in the worst case we want
4513  // to connect to a vertex that is 'dim' hops away from the locally owned
4514  // cell. Depending on the order of the periodic face map, we might
4515  // connect to that point by chance or miss it. However, after looping
4516  // through all the periodict directions (which are at most as many as
4517  // the number of space dimensions) we can be sure that all connections
4518  // to vertices have been created.
4519  for (unsigned int repetition = 0; repetition < dim; ++repetition)
4520  for (it = this->get_periodic_face_map().begin();
4521  it != this->get_periodic_face_map().end();
4522  ++it)
4523  {
4524  const cell_iterator & cell_1 = it->first.first;
4525  const unsigned int face_no_1 = it->first.second;
4526  const cell_iterator & cell_2 = it->second.first.first;
4527  const unsigned int face_no_2 = it->second.first.second;
4528  const std::bitset<3> &face_orientation = it->second.second;
4529 
4530  if (cell_1->level() == level && cell_2->level() == level)
4531  {
4532  for (unsigned int v = 0;
4533  v < GeometryInfo<dim - 1>::vertices_per_cell;
4534  ++v)
4535  {
4536  // take possible non-standard orientation of faces into
4537  // account
4538  const unsigned int vface0 =
4540  v,
4541  face_orientation[0],
4542  face_orientation[1],
4543  face_orientation[2]);
4544  if (marked_vertices[cell_1->face(face_no_1)->vertex_index(
4545  vface0)] ||
4546  marked_vertices[cell_2->face(face_no_2)->vertex_index(
4547  v)])
4548  marked_vertices[cell_1->face(face_no_1)->vertex_index(
4549  vface0)] =
4550  marked_vertices[cell_2->face(face_no_2)->vertex_index(
4551  v)] = true;
4552  }
4553  }
4554  }
4555 
4556  return marked_vertices;
4557  }
4558 
4559 
4560 
4561  template <int dim, int spacedim>
4562  void
4564  const std::vector<::GridTools::PeriodicFacePair<cell_iterator>>
4565  &periodicity_vector)
4566  {
4568  ExcMessage("The triangulation is empty!"));
4569  Assert(this->n_levels() == 1,
4570  ExcMessage("The triangulation is refined!"));
4571 
4572  using FaceVector =
4573  std::vector<::GridTools::PeriodicFacePair<cell_iterator>>;
4574  typename FaceVector::const_iterator it, periodic_end;
4575  it = periodicity_vector.begin();
4576  periodic_end = periodicity_vector.end();
4577 
4578  for (; it < periodic_end; ++it)
4579  {
4580  const cell_iterator first_cell = it->cell[0];
4581  const cell_iterator second_cell = it->cell[1];
4582  const unsigned int face_left = it->face_idx[0];
4583  const unsigned int face_right = it->face_idx[1];
4584 
4585  // respective cells of the matching faces in p4est
4586  const unsigned int tree_left =
4587  coarse_cell_to_p4est_tree_permutation[std::distance(this->begin(),
4588  first_cell)];
4589  const unsigned int tree_right =
4590  coarse_cell_to_p4est_tree_permutation[std::distance(this->begin(),
4591  second_cell)];
4592 
4593  // p4est wants to know which corner the first corner on
4594  // the face with the lower id is mapped to on the face with
4595  // with the higher id. For d==2 there are only two possibilities
4596  // that are determined by it->orientation[1].
4597  // For d==3 we have to use GridTools::OrientationLookupTable.
4598  // The result is given below.
4599 
4600  unsigned int p4est_orientation = 0;
4601  if (dim == 2)
4602  p4est_orientation = it->orientation[1];
4603  else
4604  {
4605  const unsigned int face_idx_list[] = {face_left, face_right};
4606  const cell_iterator cell_list[] = {first_cell, second_cell};
4607  unsigned int lower_idx, higher_idx;
4608  if (face_left <= face_right)
4609  {
4610  higher_idx = 1;
4611  lower_idx = 0;
4612  }
4613  else
4614  {
4615  higher_idx = 0;
4616  lower_idx = 1;
4617  }
4618 
4619  // get the cell index of the first index on the face with the
4620  // lower id
4621  unsigned int first_p4est_idx_on_cell =
4622  p8est_face_corners[face_idx_list[lower_idx]][0];
4623  unsigned int first_dealii_idx_on_face =
4625  for (unsigned int i = 0; i < GeometryInfo<dim>::vertices_per_face;
4626  ++i)
4627  {
4628  const unsigned int first_dealii_idx_on_cell =
4630  face_idx_list[lower_idx],
4631  i,
4632  cell_list[lower_idx]->face_orientation(
4633  face_idx_list[lower_idx]),
4634  cell_list[lower_idx]->face_flip(face_idx_list[lower_idx]),
4635  cell_list[lower_idx]->face_rotation(
4636  face_idx_list[lower_idx]));
4637  if (first_p4est_idx_on_cell == first_dealii_idx_on_cell)
4638  {
4639  first_dealii_idx_on_face = i;
4640  break;
4641  }
4642  }
4643  Assert(first_dealii_idx_on_face != numbers::invalid_unsigned_int,
4644  ExcInternalError());
4645  // Now map dealii_idx_on_face according to the orientation
4646  const unsigned int left_to_right[8][4] = {{0, 2, 1, 3},
4647  {0, 1, 2, 3},
4648  {3, 1, 2, 0},
4649  {3, 2, 1, 0},
4650  {2, 3, 0, 1},
4651  {1, 3, 0, 2},
4652  {1, 0, 3, 2},
4653  {2, 0, 3, 1}};
4654  const unsigned int right_to_left[8][4] = {{0, 2, 1, 3},
4655  {0, 1, 2, 3},
4656  {3, 1, 2, 0},
4657  {3, 2, 1, 0},
4658  {2, 3, 0, 1},
4659  {2, 0, 3, 1},
4660  {1, 0, 3, 2},
4661  {1, 3, 0, 2}};
4662  const unsigned int second_dealii_idx_on_face =
4663  lower_idx == 0 ? left_to_right[it->orientation.to_ulong()]
4664  [first_dealii_idx_on_face] :
4665  right_to_left[it->orientation.to_ulong()]
4666  [first_dealii_idx_on_face];
4667  const unsigned int second_dealii_idx_on_cell =
4669  face_idx_list[higher_idx],
4670  second_dealii_idx_on_face,
4671  cell_list[higher_idx]->face_orientation(
4672  face_idx_list[higher_idx]),
4673  cell_list[higher_idx]->face_flip(face_idx_list[higher_idx]),
4674  cell_list[higher_idx]->face_rotation(
4675  face_idx_list[higher_idx]));
4676  // map back to p4est
4677  const unsigned int second_p4est_idx_on_face =
4678  p8est_corner_face_corners[second_dealii_idx_on_cell]
4679  [face_idx_list[higher_idx]];
4680  p4est_orientation = second_p4est_idx_on_face;
4681  }
4682 
4684  connectivity,
4685  tree_left,
4686  tree_right,
4687  face_left,
4688  face_right,
4689  p4est_orientation);
4690  }
4691 
4692 
4694  connectivity) == 1,
4695  ExcInternalError());
4696 
4697  // now create a forest out of the connectivity data structure
4700  this->mpi_communicator,
4701  connectivity,
4702  /* minimum initial number of quadrants per tree */ 0,
4703  /* minimum level of upfront refinement */ 0,
4704  /* use uniform upfront refinement */ 1,
4705  /* user_data_size = */ 0,
4706  /* user_data_constructor = */ nullptr,
4707  /* user_pointer */ this);
4708 
4709 
4710  try
4711  {
4713  }
4714  catch (const typename Triangulation<dim>::DistortedCellList &)
4715  {
4716  // the underlying triangulation should not be checking for distorted
4717  // cells
4718  Assert(false, ExcInternalError());
4719  }
4720 
4721  // finally call the base class for storing the periodicity information
4723 
4724  // The range of ghost_owners might have changed so update that information
4725  this->update_number_cache();
4726  }
4727 
4728 
4729 
4730  template <int dim, int spacedim>
4731  std::size_t
4733  {
4734  std::size_t mem =
4735  this->::parallel::Triangulation<dim,
4736  spacedim>::memory_consumption() +
4739  MemoryConsumption::memory_consumption(parallel_forest) +
4741  cell_attached_data.n_attached_data_sets) +
4742  // MemoryConsumption::memory_consumption(cell_attached_data.pack_callbacks_fixed)
4743  // +
4744  // MemoryConsumption::memory_consumption(cell_attached_data.pack_callbacks_variable)
4745  // +
4746  // TODO[TH]: how?
4748  coarse_cell_to_p4est_tree_permutation) +
4750  p4est_tree_to_coarse_cell_permutation) +
4752 
4753  return mem;
4754  }
4755 
4756 
4757 
4758  template <int dim, int spacedim>
4759  std::size_t
4761  {
4762  return ::internal::p4est::functions<dim>::forest_memory_used(
4763  parallel_forest) +
4765  connectivity);
4766  }
4767 
4768 
4769 
4770  template <int dim, int spacedim>
4771  void
4773  const ::Triangulation<dim, spacedim> &other_tria)
4774  {
4775  try
4776  {
4778  other_tria);
4779  }
4780  catch (
4781  const typename ::Triangulation<dim, spacedim>::DistortedCellList
4782  &)
4783  {
4784  // the underlying triangulation should not be checking for distorted
4785  // cells
4786  Assert(false, ExcInternalError());
4787  }
4788 
4789  // note that now we have some content in the p4est objects and call the
4790  // functions that do the actual work (which are dimension dependent, so
4791  // separate)
4793 
4794  Assert(other_tria.n_levels() == 1,
4795  ExcMessage(
4796  "Parallel distributed triangulations can only be copied, "
4797  "if they are not refined!"));
4798 
4799  if (const ::parallel::distributed::Triangulation<dim, spacedim>
4800  *other_tria_x =
4801  dynamic_cast<const ::parallel::distributed::
4802  Triangulation<dim, spacedim> *>(&other_tria))
4803  {
4804  coarse_cell_to_p4est_tree_permutation =
4805  other_tria_x->coarse_cell_to_p4est_tree_permutation;
4806  p4est_tree_to_coarse_cell_permutation =
4807  other_tria_x->p4est_tree_to_coarse_cell_permutation;
4808  cell_attached_data = other_tria_x->cell_attached_data;
4809  data_transfer = other_tria_x->data_transfer;
4810 
4811  settings = other_tria_x->settings;
4812  }
4813  else
4814  {
4816  }
4817 
4818  copy_new_triangulation_to_p4est(std::integral_constant<int, dim>());
4819 
4820  try
4821  {
4823  }
4824  catch (const typename Triangulation<dim>::DistortedCellList &)
4825  {
4826  // the underlying triangulation should not be checking for distorted
4827  // cells
4828  Assert(false, ExcInternalError());
4829  }
4830 
4831  this->update_number_cache();
4832  this->update_periodic_face_map();
4833  }
4834 
4835 
4836 
4837  template <int dim, int spacedim>
4838  void
4840  {
4841  // reorganize memory for local_quadrant_cell_relations
4843  parallel_forest->local_num_quadrants);
4844  local_quadrant_cell_relations.shrink_to_fit();
4845 
4846  // recurse over p4est
4847  for (typename Triangulation<dim, spacedim>::cell_iterator cell =
4848  this->begin(0);
4849  cell != this->end(0);
4850  ++cell)
4851  {
4852  // skip coarse cells that are not ours
4853  if (tree_exists_locally<dim, spacedim>(
4854  parallel_forest,
4855  coarse_cell_to_p4est_tree_permutation[cell->index()]) == false)
4856  continue;
4857 
4858  // initialize auxiliary top level p4est quadrant
4859  typename ::internal::p4est::types<dim>::quadrant
4860  p4est_coarse_cell;
4861  ::internal::p4est::init_coarse_quadrant<dim>(p4est_coarse_cell);
4862 
4863  // determine tree to start recursion on
4864  typename ::internal::p4est::types<dim>::tree *tree =
4865  init_tree(cell->index());
4866 
4867  update_quadrant_cell_relations_recursively<dim, spacedim>(
4868  local_quadrant_cell_relations, *tree, cell, p4est_coarse_cell);
4869  }
4870  }
4871 
4872 
4873 
4874  template <int dim, int spacedim>
4875  std::vector<unsigned int>
4877  {
4878  // check if local_quadrant_cell_relations have been previously gathered
4879  // correctly
4881  static_cast<unsigned int>(parallel_forest->local_num_quadrants),
4882  ExcInternalError());
4883 
4884  // Allocate the space for the weights. In fact we do not know yet, how
4885  // many cells we own after the refinement (only p4est knows that
4886  // at this point). We simply reserve n_active_cells space and if many
4887  // more cells are refined than coarsened than additional reallocation
4888  // will be done inside get_cell_weights_recursively.
4889  std::vector<unsigned int> weights;
4890  weights.reserve(this->n_active_cells());
4891 
4892  // Iterate over p4est and Triangulation relations
4893  // to find refined/coarsened/kept
4894  // cells. Then append cell_weight.
4895  // Note that we need to follow the p4est ordering
4896  // instead of the deal.II ordering to get the cell_weights
4897  // in the same order p4est will encounter them during repartitioning.
4898  for (const auto &quad_cell_rel : local_quadrant_cell_relations)
4899  {
4900  const auto &cell_status = std::get<1>(quad_cell_rel);
4901  const auto &cell_it = std::get<2>(quad_cell_rel);
4902 
4903  switch (cell_status)
4904  {
4906  spacedim>::CELL_PERSIST:
4907  weights.push_back(1000);
4908  weights.back() += this->signals.cell_weight(
4909  cell_it,
4911  spacedim>::CELL_PERSIST);
4912  break;
4913 
4915  spacedim>::CELL_REFINE:
4917  spacedim>::CELL_INVALID:
4918  {
4919  // calculate weight of parent cell
4920  unsigned int parent_weight = 1000;
4921  parent_weight += this->signals.cell_weight(
4922  cell_it,
4924  CELL_REFINE);
4925  // assign the weight of the parent cell equally to all
4926  // children
4927  weights.push_back(parent_weight);
4928  break;
4929  }
4930 
4932  spacedim>::CELL_COARSEN:
4933  weights.push_back(1000);
4934  weights.back() += this->signals.cell_weight(
4935  cell_it,
4937  spacedim>::CELL_COARSEN);
4938  break;
4939 
4940  default:
4941  Assert(false, ExcInternalError());
4942  break;
4943  }
4944  }
4945 
4946  return weights;
4947  }
4948 
4949 
4950 
4951  template <int spacedim>
4953  MPI_Comm mpi_communicator,
4954  const typename ::Triangulation<1, spacedim>::MeshSmoothing
4955  smooth_grid,
4956  const Settings /*settings*/)
4957  : ::parallel::Triangulation<1, spacedim>(mpi_communicator,
4958  smooth_grid,
4959  false)
4960  {
4961  Assert(false, ExcNotImplemented());
4962  }
4963 
4964 
4965  template <int spacedim>
4967  {
4968  AssertNothrow(false, ExcNotImplemented());
4969  }
4970 
4971 
4972 
4973  template <int spacedim>
4974  void
4976  const std::vector<bool> & /*vertex_locally_moved*/)
4977  {
4978  Assert(false, ExcNotImplemented());
4979  }
4980 
4981 
4982 
4983  template <int spacedim>
4984  unsigned int
4986  const std::function<std::vector<char>(
4987  const typename ::Triangulation<1, spacedim>::cell_iterator &,
4988  const typename ::Triangulation<1, spacedim>::CellStatus)>
4989  & /*pack_callback*/,
4990  const bool /*returns_variable_size_data*/)
4991  {
4992  Assert(false, ExcNotImplemented());
4993  return 0;
4994  }
4995 
4996 
4997 
4998  template <int spacedim>
4999  void
5001  const unsigned int /*handle*/,
5002  const std::function<
5003  void(const typename ::Triangulation<1, spacedim>::cell_iterator &,
5004  const typename ::Triangulation<1, spacedim>::CellStatus,
5005  const boost::iterator_range<std::vector<char>::const_iterator> &)>
5006  & /*unpack_callback*/)
5007  {
5008  Assert(false, ExcNotImplemented());
5009  }
5010 
5011 
5012 
5013  template <int spacedim>
5014  const std::vector<types::global_dof_index> &
5016  const
5017  {
5018  static std::vector<types::global_dof_index> a;
5019  return a;
5020  }
5021 
5022 
5023 
5024  template <int spacedim>
5025  std::map<unsigned int, std::set<::types::subdomain_id>>
5027  {
5028  Assert(false, ExcNotImplemented());
5029  return std::map<unsigned int, std::set<::types::subdomain_id>>();
5030  }
5031 
5032 
5033 
5034  template <int spacedim>
5035  std::map<unsigned int, std::set<::types::subdomain_id>>
5037  const unsigned int /*level*/) const
5038  {
5039  Assert(false, ExcNotImplemented());
5040 
5041  return std::map<unsigned int, std::set<::types::subdomain_id>>();
5042  }
5043 
5044 
5045 
5046  template <int spacedim>
5047  std::vector<bool>
5049  const unsigned int) const
5050  {
5051  Assert(false, ExcNotImplemented());
5052  return std::vector<bool>();
5053  }
5054 
5055 
5056 
5057  template <int spacedim>
5058  void
5059  Triangulation<1, spacedim>::load(const char *, const bool)
5060  {
5061  Assert(false, ExcNotImplemented());
5062  }
5063 
5064 
5065 
5066  template <int spacedim>
5067  void
5069  {
5070  Assert(false, ExcNotImplemented());
5071  }
5072 
5073  } // namespace distributed
5074 } // namespace parallel
5075 
5076 
5077 #endif // DEAL_II_WITH_P4EST
5078 
5079 
5080 
5081 /*-------------- Explicit Instantiations -------------------------------*/
5082 #include "tria.inst"
5083 
5084 
5085 DEAL_II_NAMESPACE_CLOSE
void write_mesh_vtk(const char *file_basename) const
Definition: tria.cc:2675
unsigned int register_data_attach(const std::function< std::vector< char >(const cell_iterator &, const CellStatus)> &pack_callback, const bool returns_variable_size_data)
Definition: tria.cc:4342
static const unsigned int invalid_unsigned_int
Definition: types.h:173
#define AssertNothrow(cond, exc)
Definition: exceptions.h:1278
const std::vector< Point< spacedim > > & get_vertices() const
types::subdomain_id locally_owned_subdomain() const override
Definition: tria_base.cc:335
cell_iterator end() const
Definition: tria.cc:12004
types::subdomain_id my_subdomain
Definition: tria_base.h:184
static unsigned int face_to_cell_vertices(const unsigned int face, const unsigned int vertex, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
unsigned int n_active_lines() const
Definition: tria.cc:12743
static::ExceptionBase & ExcIO()
std::vector< Point< spacedim > > vertices
Definition: tria.h:3662
boost::signals2::signal< void()> pre_distributed_refinement
Definition: tria.h:2256
typename::Triangulation< dim, spacedim >::active_cell_iterator active_cell_iterator
Definition: tria.h:290
virtual bool has_hanging_nodes() const override
Definition: tria.cc:2627
void pack_data(const std::vector< quadrant_cell_relation_t > &quad_cell_relations, const std::vector< typename CellAttachedData::pack_callback_t > &pack_callbacks_fixed, const std::vector< typename CellAttachedData::pack_callback_t > &pack_callbacks_variable)
Definition: tria.cc:1146
const std::vector< bool > & get_used_vertices() const
Definition: tria.cc:13104
virtual std::size_t memory_consumption_p4est() const
Definition: tria.cc:4760
unsigned int get_checksum() const
Definition: tria.cc:2878
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
void load(const char *filename, const bool autopartition=true)
Definition: tria.cc:2765
Triangulation(MPI_Comm mpi_communicator, const typename::Triangulation< dim, spacedim >::MeshSmoothing smooth_grid=(::Triangulation< dim, spacedim >::none), const Settings settings=default_setting)
Definition: tria.cc:2142
virtual std::size_t memory_consumption() const override
Definition: tria.cc:4732
cell_iterator begin(const unsigned int level=0) const
Definition: tria.cc:11915
unsigned int n_active_cells() const
Definition: tria.cc:12509
std::vector< unsigned int > get_cell_weights() const
Definition: tria.cc:4876
typename::internal::p4est::types< dim >::ghost * parallel_ghost
Definition: tria.h:878
unsigned int n_levels() const
typename::internal::p4est::types< dim >::forest * parallel_forest
Definition: tria.h:872
virtual void add_periodicity(const std::vector< GridTools::PeriodicFacePair< cell_iterator >> &)
Definition: tria.cc:13200
virtual void execute_coarsening_and_refinement()
Definition: tria.cc:13229
virtual MPI_Comm get_communicator() const
Definition: tria_base.cc:155
void save_coarsen_flags(std::ostream &out) const
Definition: tria.cc:10875
virtual void copy_triangulation(const ::Triangulation< dim, spacedim > &old_tria) override
Definition: tria_base.cc:66
const std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, std::bitset< 3 > > > & get_periodic_face_map() const
Definition: tria.cc:13220
virtual bool prepare_coarsening_and_refinement()
Definition: tria.cc:13935
static::ExceptionBase & ExcMessage(std::string arg1)
unsigned int subdomain_id
Definition: types.h:43
virtual bool prepare_coarsening_and_refinement() override
Definition: tria.cc:3418
Triangulation(const MeshSmoothing smooth_grid=none, const bool check_for_distorted_cells=false)
Definition: tria.cc:10129
unsigned int n_cells() const
Definition: tria.cc:12501
T sum(const T &t, const MPI_Comm &mpi_communicator)
virtual void create_triangulation(const std::vector< Point< spacedim >> &vertices, const std::vector< CellData< dim >> &cells, const SubCellData &subcelldata)
Definition: tria.cc:10556
std::vector< bool > mark_locally_active_vertices_on_level(const int level) const
Definition: tria.cc:4487
const std::vector< types::global_dof_index > & get_p4est_tree_to_coarse_cell_permutation() const
Definition: tria.cc:4454
#define Assert(cond, exc)
Definition: exceptions.h:1227
virtual void update_number_cache()
Definition: tria_base.cc:163
Signals signals
Definition: tria.h:2287
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
void copy_new_triangulation_to_p4est(std::integral_constant< int, 2 >)
void notify_ready_to_unpack(const unsigned int handle, const std::function< void(const cell_iterator &, const CellStatus, const boost::iterator_range< std::vector< char >::const_iterator > &)> &unpack_callback)
Definition: tria.cc:4372
virtual unsigned int n_global_levels() const override
Definition: tria_base.cc:133
boost::signals2::signal< void()> pre_distributed_save
Definition: tria.h:2274
void save_refine_flags(std::ostream &out) const
Definition: tria.cc:10807
static unsigned int standard_to_real_face_vertex(const unsigned int vertex, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
std::vector< unsigned int > invert_permutation(const std::vector< unsigned int > &permutation)
Definition: utilities.cc:503
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition: utilities.h:1046
active_cell_iterator last_active() const
Definition: tria.cc:11983
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
Definition: mpi.cc:69
virtual void update_number_cache() override
Definition: tria.cc:2890
std::vector< quadrant_cell_relation_t > local_quadrant_cell_relations
Definition: tria.h:932
void reorder_hierarchical(const DynamicSparsityPattern &sparsity, std::vector< DynamicSparsityPattern::size_type > &new_indices)
const types::subdomain_id artificial_subdomain_id
Definition: types.h:272
void communicate_locally_moved_vertices(const std::vector< bool > &vertex_locally_moved)
Definition: tria.cc:4171
#define AssertThrowMPI(error_code)
Definition: exceptions.h:1443
void update_periodic_face_map()
Definition: tria.cc:13288
virtual ~Triangulation() override
Definition: tria.cc:2172
MeshSmoothing smooth_grid
Definition: tria.h:3379
boost::signals2::signal< unsigned int(const cell_iterator &, const CellStatus), CellWeightSum< unsigned int > > cell_weight
Definition: tria.h:2243
void setup_coarse_cell_to_p4est_tree_permutation()
Definition: tria.cc:2658
virtual void copy_triangulation(const ::Triangulation< dim, spacedim > &other_tria) override
Definition: tria.cc:4772
T unpack(const std::vector< char > &buffer, const bool allow_compression=true)
Definition: utilities.h:1186
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
Definition: mpi.cc:80
static::ExceptionBase & ExcNotImplemented()
void save(const char *filename) const
Definition: tria.cc:2689
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: tria.cc:11935
virtual void execute_coarsening_and_refinement() override
Definition: tria.cc:3810
std::vector< unsigned int > compute_point_to_point_communication_pattern(const MPI_Comm &mpi_comm, const std::vector< unsigned int > &destinations)
Definition: mpi.cc:184
boost::signals2::signal< void()> post_distributed_load
Definition: tria.h:2281
typename::Triangulation< dim, spacedim >::cell_iterator cell_iterator
Definition: tria.h:269
virtual void create_triangulation(const std::vector< Point< spacedim >> &vertices, const std::vector< CellData< dim >> &cells, const SubCellData &subcelldata) override
Definition: tria.cc:2193
unsigned int n_vertices() const
typename::internal::p4est::types< dim >::tree * init_tree(const int dealii_coarse_cell_index) const
Definition: tria.cc:2902
const std::vector< types::global_dof_index > & get_coarse_cell_to_p4est_tree_permutation() const
Definition: tria.cc:4464
T max(const T &t, const MPI_Comm &mpi_communicator)
virtual void clear()
Definition: tria.cc:10232
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
std::vector< types::global_dof_index > coarse_cell_to_p4est_tree_permutation
Definition: tria.h:1136
virtual void clear() override
Definition: tria.cc:2588
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
static::ExceptionBase & ExcInternalError()
virtual std::map< unsigned int, std::set<::types::subdomain_id > > compute_vertices_with_ghost_neighbors() const override
Definition: tria.cc:4474
boost::signals2::signal< void()> post_distributed_refinement
Definition: tria.h:2266
virtual void add_periodicity(const std::vector<::GridTools::PeriodicFacePair< cell_iterator >> &) override
Definition: tria.cc:4563