Loading [MathJax]/extensions/TeX/AMSsymbols.js
 Reference documentation for deal.II version 8.5.1
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
mg_transfer_internal.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2016 - 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 
17 #include <deal.II/distributed/tria.h>
18 #include <deal.II/dofs/dof_tools.h>
19 #include <deal.II/fe/fe_tools.h>
20 #include <deal.II/matrix_free/shape_info.h>
21 #include <deal.II/multigrid/mg_transfer_internal.h>
22 
23 DEAL_II_NAMESPACE_OPEN
24 
25 namespace internal
26 {
27  namespace MGTransfer
28  {
29 
30  // Internal data structure that is used in the MPI communication in
31  // fill_copy_indices(). It represents an entry in the copy_indices* map,
32  // that associates a level dof index with a global dof index.
33  struct DoFPair
34  {
35  unsigned int level;
37  types::global_dof_index level_dof_index;
38 
39  DoFPair(const unsigned int level,
40  const types::global_dof_index global_dof_index,
41  const types::global_dof_index level_dof_index)
42  :
43  level(level),
45  level_dof_index(level_dof_index)
46  {}
47 
48  DoFPair()
49  :
50  level (numbers::invalid_unsigned_int),
52  level_dof_index (numbers::invalid_dof_index)
53  {}
54  };
55 
56  // Internal function for filling the copy indices from global to level
57  // indices
58  template <int dim, int spacedim>
59  void fill_copy_indices(const ::DoFHandler<dim,spacedim> &mg_dof,
60  const MGConstrainedDoFs *mg_constrained_dofs,
61  std::vector<std::vector<std::pair<types::global_dof_index, types::global_dof_index> > > &copy_indices,
62  std::vector<std::vector<std::pair<types::global_dof_index, types::global_dof_index> > > &copy_indices_global_mine,
63  std::vector<std::vector<std::pair<types::global_dof_index, types::global_dof_index> > > &copy_indices_level_mine)
64  {
65  // Now we are filling the variables copy_indices*, which are essentially
66  // maps from global to mgdof for each level stored as a std::vector of
67  // pairs. We need to split this map on each level depending on the
68  // ownership of the global and mgdof, so that we later not access
69  // non-local elements in copy_to/from_mg.
70  // We keep track in the bitfield dof_touched which global dof has been
71  // processed already (on the current level). This is the same as the
72  // multigrid running in serial.
73 
74  // map cpu_index -> vector of data
75  // that will be copied into copy_indices_level_mine
76  std::vector<DoFPair> send_data_temp;
77 
78  const unsigned int n_levels = mg_dof.get_triangulation().n_global_levels();
79  copy_indices.resize(n_levels);
80  copy_indices_global_mine.resize(n_levels);
81  copy_indices_level_mine.resize(n_levels);
82  IndexSet globally_relevant;
83  DoFTools::extract_locally_relevant_dofs(mg_dof, globally_relevant);
84 
85  const unsigned int dofs_per_cell = mg_dof.get_fe().dofs_per_cell;
86  std::vector<types::global_dof_index> global_dof_indices (dofs_per_cell);
87  std::vector<types::global_dof_index> level_dof_indices (dofs_per_cell);
88 
89  for (unsigned int level=0; level<n_levels; ++level)
90  {
91  std::vector<bool> dof_touched(globally_relevant.n_elements(), false);
92  copy_indices[level].clear();
93  copy_indices_level_mine[level].clear();
94  copy_indices_global_mine[level].clear();
95 
96  typename ::DoFHandler<dim,spacedim>::active_cell_iterator
97  level_cell = mg_dof.begin_active(level);
98  const typename ::DoFHandler<dim,spacedim>::active_cell_iterator
99  level_end = mg_dof.end_active(level);
100 
101  for (; level_cell!=level_end; ++level_cell)
102  {
103  if (mg_dof.get_triangulation().locally_owned_subdomain()!=numbers::invalid_subdomain_id
104  && (level_cell->level_subdomain_id()==numbers::artificial_subdomain_id
105  || level_cell->subdomain_id()==numbers::artificial_subdomain_id)
106  )
107  continue;
108 
109  // get the dof numbers of this cell for the global and the
110  // level-wise numbering
111  level_cell->get_dof_indices (global_dof_indices);
112  level_cell->get_mg_dof_indices (level_dof_indices);
113 
114  for (unsigned int i=0; i<dofs_per_cell; ++i)
115  {
116  // we need to ignore if the DoF is on a refinement edge (hanging node)
117  if (mg_constrained_dofs != 0
118  && mg_constrained_dofs->at_refinement_edge(level, level_dof_indices[i]))
119  continue;
120  types::global_dof_index global_idx = globally_relevant.index_within_set(global_dof_indices[i]);
121  //skip if we did this global dof already (on this or a coarser level)
122  if (dof_touched[global_idx])
123  continue;
124  bool global_mine = mg_dof.locally_owned_dofs().is_element(global_dof_indices[i]);
125  bool level_mine = mg_dof.locally_owned_mg_dofs(level).is_element(level_dof_indices[i]);
126 
127 
128  if (global_mine && level_mine)
129  {
130  copy_indices[level].push_back(
131  std::make_pair (global_dof_indices[i], level_dof_indices[i]));
132  }
133  else if (global_mine)
134  {
135  copy_indices_global_mine[level].push_back(
136  std::make_pair (global_dof_indices[i], level_dof_indices[i]));
137 
138  //send this to the owner of the level_dof:
139  send_data_temp.push_back(DoFPair(level, global_dof_indices[i], level_dof_indices[i]));
140  }
141  else
142  {
143  // somebody will send those to me
144  }
145 
146  dof_touched[global_idx] = true;
147  }
148  }
149  }
150 
151  const ::parallel::distributed::Triangulation<dim,spacedim> *tria =
153  (&mg_dof.get_triangulation()));
154  AssertThrow(send_data_temp.size()==0 || tria!=NULL, ExcMessage("parallel Multigrid only works with a distributed Triangulation!"));
155 
156 #ifdef DEAL_II_WITH_MPI
157  if (tria)
158  {
159  // TODO: Searching the owner for every single DoF becomes quite
160  // inefficient. Please fix this, Timo.
161  // The list of neighbors is symmetric (our neighbors have us as a
162  // neighbor), so we can use it to send and to know how many messages
163  // we will get.
164  std::set<types::subdomain_id> neighbors = tria->level_ghost_owners();
165  std::map<int, std::vector<DoFPair> > send_data;
166 
167  // * find owners of the level dofs and insert into send_data accordingly
168  for (typename std::vector<DoFPair>::iterator dofpair=send_data_temp.begin(); dofpair != send_data_temp.end(); ++dofpair)
169  {
170  std::set<types::subdomain_id>::iterator it;
171  for (it = neighbors.begin(); it != neighbors.end(); ++it)
172  {
173  if (mg_dof.locally_owned_mg_dofs_per_processor(dofpair->level)[*it].is_element(dofpair->level_dof_index))
174  {
175  send_data[*it].push_back(*dofpair);
176  break;
177  }
178  }
179  // Is this level dof not owned by any of our neighbors? That would
180  // certainly be a bug!
181  Assert(it!=neighbors.end(), ExcMessage("could not find DoF owner."));
182  }
183 
184  // * send
185  std::vector<MPI_Request> requests;
186  {
187  for (std::set<types::subdomain_id>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
188  {
189  requests.push_back(MPI_Request());
190  unsigned int dest = *it;
191  std::vector<DoFPair> &data = send_data[dest];
192  // If there is nothing to send, we still need to send a message,
193  // because the receiving end will be waitng. In that case we
194  // just send an empty message.
195  if (data.size())
196  {
197  const int ierr = MPI_Isend(&data[0], data.size()*sizeof(data[0]),
198  MPI_BYTE, dest, 71, tria->get_communicator(),
199  &*requests.rbegin());
200  AssertThrowMPI(ierr);
201  }
202  else
203  {
204  const int ierr = MPI_Isend(NULL, 0, MPI_BYTE, dest, 71,
205  tria->get_communicator(), &*requests.rbegin());
206  AssertThrowMPI(ierr);
207  }
208  }
209  }
210 
211  // * receive
212  {
213  // We should get one message from each of our neighbors
214  std::vector<DoFPair> receive_buffer;
215  for (unsigned int counter=0; counter<neighbors.size(); ++counter)
216  {
217  MPI_Status status;
218  int len;
219  int ierr = MPI_Probe(MPI_ANY_SOURCE, 71, tria->get_communicator(), &status);
220  AssertThrowMPI(ierr);
221  ierr = MPI_Get_count(&status, MPI_BYTE, &len);
222  AssertThrowMPI(ierr);
223 
224  if (len==0)
225  {
226  ierr = MPI_Recv(NULL, 0, MPI_BYTE, status.MPI_SOURCE, status.MPI_TAG,
227  tria->get_communicator(), &status);
228  AssertThrowMPI(ierr);
229  continue;
230  }
231 
232  int count = len / sizeof(DoFPair);
233  Assert(static_cast<int>(count * sizeof(DoFPair)) == len, ExcInternalError());
234  receive_buffer.resize(count);
235 
236  void *ptr = &receive_buffer[0];
237  ierr = MPI_Recv(ptr, len, MPI_BYTE, status.MPI_SOURCE, status.MPI_TAG,
238  tria->get_communicator(), &status);
239  AssertThrowMPI(ierr);
240 
241  for (unsigned int i=0; i<receive_buffer.size(); ++i)
242  {
243  copy_indices_level_mine[receive_buffer[i].level].push_back(
244  std::make_pair (receive_buffer[i].global_dof_index, receive_buffer[i].level_dof_index)
245  );
246  }
247  }
248  }
249 
250  // * wait for all MPI_Isend to complete
251  if (requests.size() > 0)
252  {
253  const int ierr = MPI_Waitall(requests.size(), &requests[0], MPI_STATUSES_IGNORE);
254  AssertThrowMPI(ierr);
255  requests.clear();
256  }
257 #ifdef DEBUG
258  // Make sure in debug mode, that everybody sent/received all packages
259  // on this level. If a deadlock occurs here, the list of expected
260  // senders is not computed correctly.
261  const int ierr = MPI_Barrier(tria->get_communicator());
262  AssertThrowMPI(ierr);
263 #endif
264  }
265 #endif
266 
267  // Sort the indices. This will produce more reliable debug output for
268  // regression tests and likely won't hurt performance even in release
269  // mode.
270  std::less<std::pair<types::global_dof_index, types::global_dof_index> > compare;
271  for (unsigned int level=0; level<copy_indices.size(); ++level)
272  std::sort(copy_indices[level].begin(), copy_indices[level].end(), compare);
273  for (unsigned int level=0; level<copy_indices_level_mine.size(); ++level)
274  std::sort(copy_indices_level_mine[level].begin(), copy_indices_level_mine[level].end(), compare);
275  for (unsigned int level=0; level<copy_indices_global_mine.size(); ++level)
276  std::sort(copy_indices_global_mine[level].begin(), copy_indices_global_mine[level].end(), compare);
277  }
278 
279 
280 
281  // initialize the vectors needed for the transfer (and merge with the
282  // content in copy_indices_global_mine)
283  template <typename Number>
284  void
285  reinit_ghosted_vector(const IndexSet &locally_owned,
286  std::vector<types::global_dof_index> &ghosted_level_dofs,
287  const MPI_Comm &communicator,
288  LinearAlgebra::distributed::Vector<Number> &ghosted_level_vector,
289  std::vector<std::pair<unsigned int,unsigned int> > &copy_indices_global_mine)
290  {
291  std::sort(ghosted_level_dofs.begin(), ghosted_level_dofs.end());
292  IndexSet ghosted_dofs(locally_owned.size());
293  ghosted_dofs.add_indices(ghosted_level_dofs.begin(),
294  std::unique(ghosted_level_dofs.begin(),
295  ghosted_level_dofs.end()));
296  ghosted_dofs.compress();
297 
298  // Add possible ghosts from the previous content in the vector
299  if (ghosted_level_vector.size() == locally_owned.size())
300  {
301  // shift the local number of the copy indices according to the new
302  // partitioner that we are going to use for the vector
303  const std_cxx11::shared_ptr<const Utilities::MPI::Partitioner> part
304  = ghosted_level_vector.get_partitioner();
305  ghosted_dofs.add_indices(part->ghost_indices());
306  for (unsigned int i=0; i<copy_indices_global_mine.size(); ++i)
307  copy_indices_global_mine[i].second =
308  locally_owned.n_elements() +
309  ghosted_dofs.index_within_set(part->local_to_global(copy_indices_global_mine[i].second));
310  }
311  ghosted_level_vector.reinit(locally_owned, ghosted_dofs, communicator);
312  }
313 
314  // Transform the ghost indices to local index space for the vector
315  inline void
316  copy_indices_to_mpi_local_numbers(const Utilities::MPI::Partitioner &part,
317  const std::vector<types::global_dof_index> &mine,
318  const std::vector<types::global_dof_index> &remote,
319  std::vector<unsigned int> &localized_indices)
320  {
321  localized_indices.resize(mine.size()+remote.size(),
323  for (unsigned int i=0; i<mine.size(); ++i)
324  if (mine[i] != numbers::invalid_dof_index)
325  localized_indices[i] = part.global_to_local(mine[i]);
326 
327  for (unsigned int i=0; i<remote.size(); ++i)
328  if (remote[i] != numbers::invalid_dof_index)
329  localized_indices[i+mine.size()] = part.global_to_local(remote[i]);
330  }
331 
332  // given the collection of child cells in lexicographic ordering as seen
333  // from the parent, compute the first index of the given child
334  template <int dim>
335  unsigned int
336  compute_shift_within_children(const unsigned int child,
337  const unsigned int fe_shift_1d,
338  const unsigned int fe_degree)
339  {
340  // we put the degrees of freedom of all child cells in lexicographic
341  // ordering
342  unsigned int c_tensor_index[dim];
343  unsigned int tmp = child;
344  for (unsigned int d=0; d<dim; ++d)
345  {
346  c_tensor_index[d] = tmp % 2;
347  tmp /= 2;
348  }
349  const unsigned int n_child_dofs_1d = fe_degree + 1 + fe_shift_1d;
350  unsigned int factor = 1;
351  unsigned int shift = fe_shift_1d * c_tensor_index[0];
352  for (unsigned int d=1; d<dim; ++d)
353  {
354  factor *= n_child_dofs_1d;
355  shift = shift + factor * fe_shift_1d * c_tensor_index[d];
356  }
357  return shift;
358  }
359 
360  // puts the indices on the given child cell in lexicographic ordering with
361  // respect to the collection of all child cells as seen from the parent
362  template <int dim>
363  void add_child_indices(const unsigned int child,
364  const unsigned int fe_shift_1d,
365  const unsigned int fe_degree,
366  const std::vector<unsigned int> &lexicographic_numbering,
367  const std::vector<types::global_dof_index> &local_dof_indices,
368  types::global_dof_index *target_indices)
369  {
370  const unsigned int n_child_dofs_1d = fe_degree + 1 + fe_shift_1d;
371  const unsigned int shift =
372  compute_shift_within_children<dim>(child, fe_shift_1d, fe_degree);
373  const unsigned int n_components =
374  local_dof_indices.size()/Utilities::fixed_power<dim>(fe_degree+1);
375  types::global_dof_index *indices = target_indices + shift;
376  const unsigned int n_scalar_cell_dofs = Utilities::fixed_power<dim>(n_child_dofs_1d);
377  for (unsigned int c=0, m=0; c<n_components; ++c)
378  for (unsigned int k=0; k<(dim>2 ? (fe_degree+1) : 1); ++k)
379  for (unsigned int j=0; j<(dim>1 ? (fe_degree+1) : 1); ++j)
380  for (unsigned int i=0; i<(fe_degree+1); ++i, ++m)
381  {
382  const unsigned int index = c*n_scalar_cell_dofs+k*n_child_dofs_1d*
383  n_child_dofs_1d+j*n_child_dofs_1d+i;
384  Assert(indices[index] == numbers::invalid_dof_index ||
385  indices[index] == local_dof_indices[lexicographic_numbering[m]],
386  ExcInternalError());
387  indices[index] = local_dof_indices[lexicographic_numbering[m]];
388  }
389  }
390 
391  template <int dim, typename Number>
392  void setup_element_info(ElementInfo<Number> &elem_info,const FiniteElement<1> &fe,
393  const ::DoFHandler<dim> &mg_dof)
394  {
395  // currently, we have only FE_Q and FE_DGQ type elements implemented
396  elem_info.n_components = mg_dof.get_fe().element_multiplicity(0);
397  AssertDimension(Utilities::fixed_power<dim>(fe.dofs_per_cell)*elem_info.n_components,
398  mg_dof.get_fe().dofs_per_cell);
399  AssertDimension(fe.degree, mg_dof.get_fe().degree);
400  elem_info.fe_degree = fe.degree;
401  elem_info.element_is_continuous = fe.dofs_per_vertex > 0;
403 
404  // step 1.2: get renumbering of 1D basis functions to lexicographic
405  // numbers. The distinction according to fe.dofs_per_vertex is to support
406  // both continuous and discontinuous bases.
407  std::vector<unsigned int> renumbering(fe.dofs_per_cell);
408  {
410  renumbering[0] = 0;
411  for (unsigned int i=0; i<fe.dofs_per_line; ++i)
412  renumbering[i+fe.dofs_per_vertex] =
414  if (fe.dofs_per_vertex > 0)
415  renumbering[fe.dofs_per_cell-fe.dofs_per_vertex] = fe.dofs_per_vertex;
416  }
417 
418  // step 1.3: create a dummy 1D quadrature formula to extract the
419  // lexicographic numbering for the elements
420  std::vector<Point<1> > basic_support_points = fe.get_unit_support_points();
421  Assert(fe.dofs_per_vertex == 0 || fe.dofs_per_vertex == 1,
423  const unsigned int shift = fe.dofs_per_cell - fe.dofs_per_vertex;
424  const unsigned int n_child_dofs_1d = (fe.dofs_per_vertex > 0 ?
425  (2 * fe.dofs_per_cell - 1) :
426  (2 * fe.dofs_per_cell));
427 
428  elem_info.n_child_cell_dofs = elem_info.n_components*Utilities::fixed_power<dim>(n_child_dofs_1d);
429  const Quadrature<1> dummy_quadrature(std::vector<Point<1> >(1, Point<1>()));
431  shape_info.reinit(dummy_quadrature, mg_dof.get_fe(), 0);
432  elem_info.lexicographic_numbering = shape_info.lexicographic_numbering;
433 
434  // step 1.4: get the 1d prolongation matrix and combine from both children
435  elem_info.prolongation_matrix_1d.resize(fe.dofs_per_cell*n_child_dofs_1d);
436 
437  for (unsigned int c=0; c<GeometryInfo<1>::max_children_per_cell; ++c)
438  for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
439  for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
440  elem_info.prolongation_matrix_1d[i*n_child_dofs_1d+j+c*shift] =
441  fe.get_prolongation_matrix(c)(renumbering[j],renumbering[i]);
442  }
443 
444 
445  // Sets up most of the internal data structures of the MGTransferMatrixFree
446  // class
447  template <int dim, typename Number>
448  void setup_transfer(const ::DoFHandler<dim> &mg_dof,
449  const MGConstrainedDoFs *mg_constrained_dofs,
450  ElementInfo<Number> &elem_info,
451  std::vector<std::vector<unsigned int> > &level_dof_indices,
452  std::vector<std::vector<std::pair<unsigned int,unsigned int> > > &parent_child_connect,
453  std::vector<unsigned int> &n_owned_level_cells,
454  std::vector<std::vector<std::vector<unsigned short> > > &dirichlet_indices,
455  std::vector<std::vector<Number> > &weights_on_refined,
456  std::vector<std::vector<std::pair<unsigned int, unsigned int> > > &copy_indices_global_mine,
458  {
459  level_dof_indices.clear();
460  parent_child_connect.clear();
461  n_owned_level_cells.clear();
462  dirichlet_indices.clear();
463  weights_on_refined.clear();
464 
465  // we collect all child DoFs of a mother cell together. For faster
466  // tensorized operations, we align the degrees of freedom
467  // lexicographically. We distinguish FE_Q elements and FE_DGQ elements
468 
469  const ::Triangulation<dim> &tria = mg_dof.get_triangulation();
470 
471  // ---------------------------- 1. Extract 1D info about the finite element
472  // step 1.1: create a 1D copy of the finite element from FETools where we
473  // substitute the template argument
474  AssertDimension(mg_dof.get_fe().n_base_elements(), 1);
475  std::string fe_name = mg_dof.get_fe().base_element(0).get_name();
476  {
477  const std::size_t template_starts = fe_name.find_first_of('<');
478  Assert (fe_name[template_starts+1] == (dim==1?'1':(dim==2?'2':'3')),
479  ExcInternalError());
480  fe_name[template_starts+1] = '1';
481  }
482  std_cxx11::shared_ptr<FiniteElement<1> > fe_1d
483  (FETools::get_fe_by_name<1,1>(fe_name));
484  const FiniteElement<1> &fe = *fe_1d;
485 
486  setup_element_info(elem_info,fe,mg_dof);
487 
488 
489  // -------------- 2. Extract and match dof indices between child and parent
490  const unsigned int n_levels = tria.n_global_levels();
491  level_dof_indices.resize(n_levels);
492  parent_child_connect.resize(n_levels-1);
493  n_owned_level_cells.resize(n_levels-1);
494  std::vector<std::vector<unsigned int> > coarse_level_indices(n_levels-1);
495  for (unsigned int level=0; level<std::min(tria.n_levels(),n_levels-1); ++level)
496  coarse_level_indices[level].resize(tria.n_raw_cells(level),
498  std::vector<types::global_dof_index> local_dof_indices(mg_dof.get_fe().dofs_per_cell);
499  dirichlet_indices.resize(n_levels-1);
500 
501  // We use the vectors stored ghosted_level_vector in the base class for
502  // keeping ghosted transfer indices. To avoid keeping two very similar
503  // vectors, we merge them here.
504  if (ghosted_level_vector.max_level() != n_levels-1)
505  ghosted_level_vector.resize(0, n_levels-1);
506 
507  for (unsigned int level=n_levels-1; level > 0; --level)
508  {
509  unsigned int counter = 0;
510  std::vector<types::global_dof_index> global_level_dof_indices;
511  std::vector<types::global_dof_index> global_level_dof_indices_remote;
512  std::vector<types::global_dof_index> ghosted_level_dofs;
513  std::vector<types::global_dof_index> global_level_dof_indices_l0;
514  std::vector<types::global_dof_index> ghosted_level_dofs_l0;
515 
516  // step 2.1: loop over the cells on the coarse side
517  typename ::DoFHandler<dim>::cell_iterator cell, endc = mg_dof.end(level-1);
518  for (cell = mg_dof.begin(level-1); cell != endc; ++cell)
519  {
520  // need to look into a cell if it has children and it is locally
521  // owned
522  if (!cell->has_children())
523  continue;
524 
525  bool consider_cell = false;
526  if (tria.locally_owned_subdomain()==numbers::invalid_subdomain_id
527  || cell->level_subdomain_id()==tria.locally_owned_subdomain()
528  )
529  consider_cell = true;
530 
531  // due to the particular way we store DoF indices (via children),
532  // we also need to add the DoF indices for coarse cells where we
533  // own at least one child
534  bool cell_is_remote = !consider_cell;
535  for (unsigned int c=0; c<GeometryInfo<dim>::max_children_per_cell; ++c)
536  if (cell->child(c)->level_subdomain_id()==tria.locally_owned_subdomain())
537  {
538  consider_cell = true;
539  break;
540  }
541 
542  if (!consider_cell)
543  continue;
544 
545  // step 2.2: loop through children and append the dof indices to
546  // the appropriate list. We need separate lists for the owned
547  // coarse cell case (which will be part of
548  // restriction/prolongation between level-1 and level) and the
549  // remote case (which needs to store DoF indices for the
550  // operations between level and level+1).
551  AssertDimension(cell->n_children(),
553  std::vector<types::global_dof_index> &next_indices =
554  cell_is_remote ? global_level_dof_indices_remote : global_level_dof_indices;
555  const std::size_t start_index = next_indices.size();
556  next_indices.resize(start_index + elem_info.n_child_cell_dofs,
558  for (unsigned int c=0; c<GeometryInfo<dim>::max_children_per_cell; ++c)
559  {
560  if (cell_is_remote && cell->child(c)->level_subdomain_id() !=
561  tria.locally_owned_subdomain())
562  continue;
563  cell->child(c)->get_mg_dof_indices(local_dof_indices);
564 
565  const IndexSet &owned_level_dofs = mg_dof.locally_owned_mg_dofs(level);
566  for (unsigned int i=0; i<local_dof_indices.size(); ++i)
567  if (!owned_level_dofs.is_element(local_dof_indices[i]))
568  ghosted_level_dofs.push_back(local_dof_indices[i]);
569 
570  add_child_indices<dim>(c, fe.dofs_per_cell - fe.dofs_per_vertex,
571  fe.degree, elem_info.lexicographic_numbering,
572  local_dof_indices,
573  &next_indices[start_index]);
574 
575  // step 2.3 store the connectivity to the parent
576  if (cell->child(c)->has_children() &&
577  (tria.locally_owned_subdomain()==numbers::invalid_subdomain_id
578  || cell->child(c)->level_subdomain_id()==tria.locally_owned_subdomain()
579  ))
580  {
581  const unsigned int child_index = coarse_level_indices[level][cell->child(c)->index()];
582  AssertIndexRange(child_index, parent_child_connect[level].size());
583  unsigned int parent_index = counter;
584  // remote cells, i.e., cells where we work on a further
585  // level but are not treated on the current level, need to
586  // be placed at the end of the list; however, we do not
587  // yet know the exact position in the array, so shift
588  // their parent index by the number of cells so we can set
589  // the correct number after the end of this loop
590  if (cell_is_remote)
591  parent_index = start_index/elem_info.n_child_cell_dofs + tria.n_cells(level);
592  parent_child_connect[level][child_index] =
593  std::make_pair(parent_index, c);
594  AssertIndexRange(mg_dof.get_fe().dofs_per_cell,
595  static_cast<unsigned short>(-1));
596 
597  // set Dirichlet boundary conditions (as a list of
598  // constrained DoFs) for the child
599  if (mg_constrained_dofs != 0)
600  for (unsigned int i=0; i<mg_dof.get_fe().dofs_per_cell; ++i)
601  if (mg_constrained_dofs->is_boundary_index(level,
602  local_dof_indices[elem_info.lexicographic_numbering[i]]))
603  dirichlet_indices[level][child_index].push_back(i);
604  }
605  }
606  if (!cell_is_remote)
607  {
608  AssertIndexRange(static_cast<unsigned int>(cell->index()),
609  coarse_level_indices[level-1].size());
610  coarse_level_indices[level-1][cell->index()] = counter++;
611  }
612 
613  // step 2.4: include indices for the coarsest cells. we still
614  // insert the indices as if they were from a child in order to use
615  // the same code (the coarsest level does not matter much in terms
616  // of memory, so we gain in code simplicity)
617  if (level == 1 && !cell_is_remote)
618  {
619  cell->get_mg_dof_indices(local_dof_indices);
620 
621  const IndexSet &owned_level_dofs_l0 = mg_dof.locally_owned_mg_dofs(0);
622  for (unsigned int i=0; i<local_dof_indices.size(); ++i)
623  if (!owned_level_dofs_l0.is_element(local_dof_indices[i]))
624  ghosted_level_dofs_l0.push_back(local_dof_indices[i]);
625 
626  const std::size_t start_index = global_level_dof_indices_l0.size();
627  global_level_dof_indices_l0.resize(start_index+elem_info.n_child_cell_dofs,
629  add_child_indices<dim>(0, fe.dofs_per_cell - fe.dofs_per_vertex,
630  fe.degree, elem_info.lexicographic_numbering,
631  local_dof_indices,
632  &global_level_dof_indices_l0[start_index]);
633 
634  dirichlet_indices[0].push_back(std::vector<unsigned short>());
635  if (mg_constrained_dofs != 0)
636  for (unsigned int i=0; i<mg_dof.get_fe().dofs_per_cell; ++i)
637  if (mg_constrained_dofs->is_boundary_index(0, local_dof_indices[elem_info.lexicographic_numbering[i]]))
638  dirichlet_indices[0].back().push_back(i);
639  }
640  }
641 
642  // step 2.5: store information about the current level and prepare the
643  // Dirichlet indices and parent-child relationship for the next
644  // coarser level
645  AssertDimension(counter*elem_info.n_child_cell_dofs, global_level_dof_indices.size());
646  n_owned_level_cells[level-1] = counter;
647  dirichlet_indices[level-1].resize(counter);
648  parent_child_connect[level-1].
649  resize(counter, std::make_pair(numbers::invalid_unsigned_int,
651 
652  // step 2.6: put the cells with remotely owned parent to the end of
653  // the list (these are needed for the transfer from level to level+1
654  // but not for the transfer from level-1 to level).
655  if (level < n_levels-1)
656  for (std::vector<std::pair<unsigned int,unsigned int> >::iterator
657  i=parent_child_connect[level].begin(); i!=parent_child_connect[level].end(); ++i)
658  if (i->first >= tria.n_cells(level))
659  {
660  i->first -= tria.n_cells(level);
661  i->first += counter;
662  }
663 
664  // step 2.7: Initialize the ghosted vector
665  const parallel::Triangulation<dim,dim> *ptria =
666  (dynamic_cast<const parallel::Triangulation<dim,dim>*> (&tria));
667  const MPI_Comm communicator =
668  ptria != 0 ? ptria->get_communicator() : MPI_COMM_SELF;
669 
670  reinit_ghosted_vector (mg_dof.locally_owned_mg_dofs(level),
671  ghosted_level_dofs, communicator,
672  ghosted_level_vector[level],
673  copy_indices_global_mine[level]);
674 
675  copy_indices_to_mpi_local_numbers(*ghosted_level_vector[level].get_partitioner(),
676  global_level_dof_indices,
677  global_level_dof_indices_remote,
678  level_dof_indices[level]);
679  // step 2.8: Initialize the ghosted vector for level 0
680  if (level == 1)
681  {
682  for (unsigned int i = 0; i<parent_child_connect[0].size(); ++i)
683  parent_child_connect[0][i] = std::make_pair(i, 0U);
684 
685  reinit_ghosted_vector (mg_dof.locally_owned_mg_dofs(0),
686  ghosted_level_dofs_l0, communicator,
687  ghosted_level_vector[0],
688  copy_indices_global_mine[0]);
689 
690  copy_indices_to_mpi_local_numbers(*ghosted_level_vector[0].get_partitioner(),
691  global_level_dof_indices_l0,
692  std::vector<types::global_dof_index>(),
693  level_dof_indices[0]);
694  }
695  }
696 
697  // ---------------------- 3. compute weights to make restriction additive
698 
699  const unsigned int n_child_dofs_1d = fe.degree + 1 + fe.dofs_per_cell - fe.dofs_per_vertex;
700 
701  // get the valence of the individual components and compute the weights as
702  // the inverse of the valence
703  weights_on_refined.resize(n_levels-1);
704  for (unsigned int level = 1; level<n_levels; ++level)
705  {
706  ghosted_level_vector[level] = 0;
707  for (unsigned int c=0; c<n_owned_level_cells[level-1]; ++c)
708  for (unsigned int j=0; j<elem_info.n_child_cell_dofs; ++j)
709  ghosted_level_vector[level].local_element(level_dof_indices[level][elem_info.n_child_cell_dofs*c+j]) += Number(1.);
710  ghosted_level_vector[level].compress(VectorOperation::add);
711  ghosted_level_vector[level].update_ghost_values();
712 
713  std::vector<unsigned int> degree_to_3 (n_child_dofs_1d);
714  degree_to_3[0] = 0;
715  for (unsigned int i=1; i<n_child_dofs_1d-1; ++i)
716  degree_to_3[i] = 1;
717  degree_to_3.back() = 2;
718 
719  // we only store 3^dim weights because all dofs on a line have the
720  // same valence, and all dofs on a quad have the same valence.
721  weights_on_refined[level-1].resize(n_owned_level_cells[level-1]*Utilities::fixed_power<dim>(3));
722  for (unsigned int c=0; c<n_owned_level_cells[level-1]; ++c)
723  for (unsigned int k=0, m=0; k<(dim>2 ? n_child_dofs_1d : 1); ++k)
724  for (unsigned int j=0; j<(dim>1 ? n_child_dofs_1d : 1); ++j)
725  {
726  unsigned int shift = 9*degree_to_3[k] + 3*degree_to_3[j];
727  for (unsigned int i=0; i<n_child_dofs_1d; ++i, ++m)
728  weights_on_refined[level-1][c*Utilities::fixed_power<dim>(3)+shift+degree_to_3[i]] = Number(1.)/
729  ghosted_level_vector[level].local_element(level_dof_indices[level][elem_info.n_child_cell_dofs*c+m]);
730  }
731  }
732 
733  }
734 
735  }
736 }
737 
738 // Explicit instantiations
739 
740 #include "mg_transfer_internal.inst"
741 
742 DEAL_II_NAMESPACE_CLOSE
void reinit(const size_type size, const bool omit_zeroing_entries=false)
static const unsigned int invalid_unsigned_int
Definition: types.h:170
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1146
const types::subdomain_id invalid_subdomain_id
Definition: types.h:245
void reinit(const Quadrature< 1 > &quad, const FiniteElement< dim > &fe_dim, const unsigned int base_element=0)
virtual size_type size() const
bool is_boundary_index(const unsigned int level, const types::global_dof_index index) const
#define AssertIndexRange(index, range)
Definition: exceptions.h:1170
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
Definition: index_set.h:1463
const unsigned int degree
Definition: fe_base.h:311
#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
unsigned int global_to_local(const types::global_dof_index global_index) const
const unsigned int dofs_per_line
Definition: fe_base.h:244
Definition: point.h:89
size_type size() const
Definition: index_set.h:1419
static ::ExceptionBase & ExcMessage(std::string arg1)
unsigned int global_dof_index
Definition: types.h:88
#define Assert(cond, exc)
Definition: exceptions.h:313
size_type index_within_set(const size_type global_index) const
Definition: index_set.h:1653
virtual MPI_Comm get_communicator() const
Definition: tria_base.cc:146
void extract_locally_relevant_dofs(const DoFHandlerType &dof_handler, IndexSet &dof_set)
Definition: dof_tools.cc:980
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
const unsigned int dofs_per_cell
Definition: fe_base.h:295
const std::vector< Point< dim > > & get_unit_support_points() const
Definition: fe.cc:955
const types::subdomain_id artificial_subdomain_id
Definition: types.h:261
bool at_refinement_edge(const unsigned int level, const types::global_dof_index index) const
#define AssertThrowMPI(error_code)
Definition: exceptions.h:1211
static ::ExceptionBase & ExcNotImplemented()
const unsigned int dofs_per_vertex
Definition: fe_base.h:238
bool is_element(const size_type index) const
Definition: index_set.h:1489
std::vector< unsigned int > lexicographic_numbering
Definition: shape_info.h:190
const types::global_dof_index invalid_dof_index
Definition: types.h:184
const std_cxx11::shared_ptr< const Utilities::MPI::Partitioner > & get_partitioner() const
size_type n_elements() const
Definition: index_set.h:1560
static ::ExceptionBase & ExcInternalError()