Reference documentation for deal.II version 8.5.1
fe_tools_extrapolate.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 2017 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/distributed/p4est_wrappers.h>
17 #include <deal.II/distributed/tria.h>
18 #include <deal.II/fe/fe_tools.h>
19 #include <deal.II/grid/tria.h>
20 #include <deal.II/dofs/dof_handler.h>
21 #include <deal.II/dofs/dof_tools.h>
22 #include <deal.II/lac/block_vector.h>
23 #include <deal.II/lac/constraint_matrix.h>
24 #include <deal.II/lac/la_vector.h>
25 #include <deal.II/lac/la_parallel_vector.h>
26 #include <deal.II/lac/la_parallel_block_vector.h>
27 #include <deal.II/lac/petsc_parallel_vector.h>
28 #include <deal.II/lac/petsc_block_vector.h>
29 #include <deal.II/lac/petsc_parallel_block_vector.h>
30 #include <deal.II/lac/trilinos_vector.h>
31 #include <deal.II/lac/trilinos_block_vector.h>
32 
33 #include <queue>
34 
35 DEAL_II_NAMESPACE_OPEN
36 
37 namespace FETools
38 {
39 
40  namespace internal
41  {
42 #ifndef DEAL_II_WITH_P4EST
43  // Dummy implementation in case p4est is not available.
44  template <int dim,int spacedim,class OutVector>
45  class ExtrapolateImplementation
46  {
47  public:
48 
49  ExtrapolateImplementation ()
50  {
51  Assert(false, ExcNotImplemented());
52  };
53 
54  template <class InVector>
55  void extrapolate_parallel (const InVector &/*u2_relevant*/,
56  const DoFHandler<dim,spacedim> &/*dof2*/,
57  OutVector &/*u2*/)
58  {
59  Assert(false, ExcNotImplemented())
60  }
61  };
62 #else
63  // Implementation of the @p extrapolate function
64  // on parallel distributed grids.
65  template <int dim,int spacedim,class OutVector>
66  class ExtrapolateImplementation
67  {
68  public:
69 
70  ExtrapolateImplementation ();
71 
72  template <class InVector>
73  void extrapolate_parallel (const InVector &u2_relevant,
74  const DoFHandler<dim,spacedim> &dof2,
75  OutVector &u2);
76 
77  private:
78  // A shortcut for the type of the OutVector
79  typedef typename OutVector::value_type value_type;
80 
81  // A structure holding all data to
82  // set dofs recursively on cells of arbitrary level
83  struct WorkPackage
84  {
85  const typename ::internal::p4est::types<dim>::forest forest;
86  const typename ::internal::p4est::types<dim>::tree tree;
87  const typename ::internal::p4est::types<dim>::locidx tree_index;
88  const typename DoFHandler<dim,spacedim>::cell_iterator dealii_cell;
89  const typename ::internal::p4est::types<dim>::quadrant p4est_cell;
90 
91  WorkPackage(const typename ::internal::p4est::types<dim>::forest &forest_,
92  const typename ::internal::p4est::types<dim>::tree &tree_,
93  const typename ::internal::p4est::types<dim>::locidx &tree_index_,
94  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell_,
95  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell_)
96  :
97  forest(forest_),
98  tree(tree_),
99  tree_index(tree_index_),
100  dealii_cell(dealii_cell_),
101  p4est_cell(p4est_cell_)
102  {}
103  };
104 
105 
106  // A structure holding all data
107  // of cells needed from other processes
108  // for the extrapolate algorithm.
109  struct CellData
110  {
111  CellData ();
112 
113  CellData (const unsigned int dofs_per_cell);
114 
115  Vector<value_type> dof_values;
116 
117  unsigned int tree_index;
118 
119  typename ::internal::p4est::types<dim>::quadrant quadrant;
120 
121  int receiver;
122 
123  bool operator < (const CellData &rhs) const
124  {
125  if (::internal::p4est::functions<dim>::quadrant_compare (&quadrant, &rhs.quadrant) < 0)
126  return true;
127 
128  return false;
129  }
130 
131  unsigned int bytes_for_buffer () const
132  {
133  return (sizeof(unsigned int) + // dofs_per_cell
134  dof_values.size() * sizeof(value_type) + // dof_values
135  sizeof(unsigned int) + // tree_index
136  sizeof(typename ::internal::p4est::types<dim>::quadrant)); // quadrant
137  }
138 
139  void pack_data (std::vector<char> &buffer) const
140  {
141  buffer.resize(bytes_for_buffer());
142 
143  char *ptr = &buffer[0];
144 
145  unsigned int n_dofs = dof_values.size ();
146  std::memcpy(ptr, &n_dofs, sizeof(unsigned int));
147  ptr += sizeof(unsigned int);
148 
149  std::memcpy(ptr,dof_values.begin(),n_dofs*sizeof(value_type));
150  ptr += n_dofs*sizeof(value_type);
151 
152  std::memcpy(ptr,&tree_index,sizeof(unsigned int));
153  ptr += sizeof(unsigned int);
154 
155  std::memcpy(ptr,&quadrant,sizeof(typename ::internal::p4est::types<dim>::quadrant));
156  ptr += sizeof(typename ::internal::p4est::types<dim>::quadrant);
157 
158  Assert (ptr == &buffer[0]+buffer.size(),
159  ExcInternalError());
160  }
161 
162  void unpack_data (const std::vector<char> &buffer)
163  {
164  const char *ptr = &buffer[0];
165  unsigned int n_dofs;
166  memcpy(&n_dofs, ptr, sizeof(unsigned int));
167  ptr += sizeof(unsigned int);
168 
169  dof_values.reinit(n_dofs);
170  std::memcpy(dof_values.begin(),ptr,n_dofs * sizeof(value_type));
171  ptr += n_dofs * sizeof(value_type);
172 
173  std::memcpy(&tree_index,ptr,sizeof(unsigned int));
174  ptr += sizeof(unsigned int);
175 
176  std::memcpy(&quadrant,ptr,sizeof(typename ::internal::p4est::types<dim>::quadrant));
177  ptr += sizeof(typename ::internal::p4est::types<dim>::quadrant);
178 
179  Assert (ptr == &buffer[0]+buffer.size(),
180  ExcInternalError());
181  }
182  };
183 
184  // Problem: The function extrapolates a polynomial
185  // function from a finer mesh of size @f$h@f$ to a polynmial
186  // function of higher degree but on a coarser mesh of
187  // size @f$2h@f$. Therefor the mesh has to consist of patches
188  // of four (2d) or eight (3d) cells and the function requires
189  // that the mesh is refined globally at least once.
190  // The algorithm starts on the coarsest level of the grid,
191  // loops over all cells and if a cell has at least one active child,
192  // dof values are set via
193  // cell->get_interpolated_dof_values(u_input, dof_values)
194  // cell->set_dof_values_by_interpolation(dof_values, u_output)
195  // both *_interpolation_* functions traverse recursively
196  // over all children down to the active cells
197  // and get/set dof values by interpolation.
198  //
199  // On distributed parallel grids the problem arises, that
200  // if a cell has at least one active child, there is no guarantee
201  // that all children of this cell belong to this process.
202  // There might be children which are owned by other processes
203  // and the algorithm needs to find and has to get the
204  // dof values from these processes and so on.
205  //
206  // Algorithm:
207  // 1) Loop over all coarse cells
208  // From each coarse cell traverse down the tree
209  // of refined cells and search for active children
210  // If there is an active child, check, if all
211  // other children down to the finest level are part
212  // of this process, if not, add the cell to the list
213  // of needs.
214  // 2) Send the list of needs to other processes
215  // Each process has a list of needs and after
216  // the loop over all coarse cells (all trees)
217  // is finished, this list can be send to other processes.
218  // 3) Compute the needs required by other processes
219  // While computing the values required from other
220  // processes there can arise new needs and they are
221  // stored in a list again.
222  // 4) Send the computed values and the list of new needs around
223  //
224  // This procedure has to be repeated until no process needs any
225  // new need and all needs are computed, but there are at most the
226  // "number of grid levels" rounds of sending/receiving cell data.
227  //
228  // Then each process has all data needed for extrapolation.
229 
230  // driver function sending/receiving all values from
231  // different processes
232  template <class InVector>
233  void compute_all_non_local_data (const DoFHandler<dim,spacedim> &dof2,
234  const InVector &u);
235 
236  // traverse recursively over
237  // the cells of this tree and
238  // interpolate over patches which
239  // are part of this process
240  template <class InVector>
241  void interpolate_recursively (const typename ::internal::p4est::types<dim>::forest &forest,
242  const typename ::internal::p4est::types<dim>::tree &tree,
243  const typename ::internal::p4est::types<dim>::locidx &tree_index,
244  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
245  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
246  const InVector &u1,
247  OutVector &u2);
248 
249  // get dof values for this
250  // cell by interpolation
251  // if a child is reached which
252  // is not part of this process
253  // a new need is created
254  template <class InVector>
255  void get_interpolated_dof_values (const typename ::internal::p4est::types<dim>::forest &forest,
256  const typename ::internal::p4est::types<dim>::tree &tree,
257  const typename ::internal::p4est::types<dim>::locidx &tree_index,
258  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
259  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
260  const InVector &u,
261  Vector<value_type> &interpolated_values,
262  std::vector<CellData> &new_needs);
263 
264  // set dof values for this
265  // cell by interpolation
266  void set_dof_values_by_interpolation (const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
267  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
268  const Vector<value_type> &interpolated_values,
269  OutVector &u);
270 
271  // compute all cell_data
272  // needed from other processes
273  // to interpolate the part of
274  // this process
275  void compute_needs (const DoFHandler<dim,spacedim> &dof2,
276  std::vector<CellData> &new_needs);
277 
278  // traverse over the tree
279  // and look for patches this
280  // process has to work on
281  void traverse_tree_recursively (const typename ::internal::p4est::types<dim>::forest &forest,
282  const typename ::internal::p4est::types<dim>::tree &tree,
283  const typename ::internal::p4est::types<dim>::locidx &tree_index,
284  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
285  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
286  std::vector<CellData> &new_needs);
287 
288  // traverse recursively
289  // over a patch and look
290  // for cells needed from
291  // other processes for interpolation
292  void traverse_patch_recursively (const typename ::internal::p4est::types<dim>::forest &forest,
293  const typename ::internal::p4est::types<dim>::tree &tree,
294  const typename ::internal::p4est::types<dim>::locidx &tree_index,
295  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
296  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
297  std::vector<CellData> &new_needs);
298 
299  // compute dof values of all
300  // cells collected in cells_to_compute
301  // computed cells are deleted
302  // from cells_to_compute and
303  // stored in computed_cells
304  // during computation there can
305  // be new cells needed from
306  // other processes, these cells
307  // are stored in new_needs
308  template <class InVector>
309  void compute_cells (const DoFHandler<dim,spacedim> &dof2,
310  const InVector &u,
311  std::vector<CellData> &cells_to_compute,
312  std::vector<CellData> &computed_cells,
313  std::vector<CellData> &new_needs);
314 
315  // traverse over the tree
316  // and compute cells
317  template <class InVector>
318  void compute_cells_in_tree_recursively (const typename ::internal::p4est::types<dim>::forest &forest,
319  const typename ::internal::p4est::types<dim>::tree &tree,
320  const typename ::internal::p4est::types<dim>::locidx &tree_index,
321  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
322  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
323  const InVector &u,
324  std::vector<CellData> &cells_to_compute,
325  std::vector<CellData> &computed_cells,
326  std::vector<CellData> &new_needs);
327 
328  // send all cell_data in the vector
329  // cells_to_send to their receivers
330  // and receives a vector of cell_data
331  void send_cells (const std::vector<CellData> &cells_to_send,
332  std::vector<CellData> &received_cells) const;
333 
334  // add new cell_data to
335  // the ordered list new_needs
336  // uses cell_data_insert
337  static void add_new_need (const typename ::internal::p4est::types<dim>::forest &forest,
338  const typename ::internal::p4est::types<dim>::locidx &tree_index,
339  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
340  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
341  std::vector<CellData> &new_needs);
342 
343  // binary search in cells_list
344  // assume that cells_list
345  // is ordered
346  static int cell_data_search (const CellData &cell_data,
347  const std::vector<CellData> &cells_list);
348 
349  // insert cell_data into a sorted
350  // vector cells_list at the correct
351  // position if cell_data
352  // not exists already in cells_list
353  static void cell_data_insert (const CellData &cell_data,
354  std::vector<CellData> &cells_list);
355 
356  MPI_Comm communicator;
357 
358  // a vector of all cells this process has
359  // computed or received data
360  std::vector<CellData> available_cells;
361 
362  // stores the indices of dofs on more refined ghosted cells along
363  // with the maximum level
364  std::map<types::global_dof_index, int> dofs_on_refined_neighbors;
365 
366  // counts the send/receive round we are in
367  unsigned int round;
368  };
369 
370  template <class OutVector>
371  class ExtrapolateImplementation<1,1,OutVector>
372  {
373  public:
374 
375  ExtrapolateImplementation ()
376  {
378  }
379 
380  template <class InVector>
381  void extrapolate_parallel (const InVector &/*u2_relevant*/,
382  const DoFHandler<1,1> &/*dof2*/,
383  OutVector &/*u2*/)
384  {}
385  };
386 
387  template <class OutVector>
388  class ExtrapolateImplementation<1,2,OutVector>
389  {
390  public:
391 
392  ExtrapolateImplementation ()
393  {
395  }
396 
397  template <class InVector>
398  void extrapolate_parallel (const InVector &/*u2_relevant*/,
399  const DoFHandler<1,2> &/*dof2*/,
400  OutVector &/*u2*/)
401  {}
402  };
403 
404  template <class OutVector>
405  class ExtrapolateImplementation<1,3,OutVector>
406  {
407  public:
408 
409  ExtrapolateImplementation ()
410  {
412  }
413 
414  template <class InVector>
415  void extrapolate_parallel (const InVector &/*u2_relevant*/,
416  const DoFHandler<1,3> &/*dof2*/,
417  OutVector &/*u2*/)
418  {}
419  };
420 
421 
422 
423  template <int dim,int spacedim,class OutVector>
424  ExtrapolateImplementation<dim,spacedim,OutVector>::
425  ExtrapolateImplementation ()
426  : round(0)
427  {}
428 
429 
430 
431  template <int dim,int spacedim,class OutVector>
432  ExtrapolateImplementation<dim,spacedim,OutVector>::
433  CellData::CellData ()
434  : tree_index (0),
435  receiver (0)
436  {}
437 
438 
439 
440  template <int dim,int spacedim,class OutVector>
441  ExtrapolateImplementation<dim,spacedim,OutVector>::
442  CellData::CellData (const unsigned int dofs_per_cell)
443  : tree_index (0),
444  receiver (0)
445  {
446  dof_values.reinit (dofs_per_cell);
447  }
448 
449 
450 
451  template <int dim,int spacedim,class OutVector>
452  template <class InVector>
453  void
454  ExtrapolateImplementation<dim,spacedim,OutVector>::
455  interpolate_recursively (const typename ::internal::p4est::types<dim>::forest &forest,
456  const typename ::internal::p4est::types<dim>::tree &tree,
457  const typename ::internal::p4est::types<dim>::locidx &tree_index,
458  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
459  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
460  const InVector &u1,
461  OutVector &u2)
462  {
463  // check if this cell exists in the local p4est
464  int idx = sc_array_bsearch(const_cast<sc_array_t *>(&tree.quadrants),
465  &p4est_cell,
467 
468  // if neither this cell nor one of it's children belongs to us, don't do anything
469  if (idx == -1 && (::internal::p4est::functions<dim>::
470  quadrant_overlaps_tree (const_cast<typename ::internal::p4est::types<dim>::tree *>(&tree),
471  &p4est_cell)
472  == false))
473  return;
474 
475  bool p4est_has_children = (idx == -1);
476 
477  bool locally_owned_children = false;
478  if (p4est_has_children)
479  {
480  Assert (dealii_cell->has_children (), ExcInternalError ());
481 
482  // check if at least one child is locally owned on our process
483  for (unsigned int child_n=0; child_n<dealii_cell->n_children(); ++child_n)
484  if (dealii_cell->child(child_n)->active())
485  if (dealii_cell->child(child_n)->is_locally_owned())
486  {
487  locally_owned_children=true;
488  break;
489  }
490  }
491 
492  if (locally_owned_children)
493  {
494  const FiniteElement<dim,spacedim> &fe = dealii_cell->get_dof_handler().get_fe();
495  const unsigned int dofs_per_cell = fe.dofs_per_cell;
496 
497  Vector<typename OutVector::value_type> interpolated_values(dofs_per_cell);
498 
499  std::vector<CellData> new_needs;
500  get_interpolated_dof_values (forest,
501  tree,
502  tree_index,
503  dealii_cell,
504  p4est_cell,
505  u1,
506  interpolated_values,
507  new_needs);
508 
509  // at this point of
510  // the procedure no new
511  // needs should come up
512  Assert (new_needs.size () == 0,
513  ExcInternalError ());
514 
515  set_dof_values_by_interpolation (dealii_cell,
516  p4est_cell,
517  interpolated_values,
518  u2);
519  }
520 
521 
522 
523  }
524 
525 
526 
527  template <int dim,int spacedim, class OutVector>
528  template <class InVector>
529  void
530  ExtrapolateImplementation<dim,spacedim,OutVector>::
531  get_interpolated_dof_values (const typename ::internal::p4est::types<dim>::forest &forest,
532  const typename ::internal::p4est::types<dim>::tree &tree,
533  const typename ::internal::p4est::types<dim>::locidx &tree_index,
534  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
535  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
536  const InVector &u,
537  Vector<value_type> &interpolated_values,
538  std::vector<CellData> &new_needs)
539  {
540  if (!dealii_cell->has_children ())
541  {
542  if (dealii_cell->is_locally_owned ())
543  {
544  // if this is one of our cells,
545  // get dof values from input vector
546  dealii_cell->get_dof_values (u, interpolated_values);
547  }
548  else
549  {
550  add_new_need (forest,
551  tree_index,
552  dealii_cell,
553  p4est_cell,
554  new_needs);
555  }
556  }
557  else
558  {
559  const FiniteElement<dim,spacedim> &fe = dealii_cell->get_dof_handler().get_fe();
560  const unsigned int dofs_per_cell = fe.dofs_per_cell;
561 
562  Assert (interpolated_values.size() == dofs_per_cell,
563  ExcDimensionMismatch(interpolated_values.size(), dofs_per_cell));
564  Assert (u.size() == dealii_cell->get_dof_handler().n_dofs(),
565  ExcDimensionMismatch(u.size(), dealii_cell->get_dof_handler().n_dofs()));
566 
567  Vector<value_type> tmp1(dofs_per_cell);
568  Vector<value_type> tmp2(dofs_per_cell);
569 
570  interpolated_values = 0;
571  std::vector<bool> restriction_is_additive (dofs_per_cell);
572  for (unsigned int i=0; i<dofs_per_cell; ++i)
573  restriction_is_additive[i] = fe.restriction_is_additive(i);
574 
575  typename ::internal::p4est::types<dim>::quadrant
577 
578  ::internal::p4est::init_quadrant_children<dim> (p4est_cell,
579  p4est_child);
580 
581  bool found_child = true;
582  for (unsigned int c=0; c<GeometryInfo<dim>::max_children_per_cell; ++c)
583  {
585  quadrant_overlaps_tree (const_cast<typename ::internal::p4est::types<dim>::tree *>(&tree),
586  &p4est_child[c])
587  == false)
588  {
589  // this is a cell this process needs
590  // data from another process
591 
592  // check if this cell is
593  // available from other
594  // computed patches
595  CellData cell_data;
596  cell_data.quadrant = p4est_child[c];
597  int pos = cell_data_search (cell_data, available_cells);
598 
599  if (pos == -1)
600  {
601  // data is not available
602  // create a new need
603  found_child = false;
604 
605  add_new_need (forest,
606  tree_index,
607  dealii_cell->child(c),
608  p4est_child[c],
609  new_needs);
610  }
611  else
612  {
613  Assert (available_cells[pos].dof_values.size() == dofs_per_cell,
614  ExcDimensionMismatch(available_cells[pos].dof_values.size(), dofs_per_cell));
615 
616  tmp1 = available_cells[pos].dof_values;
617  }
618  }
619  else
620  {
621  // get the values from the present child, if necessary by
622  // interpolation either from its own children or
623  // by interpolating from the finite element on an active
624  // child to the finite element space requested here
625  get_interpolated_dof_values (forest,
626  tree,
627  tree_index,
628  dealii_cell->child(c),
629  p4est_child[c],
630  u,
631  tmp1,
632  new_needs);
633  }
634 
635  if (found_child)
636  {
637  // interpolate these to the mother cell
638  fe.get_restriction_matrix(c, dealii_cell->refinement_case()).vmult (tmp2, tmp1);
639 
640  // and add up or set them in the output vector
641  for (unsigned int i=0; i<dofs_per_cell; ++i)
642  if (tmp2(i) != value_type())
643  {
644  if (restriction_is_additive[i])
645  interpolated_values(i) += tmp2(i);
646  else
647  interpolated_values(i) = tmp2(i);
648  }
649  }
650  }
651 
652  if (found_child == false)
653  interpolated_values = 0;
654  }
655  }
656 
657 
658 
659  template <int dim,int spacedim,class OutVector>
660  void
661  ExtrapolateImplementation<dim,spacedim,OutVector>::
662  set_dof_values_by_interpolation (const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
663  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
664  const Vector<value_type> &local_values,
665  OutVector &u)
666  {
667  const FiniteElement<dim,spacedim> &fe = dealii_cell->get_dof_handler().get_fe();
668  const unsigned int dofs_per_cell = fe.dofs_per_cell;
669 
670  if (!dealii_cell->has_children ())
671  {
672  if (dealii_cell->is_locally_owned ())
673  {
674  std::vector<types::global_dof_index> indices(dofs_per_cell);
675  dealii_cell->get_dof_indices(indices);
676  for (unsigned int j=0; j<dofs_per_cell; ++j)
677  {
678  // don't set this dof if there is a more refined ghosted neighbor setting this dof.
679  const bool on_refined_neighbor
680  = (dofs_on_refined_neighbors.find(indices[j])!=dofs_on_refined_neighbors.end());
681  if (!(on_refined_neighbor && dofs_on_refined_neighbors[indices[j]]>dealii_cell->level()))
682  u(indices[j]) = local_values(j);
683  }
684  }
685  }
686  else
687  {
688  Assert (local_values.size() == dofs_per_cell,
689  ExcDimensionMismatch(local_values.size(), dofs_per_cell));
690  Assert (u.size() == dealii_cell->get_dof_handler().n_dofs(),
691  ExcDimensionMismatch(u.size(), dealii_cell->get_dof_handler().n_dofs()));
692 
693  Vector<value_type> tmp(dofs_per_cell);
694 
695  typename ::internal::p4est::types<dim>::quadrant
697 
698  ::internal::p4est::init_quadrant_children<dim> (p4est_cell,
699  p4est_child);
700 
701  for (unsigned int c=0; c<GeometryInfo<dim>::max_children_per_cell; ++c)
702  {
703  if (tmp.size() > 0)
704  fe.get_prolongation_matrix(c, dealii_cell->refinement_case())
705  .vmult (tmp, local_values);
706 
707  set_dof_values_by_interpolation (dealii_cell->child(c),
708  p4est_child[c],
709  tmp,
710  u);
711  }
712  }
713  }
714 
715 
716 
717  template <int dim,int spacedim,class OutVector>
718  void
719  ExtrapolateImplementation<dim,spacedim,OutVector>::
720  compute_needs (const DoFHandler<dim,spacedim> &dof2,
721  std::vector<CellData> &new_needs)
722  {
725  (&dof2.get_tria()));
726 
727  Assert (tr != 0, ExcInternalError());
728 
730  cell=dof2.begin(0),
731  endc=dof2.end(0);
732  for (; cell!=endc; ++cell)
733  {
734  if (::internal::p4est::tree_exists_locally<dim> (tr->parallel_forest,
735  tr->coarse_cell_to_p4est_tree_permutation[cell->index()])
736  == false)
737  continue;
738 
739  typename ::internal::p4est::types<dim>::quadrant p4est_coarse_cell;
740  const unsigned int tree_index = tr->coarse_cell_to_p4est_tree_permutation[cell->index()];
741  typename ::internal::p4est::types<dim>::tree *tree = tr->init_tree(cell->index());
742 
743  ::internal::p4est::init_coarse_quadrant<dim>(p4est_coarse_cell);
744 
745  // make sure that each cell on the
746  // coarsest level is at least once
747  // refined, otherwise, these cells
748  // can't be treated and would
749  // generate a bogus result
750  {
751  int idx = sc_array_bsearch(const_cast<sc_array_t *>(&tree->quadrants),
752  &p4est_coarse_cell,
754 
756  }
757 
758  traverse_tree_recursively (*tr->parallel_forest,
759  *tree,
760  tree_index,
761  cell,
762  p4est_coarse_cell,
763  new_needs);
764  }
765  }
766 
767 
768 
769  template <int dim,int spacedim,class OutVector>
770  void
771  ExtrapolateImplementation<dim,spacedim,OutVector>::
772  traverse_tree_recursively (const typename ::internal::p4est::types<dim>::forest &forest,
773  const typename ::internal::p4est::types<dim>::tree &tree,
774  const typename ::internal::p4est::types<dim>::locidx &tree_index,
775  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
776  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
777  std::vector<CellData> &new_needs)
778  {
779  // check if this cell exists in the local p4est
780  int idx = sc_array_bsearch(const_cast<sc_array_t *>(&tree.quadrants),
781  &p4est_cell,
783 
784  // if neither this cell nor one of it's children belongs to us, don't do anything
785  if (idx == -1 && (::internal::p4est::functions<dim>::
786  quadrant_overlaps_tree (const_cast<typename ::internal::p4est::types<dim>::tree *>(&tree),
787  &p4est_cell)
788  == false))
789  return;
790 
791  bool p4est_has_children = (idx == -1);
792 
793  // this cell is part of a patch
794  // this process has to interpolate on
795  // if there is at least one locally
796  // owned child
797  bool locally_owned_children = false;
798  if (p4est_has_children)
799  {
800  Assert (dealii_cell->has_children (), ExcInternalError ());
801 
802  for (unsigned int child_n=0; child_n<dealii_cell->n_children(); ++child_n)
803  if (dealii_cell->child(child_n)->active())
804  if (dealii_cell->child(child_n)->is_locally_owned())
805  {
806  locally_owned_children=true;
807  break;
808  }
809  }
810 
811  // traverse the patch recursively
812  // to find cells needed from
813  // other processes
814  if (locally_owned_children)
815  {
816  traverse_patch_recursively (forest,
817  tree,
818  tree_index,
819  dealii_cell,
820  p4est_cell,
821  new_needs);
822  }
823 
824  // traverse recursively over this tree
825  if (p4est_has_children)
826  {
827  typename ::internal::p4est::types<dim>::quadrant
829 
830  ::internal::p4est::init_quadrant_children<dim> (p4est_cell,
831  p4est_child);
832 
833  for (unsigned int c=0; c<GeometryInfo<dim>::max_children_per_cell; ++c)
834  {
835  traverse_tree_recursively (forest,
836  tree,
837  tree_index,
838  dealii_cell->child(c),
839  p4est_child[c],
840  new_needs);
841  }
842  }
843  }
844 
845 
846 
847  template <int dim,int spacedim,class OutVector>
848  void
849  ExtrapolateImplementation<dim,spacedim,OutVector>::
850  traverse_patch_recursively (const typename ::internal::p4est::types<dim>::forest &forest,
851  const typename ::internal::p4est::types<dim>::tree &tree,
852  const typename ::internal::p4est::types<dim>::locidx &tree_index,
853  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
854  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
855  std::vector<CellData> &new_needs)
856  {
857  if (dealii_cell->has_children ())
858  {
859  Assert (dealii_cell->has_children (), ExcInternalError ());
860 
861  typename ::internal::p4est::types<dim>::quadrant
863 
864  ::internal::p4est::init_quadrant_children<dim> (p4est_cell,
865  p4est_child);
866 
867  for (unsigned int c=0; c<GeometryInfo<dim>::max_children_per_cell; ++c)
868  {
869  // check if this child
870  // is locally available
871  // in the p4est
873  quadrant_overlaps_tree (const_cast<typename ::internal::p4est::types<dim>::tree *>(&tree),
874  &p4est_child[c])
875  == false)
876  {
877  // this is a cell for which this process
878  // needs data from another process
879  // so add the cell to the list
880  add_new_need (forest,
881  tree_index,
882  dealii_cell->child(c),
883  p4est_child[c],
884  new_needs);
885  }
886  else
887  {
888  // at least some part of
889  // the tree rooted in this
890  // child is locally available
891  traverse_patch_recursively (forest,
892  tree,
893  tree_index,
894  dealii_cell->child(c),
895  p4est_child[c],
896  new_needs);
897  }
898  }
899  }
900  }
901 
902 
903 
904  template <int dim,int spacedim,class OutVector>
905  template <class InVector>
906  void
907  ExtrapolateImplementation<dim,spacedim,OutVector>::
908  compute_cells (const DoFHandler<dim,spacedim> &dof2,
909  const InVector &u,
910  std::vector<CellData> &cells_to_compute,
911  std::vector<CellData> &computed_cells,
912  std::vector<CellData> &new_needs)
913  {
916  (&dof2.get_tria()));
917 
918  Assert (tr != 0, ExcInternalError());
919 
920  // collect in a set all trees this
921  // process has to compute cells on
922  std::set<unsigned int> trees;
923  for (typename std::vector<CellData>::const_iterator it=cells_to_compute.begin(); it!=cells_to_compute.end(); ++it)
924  trees.insert (it->tree_index);
925 
927  cell=dof2.begin(0),
928  endc=dof2.end(0);
929  for (; cell!=endc; ++cell)
930  {
931  // check if this is a tree this process has to
932  // work on and that this tree is in the p4est
933  const unsigned int tree_index = tr->coarse_cell_to_p4est_tree_permutation[cell->index()];
934 
935  if ((trees.find (tree_index) == trees.end ())
936  ||
937  (::internal::p4est::tree_exists_locally<dim> (tr->parallel_forest,
938  tree_index)
939  == false))
940  continue;
941 
942  typename ::internal::p4est::types<dim>::quadrant p4est_coarse_cell;
943  typename ::internal::p4est::types<dim>::tree *tree = tr->init_tree(cell->index());
944 
945  ::internal::p4est::init_coarse_quadrant<dim>(p4est_coarse_cell);
946 
947  compute_cells_in_tree_recursively (*tr->parallel_forest,
948  *tree,
949  tree_index,
950  cell,
951  p4est_coarse_cell,
952  u,
953  cells_to_compute,
954  computed_cells,
955  new_needs);
956  }
957  }
958 
959 
960 
961  template <int dim,int spacedim,class OutVector>
962  template <class InVector>
963  void
964  ExtrapolateImplementation<dim,spacedim,OutVector>::
965  compute_cells_in_tree_recursively (const typename ::internal::p4est::types<dim>::forest &forest,
966  const typename ::internal::p4est::types<dim>::tree &tree,
967  const typename ::internal::p4est::types<dim>::locidx &tree_index,
968  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
969  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
970  const InVector &u,
971  std::vector<CellData> &cells_to_compute,
972  std::vector<CellData> &computed_cells,
973  std::vector<CellData> &new_needs)
974  {
975  if (cells_to_compute.size () == 0)
976  return;
977 
978  // check if this cell exists in the local p4est
979  int idx = sc_array_bsearch(const_cast<sc_array_t *>(&tree.quadrants),
980  &p4est_cell,
982 
983  // if neither this cell nor one one of it's children belongs to us, don't do anything
984  if (idx == -1 && (::internal::p4est::functions<dim>::
985  quadrant_overlaps_tree (const_cast<typename ::internal::p4est::types<dim>::tree *>(&tree),
986  &p4est_cell)
987  == false))
988  return;
989 
990  bool p4est_has_children = (idx == -1);
991 
992  // check if this quadrant is in the list
993  CellData cell_data;
994  cell_data.quadrant = p4est_cell;
995  int pos = cell_data_search (cell_data, cells_to_compute);
996  if (pos != -1)
997  {
998  std::vector<CellData> tmp;
999  // compute dof values
1000  get_interpolated_dof_values (forest,
1001  tree,
1002  tree_index,
1003  dealii_cell,
1004  p4est_cell,
1005  u,
1006  cells_to_compute[pos].dof_values,
1007  tmp);
1008  // there is no new cell_data
1009  // this process needs for computing this cell,
1010  // store cell_data in the list of
1011  // computed cells and erase this cell
1012  // from the list of cells to compute
1013  if (tmp.size () == 0)
1014  {
1015  cell_data_insert (cells_to_compute[pos], computed_cells);
1016  cells_to_compute.erase (cells_to_compute.begin () + pos);
1017  }
1018  else
1019  {
1020  for (unsigned int i=0; i<tmp.size (); ++i)
1021  cell_data_insert (tmp[i], new_needs);
1022  }
1023  }
1024 
1025  // search recursively over this tree
1026  if (p4est_has_children)
1027  {
1028  typename ::internal::p4est::types<dim>::quadrant
1030 
1031  ::internal::p4est::init_quadrant_children<dim> (p4est_cell,
1032  p4est_child);
1033 
1034  for (unsigned int c=0; c<GeometryInfo<dim>::max_children_per_cell; ++c)
1035  {
1036  compute_cells_in_tree_recursively (forest,
1037  tree,
1038  tree_index,
1039  dealii_cell->child(c),
1040  p4est_child[c],
1041  u,
1042  cells_to_compute,
1043  computed_cells,
1044  new_needs);
1045  }
1046  }
1047  }
1048 
1049 
1050 
1051  template <int dim,int spacedim,class OutVector>
1052  void
1053  ExtrapolateImplementation<dim,spacedim,OutVector>::
1054  send_cells (const std::vector<CellData> &cells_to_send,
1055  std::vector<CellData> &received_cells) const
1056  {
1057  std::vector<std::vector<char> > sendbuffers (cells_to_send.size());
1058  std::vector<std::vector<char> >::iterator buffer = sendbuffers.begin();
1059  std::vector<MPI_Request> requests (cells_to_send.size());
1060  std::vector<unsigned int> destinations;
1061 
1062  // send data
1063  unsigned int idx=0;
1064  for (typename std::vector<CellData>::const_iterator it=cells_to_send.begin();
1065  it!=cells_to_send.end();
1066  ++it, ++idx)
1067  {
1068  destinations.push_back (it->receiver);
1069 
1070  it->pack_data (*buffer);
1071  const int ierr = MPI_Isend (&(*buffer)[0], buffer->size(),
1072  MPI_BYTE,
1073  it->receiver,
1074  round,
1075  communicator,
1076  &requests[idx]);
1077  AssertThrowMPI(ierr);
1078  }
1079 
1080  Assert(destinations.size()==cells_to_send.size(), ExcInternalError());
1081 
1082  std::vector<unsigned int> senders
1084 
1085  // receive data
1086  std::vector<char> receive;
1087  CellData cell_data;
1088  for (unsigned int index=0; index<senders.size (); ++index)
1089  {
1090  MPI_Status status;
1091  int len;
1092  int ierr = MPI_Probe(MPI_ANY_SOURCE, round, communicator, &status);
1093  AssertThrowMPI(ierr);
1094  ierr = MPI_Get_count(&status, MPI_BYTE, &len);
1095  AssertThrowMPI(ierr);
1096  receive.resize (len);
1097 
1098  char *buf = &receive[0];
1099  ierr = MPI_Recv (buf, len, MPI_BYTE, status.MPI_SOURCE, status.MPI_TAG, communicator, &status);
1100  AssertThrowMPI(ierr);
1101 
1102  cell_data.unpack_data (receive);
1103 
1104  // this process has to send this
1105  // cell back to the sender
1106  // the receiver is the old sender
1107  cell_data.receiver = status.MPI_SOURCE;
1108 
1109  received_cells.push_back (cell_data);
1110  }
1111 
1112  if (requests.size () > 0)
1113  {
1114  const int ierr = MPI_Waitall(requests.size(), &requests[0], MPI_STATUSES_IGNORE);
1115  AssertThrowMPI(ierr);
1116  }
1117 
1118  // finally sort the list of cells
1119  std::sort (received_cells.begin (), received_cells.end ());
1120  }
1121 
1122 
1123 
1124  template <int dim,int spacedim,class OutVector>
1125  void
1126  ExtrapolateImplementation<dim,spacedim,OutVector>::
1127  add_new_need (const typename ::internal::p4est::types<dim>::forest &forest,
1128  const typename ::internal::p4est::types<dim>::locidx &tree_index,
1129  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell,
1130  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell,
1131  std::vector<CellData> &new_needs)
1132  {
1133  const FiniteElement<dim,spacedim> &fe = dealii_cell->get_dof_handler().get_fe();
1134  const unsigned int dofs_per_cell = fe.dofs_per_cell;
1135 
1136  CellData cell_data (dofs_per_cell);
1137  cell_data.quadrant = p4est_cell;
1138  cell_data.tree_index = tree_index;
1139  cell_data.receiver = ::internal::p4est::functions<dim>::
1140  comm_find_owner (const_cast<typename ::internal::p4est::types<dim>::forest *> (&forest),
1141  tree_index,
1142  &p4est_cell,
1143  dealii_cell->level_subdomain_id ());
1144 
1145  cell_data_insert (cell_data, new_needs);
1146  }
1147 
1148 
1149 
1150  template <int dim,int spacedim,class OutVector>
1151  int
1152  ExtrapolateImplementation<dim,spacedim,OutVector>::
1153  cell_data_search (const CellData &cell_data,
1154  const std::vector<CellData> &cells_list)
1155  {
1156  typename std::vector<CellData>::const_iterator bound
1157  = std::lower_bound (cells_list.begin(), cells_list.end(), cell_data);
1158 
1159  if ((bound != cells_list.end ())
1160  &&
1161  !(cell_data < *bound))
1162  return (int)(bound - cells_list.begin ());
1163 
1164  return (-1);
1165  }
1166 
1167 
1168 
1169  template <int dim,int spacedim,class OutVector>
1170  void
1171  ExtrapolateImplementation<dim,spacedim,OutVector>::
1172  cell_data_insert (const CellData &cell_data,
1173  std::vector<CellData> &cells_list)
1174  {
1175  typename std::vector<CellData>::iterator bound
1176  = std::lower_bound (cells_list.begin(), cells_list.end(), cell_data);
1177 
1178  if ((bound == cells_list.end ())
1179  ||
1180  (cell_data < *bound))
1181  cells_list.insert (bound, 1, cell_data);
1182  }
1183 
1184 
1185 
1186  template <int dim,int spacedim,class OutVector>
1187  template <class InVector>
1188  void
1189  ExtrapolateImplementation<dim,spacedim,OutVector>::
1190  compute_all_non_local_data (const DoFHandler<dim,spacedim> &dof2,
1191  const InVector &u)
1192  {
1193  std::vector<CellData> cells_we_need,
1194  cells_to_compute,
1195  received_cells,
1196  received_needs,
1197  new_needs,
1198  computed_cells,
1199  cells_to_send;
1200 
1201  // reset the round count we will use in send_cells
1202  round = 0;
1203 
1204  // Compute all the cells needed from other processes.
1205  compute_needs (dof2, cells_we_need);
1206 
1207  // Send the cells needed to their owners and receive
1208  // a list of cells other processes need from us.
1209  send_cells (cells_we_need, received_needs);
1210 
1211  // The list of received needs can contain some cells more than once
1212  // because different processes may need data from the same cell.
1213  // To compute data only once, generate a vector with unique entries
1214  // and distribute the computed data afterwards back to a vector with
1215  // correct receivers.
1216  // Computing cell_data can cause a need for data from some new cells.
1217  // If a cell is computed, send it back to their senders, maybe receive
1218  // new needs and compute again, do not wait that all cells are computed
1219  // or all needs are collected.
1220  // Otherwise we can run into a deadlock if a cell needed from another
1221  // process itself needs some data from us.
1222  unsigned int ready = 0;
1223  do
1224  {
1225  for (unsigned int i=0; i<received_needs.size(); ++i)
1226  cell_data_insert (received_needs[i], cells_to_compute);
1227 
1228  compute_cells (dof2, u, cells_to_compute, computed_cells, new_needs);
1229 
1230  // if there are no cells to compute and no new needs, stop
1231  ready = Utilities::MPI::sum (new_needs.size () + cells_to_compute.size (), communicator);
1232 
1233  for (typename std::vector<CellData>::const_iterator comp=computed_cells.begin ();
1234  comp != computed_cells.end ();
1235  ++comp)
1236  {
1237  // store computed cells...
1238  cell_data_insert (*comp, available_cells);
1239 
1240  // ...and generate a vector of computed cells with correct
1241  // receivers, then delete this received need from the list
1242  typename std::vector<CellData>::iterator recv=received_needs.begin();
1243  while (recv != received_needs.end())
1244  {
1245  if (::internal::p4est::quadrant_is_equal<dim>(recv->quadrant, comp->quadrant))
1246  {
1247  recv->dof_values = comp->dof_values;
1248  cells_to_send.push_back (*recv);
1249  received_needs.erase (recv);
1250  recv = received_needs.begin();
1251  }
1252  else
1253  ++recv;
1254  }
1255  }
1256 
1257  // increase the round counter, such that we are sure to only send
1258  // and receive data from the correct call
1259  ++round;
1260 
1261  send_cells (cells_to_send, received_cells);
1262 
1263  // store received cell_data
1264  for (typename std::vector<CellData>::const_iterator recv=received_cells.begin ();
1265  recv != received_cells.end ();
1266  ++recv)
1267  {
1268  cell_data_insert (*recv, available_cells);
1269  }
1270 
1271  // increase the round counter, such that we are sure to only send
1272  // and receive data from the correct call
1273  ++round;
1274 
1275  // finally send and receive new needs and start a new round
1276  send_cells (new_needs, received_needs);
1277  }
1278  while (ready != 0);
1279  }
1280 
1281 
1282 
1283  template <int dim,int spacedim,class OutVector>
1284  template <class InVector>
1285  void
1286  ExtrapolateImplementation<dim,spacedim,OutVector>::
1287  extrapolate_parallel (const InVector &u2_relevant,
1288  const DoFHandler<dim,spacedim> &dof2,
1289  OutVector &u2)
1290  {
1293  (&dof2.get_tria()));
1294 
1295  Assert (tr != 0,
1296  ExcMessage ("Extrapolate in parallel only works for parallel distributed triangulations!"));
1297 
1298  communicator = tr->get_communicator ();
1299 
1300  compute_all_non_local_data (dof2, u2_relevant);
1301 
1302  // exclude dofs on more refined ghosted cells
1303  const FiniteElement<dim,spacedim> &fe = dof2.get_fe();
1304  const unsigned int dofs_per_face = fe.dofs_per_face;
1305  if (dofs_per_face > 0)
1306  {
1307  const unsigned int dofs_per_cell = fe.dofs_per_cell;
1308  std::vector<types::global_dof_index> indices (dofs_per_cell);
1310  cell=dof2.begin_active(),
1311  endc=dof2.end();
1312  for (; cell!=endc; ++cell)
1313  if (cell->is_ghost())
1314  {
1315  cell->get_dof_indices(indices);
1316  for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
1317  if (!cell->at_boundary(face))
1318  {
1319  const typename DoFHandler<dim,spacedim>::cell_iterator neighbor = cell->neighbor(face);
1320  if (neighbor->level() != cell->level())
1321  for (unsigned int i=0; i<dofs_per_face; ++i)
1322  {
1323  const types::global_dof_index index = indices[fe.face_to_cell_index(i,face)];;
1324  const bool index_stored
1325  = (dofs_on_refined_neighbors.find(index)!=dofs_on_refined_neighbors.end());
1326  const unsigned int level = index_stored ?
1327  std::max(cell->level(), dofs_on_refined_neighbors[index]) :
1328  cell->level();
1329  dofs_on_refined_neighbors[index] = level;
1330  }
1331  }
1332  }
1333  }
1334 
1335  // after all dof values on
1336  // not owned patch cells
1337  // are computed, start
1338  // the interpolation
1339  u2 = 0;
1340 
1341  std::queue<WorkPackage> queue;
1342  {
1344  cell=dof2.begin(0),
1345  endc=dof2.end(0);
1346  for (; cell!=endc; ++cell)
1347  {
1348  if (::internal::p4est::tree_exists_locally<dim> (tr->parallel_forest,
1349  tr->coarse_cell_to_p4est_tree_permutation[cell->index()])
1350  == false)
1351  continue;
1352 
1353  typename ::internal::p4est::types<dim>::quadrant p4est_coarse_cell;
1354  const unsigned int tree_index = tr->coarse_cell_to_p4est_tree_permutation[cell->index()];
1355  typename ::internal::p4est::types<dim>::tree *tree = tr->init_tree(cell->index());
1356 
1357  ::internal::p4est::init_coarse_quadrant<dim>(p4est_coarse_cell);
1358 
1359  const WorkPackage data (*tr->parallel_forest, *tree,tree_index,cell,p4est_coarse_cell);
1360 
1361  queue.push(data);
1362  }
1363  }
1364 
1365  while (!queue.empty())
1366  {
1367  const WorkPackage &data = queue.front();
1368 
1369  const typename ::internal::p4est::types<dim>::forest &forest = data.forest;
1370  const typename ::internal::p4est::types<dim>::tree &tree = data.tree;
1371  const typename ::internal::p4est::types<dim>::locidx &tree_index= data.tree_index;
1372  const typename DoFHandler<dim,spacedim>::cell_iterator &dealii_cell = data.dealii_cell;
1373  const typename ::internal::p4est::types<dim>::quadrant &p4est_cell = data.p4est_cell;
1374 
1375  interpolate_recursively (forest, tree, tree_index, dealii_cell, p4est_cell, u2_relevant, u2);
1376 
1377  // traverse recursively over this tree
1378  if (dealii_cell->has_children())
1379  {
1380  Assert(dealii_cell->has_children(), ExcInternalError());
1381  typename ::internal::p4est::types<dim>::quadrant
1383 
1384  ::internal::p4est::init_quadrant_children<dim> (p4est_cell,
1385  p4est_child);
1386 
1387  for (unsigned int c=0; c<GeometryInfo<dim>::max_children_per_cell; ++c)
1388  queue.push(WorkPackage(forest, tree, tree_index, dealii_cell->child(c), p4est_child[c]));
1389  }
1390  queue.pop();
1391  }
1392 
1393 
1394  u2.compress(VectorOperation::insert);
1395  }
1396 #endif //DEAL_II_WITH_P4EST
1397 
1398  namespace
1399  {
1400  template <class VectorType, class DH>
1401  void reinit_distributed(const DH &dh,
1402  VectorType &vector)
1403  {
1404  vector.reinit(dh.n_dofs());
1405  }
1406 
1407 #ifdef DEAL_II_WITH_PETSC
1408  template <int dim, int spacedim>
1409  void reinit_distributed(const DoFHandler<dim, spacedim> &dh,
1411  {
1414  Assert (parallel_tria !=0, ExcNotImplemented());
1415 
1416  const IndexSet locally_owned_dofs = dh.locally_owned_dofs();
1417  vector.reinit(locally_owned_dofs, parallel_tria->get_communicator());
1418  }
1419 #endif //DEAL_II_WITH_PETSC
1420 
1421 #ifdef DEAL_II_WITH_TRILINOS
1422  template <int dim, int spacedim>
1423  void reinit_distributed(const DoFHandler<dim, spacedim> &dh,
1425  {
1428  Assert (parallel_tria !=0, ExcNotImplemented());
1429 
1430  const IndexSet locally_owned_dofs = dh.locally_owned_dofs();
1431  vector.reinit(locally_owned_dofs, parallel_tria->get_communicator());
1432  }
1433 #endif //DEAL_II_WITH_TRILINOS
1434 
1435  template <int dim, int spacedim, typename Number>
1436  void reinit_distributed(const DoFHandler<dim, spacedim> &dh,
1438  {
1441  Assert (parallel_tria !=0, ExcNotImplemented());
1442 
1443  const IndexSet locally_owned_dofs = dh.locally_owned_dofs();
1444  vector.reinit(locally_owned_dofs, parallel_tria->get_communicator());
1445  }
1446 
1447 
1448 
1449  template <class VectorType, class DH>
1450  void reinit_ghosted(const DH &/*dh*/,
1451  VectorType &/*vector*/)
1452  {
1453  Assert(false, ExcNotImplemented());
1454  }
1455 
1456 #ifdef DEAL_II_WITH_PETSC
1457  template <int dim, int spacedim>
1458  void reinit_ghosted(const DoFHandler<dim, spacedim> &dh,
1460  {
1463  Assert(parallel_tria !=0, ExcNotImplemented());
1464  const IndexSet locally_owned_dofs = dh.locally_owned_dofs();
1465  IndexSet locally_relevant_dofs;
1466  DoFTools::extract_locally_relevant_dofs (dh, locally_relevant_dofs);
1467  vector.reinit (locally_owned_dofs, locally_relevant_dofs,
1468  parallel_tria->get_communicator());
1469  }
1470 #endif //DEAL_II_WITH_PETSC
1471 
1472 #ifdef DEAL_II_WITH_TRILINOS
1473  template <int dim, int spacedim>
1474  void reinit_ghosted(const DoFHandler<dim, spacedim> &dh,
1476  {
1479  Assert (parallel_tria !=0, ExcNotImplemented());
1480  const IndexSet locally_owned_dofs = dh.locally_owned_dofs();
1481  IndexSet locally_relevant_dofs;
1482  DoFTools::extract_locally_relevant_dofs (dh, locally_relevant_dofs);
1483  vector.reinit (locally_owned_dofs, locally_relevant_dofs,
1484  parallel_tria->get_communicator());
1485  }
1486 #endif //DEAL_II_WITH_TRILINOS
1487 
1488  template <int dim, int spacedim, typename Number>
1489  void reinit_ghosted(const DoFHandler<dim, spacedim> &dh,
1491  {
1494  Assert (parallel_tria !=0, ExcNotImplemented());
1495  const IndexSet locally_owned_dofs = dh.locally_owned_dofs();
1496  IndexSet locally_relevant_dofs;
1497  DoFTools::extract_locally_relevant_dofs (dh, locally_relevant_dofs);
1498  vector.reinit (locally_owned_dofs, locally_relevant_dofs,
1499  parallel_tria->get_communicator());
1500  }
1501 
1502 
1503 
1504  template <int dim, class InVector, class OutVector, int spacedim>
1505  void extrapolate_serial(const InVector &u3,
1506  const DoFHandler<dim,spacedim> &dof2,
1507  OutVector &u2)
1508  {
1509  const unsigned int dofs_per_cell = dof2.get_fe().dofs_per_cell;
1510  Vector<typename OutVector::value_type> dof_values(dofs_per_cell);
1511 
1512  // then traverse grid bottom up
1513  for (unsigned int level=0; level<dof2.get_triangulation().n_levels()-1; ++level)
1514  {
1515  typename DoFHandler<dim,spacedim>::cell_iterator cell=dof2.begin(level),
1516  endc=dof2.end(level);
1517 
1518  for (; cell!=endc; ++cell)
1519  if (!cell->active())
1520  {
1521  // check whether this
1522  // cell has active
1523  // children
1524  bool active_children=false;
1525  for (unsigned int child_n=0; child_n<cell->n_children(); ++child_n)
1526  if (cell->child(child_n)->active())
1527  {
1528  active_children=true;
1529  break;
1530  }
1531 
1532  // if there are active
1533  // children, this process
1534  // has to work on this
1535  // cell. get the data
1536  // from the one vector
1537  // and set it on the
1538  // other
1539  if (active_children)
1540  {
1541  cell->get_interpolated_dof_values(u3, dof_values);
1542  cell->set_dof_values_by_interpolation(dof_values, u2);
1543  }
1544  }
1545  }
1546  }
1547  }
1548  }
1549 
1550  template <int dim, class InVector, class OutVector, int spacedim>
1552  const InVector &u1,
1553  const DoFHandler<dim,spacedim> &dof2,
1554  OutVector &u2)
1555  {
1556  ConstraintMatrix dummy;
1557  dummy.close();
1558  extrapolate(dof1, u1, dof2, dummy, u2);
1559  }
1560 
1561 
1562 
1563  template <int dim, class InVector, class OutVector, int spacedim>
1565  const InVector &u1,
1566  const DoFHandler<dim,spacedim> &dof2,
1567  const ConstraintMatrix &constraints,
1568  OutVector &u2)
1569  {
1570  Assert(dof1.get_fe().n_components() == dof2.get_fe().n_components(),
1571  ExcDimensionMismatch(dof1.get_fe().n_components(), dof2.get_fe().n_components()));
1573  Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
1574  Assert(u2.size()==dof2.n_dofs(), ExcDimensionMismatch(u2.size(), dof2.n_dofs()));
1575 
1576  // make sure that each cell on the coarsest level is at least once refined, otherwise, these cells
1577  // can't be treated and would generate a bogus result
1578  {
1579  typename DoFHandler<dim,spacedim>::cell_iterator cell = dof2.begin(0),
1580  endc = dof2.end(0);
1581  for (; cell!=endc; ++cell)
1582  Assert (cell->has_children() || cell->is_artificial(), ExcGridNotRefinedAtLeastOnce());
1583  }
1584 
1585 
1586  OutVector u3;
1587  internal::reinit_distributed(dof2, u3);
1588  if (dynamic_cast<const parallel::distributed::Triangulation<dim,spacedim>*>(&dof2.get_tria()) != 0)
1589  {
1590  interpolate(dof1, u1, dof2, constraints, u3);
1591 
1592  OutVector u3_relevant;
1593  internal::reinit_ghosted(dof2, u3_relevant);
1594  u3_relevant = u3;
1595 
1596  internal::ExtrapolateImplementation<dim,spacedim,OutVector> implementation;
1597  implementation.extrapolate_parallel (u3_relevant, dof2, u2);
1598  }
1599  else
1600  {
1601  interpolate(dof1, u1, dof2, constraints, u3);
1602 
1603  internal::extrapolate_serial (u3, dof2, u2);
1604  }
1605 
1606  constraints.distribute(u2);
1607  }
1608 } // end of namespace FETools
1609 
1610 
1611 /*-------------- Explicit Instantiations -------------------------------*/
1612 #include "fe_tools_extrapolate.inst"
1613 
1614 
1615 /*---------------------------- fe_tools.cc ---------------------------*/
1616 
1617 DEAL_II_NAMESPACE_CLOSE
void reinit(const size_type size, const bool omit_zeroing_entries=false)
Definition: tria.h:67
bool restriction_is_additive(const unsigned int index) const
Definition: fe.h:3000
static ::ExceptionBase & ExcGridNotRefinedAtLeastOnce()
cell_iterator begin(const unsigned int level=0) const
Definition: dof_handler.cc:728
const Triangulation< dim, spacedim > & get_tria() const 1
cell_iterator end() const
Definition: dof_handler.cc:756
ActiveSelector::active_cell_iterator active_cell_iterator
Definition: dof_handler.h:228
#define AssertThrow(cond, exc)
Definition: exceptions.h:369
virtual const FullMatrix< double > & get_prolongation_matrix(const unsigned int child, const RefinementCase< dim > &refinement_case=RefinementCase< dim >::isotropic_refinement) const
Definition: fe.cc:325
const FiniteElement< dim, spacedim > & get_fe() const
void extrapolate(const DoFHandler< dim, spacedim > &dof1, const InVector &z1, const DoFHandler< dim, spacedim > &dof2, OutVector &z2)
typename ::internal::p4est::types< dim >::forest * parallel_forest
Definition: tria.h:741
void reinit(const VectorBase &v, const bool omit_zeroing_entries=false, const bool allow_different_maps=false)
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: dof_handler.cc:740
static ::ExceptionBase & ExcMessage(std::string arg1)
ActiveSelector::cell_iterator cell_iterator
Definition: dof_handler.h:256
T sum(const T &t, const MPI_Comm &mpi_communicator)
unsigned int global_dof_index
Definition: types.h:88
#define Assert(cond, exc)
Definition: exceptions.h:313
virtual const FullMatrix< double > & get_restriction_matrix(const unsigned int child, const RefinementCase< dim > &refinement_case=RefinementCase< dim >::isotropic_refinement) const
Definition: fe.cc:305
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
std::size_t size() const
virtual MPI_Comm get_communicator() const
Definition: tria_base.cc:146
types::global_dof_index n_dofs() const
void extract_locally_relevant_dofs(const DoFHandlerType &dof_handler, IndexSet &dof_set)
Definition: dof_tools.cc:980
typename ::internal::p4est::types< dim >::tree * init_tree(const int dealii_coarse_cell_index) const
Definition: tria.cc:1985
virtual unsigned int face_to_cell_index(const unsigned int face_dof_index, const unsigned int face, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false) const
Definition: fe.cc:528
iterator begin()
const unsigned int dofs_per_cell
Definition: fe_base.h:295
void distribute(VectorType &vec) const
#define AssertThrowMPI(error_code)
Definition: exceptions.h:1211
void reinit(const MPI_Comm &communicator, const size_type N, const size_type local_size, const bool omit_zeroing_entries=false)
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
const unsigned int dofs_per_face
Definition: fe_base.h:288
static ::ExceptionBase & ExcNotImplemented()
const Triangulation< dim, spacedim > & get_triangulation() const
std::vector< unsigned int > compute_point_to_point_communication_pattern(const MPI_Comm &mpi_comm, const std::vector< unsigned int > &destinations)
Definition: mpi.cc:93
const IndexSet & locally_owned_dofs() const
static ::ExceptionBase & ExcTriangulationMismatch()
std::vector< types::global_dof_index > coarse_cell_to_p4est_tree_permutation
Definition: tria.h:807
void interpolate(const DoFHandlerType1< dim, spacedim > &dof1, const InVector &u1, const DoFHandlerType2< dim, spacedim > &dof2, OutVector &u2)
static ::ExceptionBase & ExcInternalError()