Reference documentation for deal.II version 9.0.0
dof_renumbering.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/thread_management.h>
17 #include <deal.II/base/utilities.h>
18 #include <deal.II/base/quadrature_lib.h>
19 #include <deal.II/base/types.h>
20 #include <deal.II/base/template_constraints.h>
21 
22 #include <deal.II/lac/sparsity_pattern.h>
23 #include <deal.II/lac/sparsity_tools.h>
24 #include <deal.II/lac/dynamic_sparsity_pattern.h>
25 #include <deal.II/lac/constraint_matrix.h>
26 
27 #include <deal.II/dofs/dof_accessor.h>
28 #include <deal.II/dofs/dof_handler.h>
29 #include <deal.II/dofs/dof_tools.h>
30 #include <deal.II/dofs/dof_renumbering.h>
31 
32 #include <deal.II/grid/tria_iterator.h>
33 #include <deal.II/grid/tria.h>
34 
35 #include <deal.II/fe/fe.h>
36 #include <deal.II/hp/dof_handler.h>
37 #include <deal.II/hp/fe_collection.h>
38 #include <deal.II/hp/fe_values.h>
39 
40 #include <deal.II/multigrid/mg_tools.h>
41 
42 #include <deal.II/distributed/tria.h>
43 
44 #include <boost/config.hpp>
45 #include <boost/graph/adjacency_list.hpp>
46 #include <boost/graph/cuthill_mckee_ordering.hpp>
47 #include <boost/graph/king_ordering.hpp>
48 #include <boost/graph/minimum_degree_ordering.hpp>
49 #include <boost/graph/properties.hpp>
50 #include <boost/graph/bandwidth.hpp>
51 #include <boost/random.hpp>
52 #include <boost/random/uniform_int_distribution.hpp>
53 
54 #include <vector>
55 #include <map>
56 #include <algorithm>
57 #include <cmath>
58 #include <functional>
59 
60 
61 DEAL_II_NAMESPACE_OPEN
62 
63 namespace DoFRenumbering
64 {
65  namespace boost
66  {
67  namespace boosttypes
68  {
69  using namespace ::boost;
70  using namespace std;
71 
72  typedef adjacency_list<vecS, vecS, undirectedS,
73  property<vertex_color_t, default_color_type,
74  property<vertex_degree_t,int> > > Graph;
75  typedef graph_traits<Graph>::vertex_descriptor Vertex;
76  typedef graph_traits<Graph>::vertices_size_type size_type;
77 
78  typedef std::pair<size_type, size_type> Pair;
79  }
80 
81 
82  namespace internal
83  {
84  template <typename DoFHandlerType>
85  void create_graph
86  (const DoFHandlerType &dof_handler,
87  const bool use_constraints,
88  boosttypes::Graph &graph,
89  boosttypes::property_map<boosttypes::Graph,boosttypes::vertex_degree_t>::type &graph_degree)
90  {
91  {
92  // create intermediate sparsity pattern
93  // (faster than directly submitting
94  // indices)
95  ConstraintMatrix constraints;
96  if (use_constraints)
97  DoFTools::make_hanging_node_constraints (dof_handler, constraints);
98  constraints.close ();
99  DynamicSparsityPattern dsp (dof_handler.n_dofs(),
100  dof_handler.n_dofs());
101  DoFTools::make_sparsity_pattern (dof_handler, dsp, constraints);
102 
103  // submit the entries to the boost graph
104  for (unsigned int row=0; row<dsp.n_rows(); ++row)
105  for (unsigned int col=0; col < dsp.row_length(row); ++col)
106  add_edge (row, dsp.column_number (row, col), graph);
107  }
108 
109  boosttypes::graph_traits<boosttypes::Graph>::vertex_iterator ui, ui_end;
110 
111  graph_degree = get(::boost::vertex_degree, graph);
112  for (::boost::tie(ui, ui_end) = vertices(graph); ui != ui_end; ++ui)
113  graph_degree[*ui] = degree(*ui, graph);
114  }
115  }
116 
117 
118  template <typename DoFHandlerType>
119  void
120  Cuthill_McKee (DoFHandlerType &dof_handler,
121  const bool reversed_numbering,
122  const bool use_constraints)
123  {
124  std::vector<types::global_dof_index> renumbering(dof_handler.n_dofs(),
126  compute_Cuthill_McKee(renumbering, dof_handler, reversed_numbering,
127  use_constraints);
128 
129  // actually perform renumbering;
130  // this is dimension specific and
131  // thus needs an own function
132  dof_handler.renumber_dofs (renumbering);
133  }
134 
135 
136  template <typename DoFHandlerType>
137  void
138  compute_Cuthill_McKee (std::vector<types::global_dof_index> &new_dof_indices,
139  const DoFHandlerType &dof_handler,
140  const bool reversed_numbering,
141  const bool use_constraints)
142  {
143  boosttypes::Graph
144  graph(dof_handler.n_dofs());
145  boosttypes::property_map<boosttypes::Graph,boosttypes::vertex_degree_t>::type
146  graph_degree;
147 
148  internal::create_graph (dof_handler, use_constraints, graph, graph_degree);
149 
150  boosttypes::property_map<boosttypes::Graph, boosttypes::vertex_index_t>::type
151  index_map = get(::boost::vertex_index, graph);
152 
153 
154  std::vector<boosttypes::Vertex> inv_perm(num_vertices(graph));
155 
156  if (reversed_numbering == false)
157  ::boost::cuthill_mckee_ordering(graph, inv_perm.rbegin(),
158  get(::boost::vertex_color, graph),
159  make_degree_map(graph));
160  else
161  ::boost::cuthill_mckee_ordering(graph, inv_perm.begin(),
162  get(::boost::vertex_color, graph),
163  make_degree_map(graph));
164 
165  for (boosttypes::size_type c = 0; c != inv_perm.size(); ++c)
166  new_dof_indices[index_map[inv_perm[c]]] = c;
167 
168  Assert (std::find (new_dof_indices.begin(), new_dof_indices.end(),
169  numbers::invalid_dof_index) == new_dof_indices.end(),
170  ExcInternalError());
171  }
172 
173 
174 
175  template <typename DoFHandlerType>
176  void
177  king_ordering (DoFHandlerType &dof_handler,
178  const bool reversed_numbering,
179  const bool use_constraints)
180  {
181  std::vector<types::global_dof_index> renumbering(dof_handler.n_dofs(),
183  compute_king_ordering(renumbering, dof_handler, reversed_numbering,
184  use_constraints);
185 
186  // actually perform renumbering;
187  // this is dimension specific and
188  // thus needs an own function
189  dof_handler.renumber_dofs (renumbering);
190  }
191 
192 
193  template <typename DoFHandlerType>
194  void
195  compute_king_ordering (std::vector<types::global_dof_index> &new_dof_indices,
196  const DoFHandlerType &dof_handler,
197  const bool reversed_numbering,
198  const bool use_constraints)
199  {
200  boosttypes::Graph
201  graph(dof_handler.n_dofs());
202  boosttypes::property_map<boosttypes::Graph,boosttypes::vertex_degree_t>::type
203  graph_degree;
204 
205  internal::create_graph (dof_handler, use_constraints, graph, graph_degree);
206 
207  boosttypes::property_map<boosttypes::Graph, boosttypes::vertex_index_t>::type
208  index_map = get(::boost::vertex_index, graph);
209 
210 
211  std::vector<boosttypes::Vertex> inv_perm(num_vertices(graph));
212 
213  if (reversed_numbering == false)
214  ::boost::king_ordering(graph, inv_perm.rbegin());
215  else
216  ::boost::king_ordering(graph, inv_perm.begin());
217 
218  for (boosttypes::size_type c = 0; c != inv_perm.size(); ++c)
219  new_dof_indices[index_map[inv_perm[c]]] = c;
220 
221  Assert (std::find (new_dof_indices.begin(), new_dof_indices.end(),
222  numbers::invalid_dof_index) == new_dof_indices.end(),
223  ExcInternalError());
224  }
225 
226 
227 
228  template <typename DoFHandlerType>
229  void
230  minimum_degree (DoFHandlerType &dof_handler,
231  const bool reversed_numbering,
232  const bool use_constraints)
233  {
234  std::vector<types::global_dof_index> renumbering(dof_handler.n_dofs(),
236  compute_minimum_degree(renumbering, dof_handler, reversed_numbering,
237  use_constraints);
238 
239  // actually perform renumbering;
240  // this is dimension specific and
241  // thus needs an own function
242  dof_handler.renumber_dofs (renumbering);
243  }
244 
245 
246  template <typename DoFHandlerType>
247  void
248  compute_minimum_degree (std::vector<types::global_dof_index> &new_dof_indices,
249  const DoFHandlerType &dof_handler,
250  const bool reversed_numbering,
251  const bool use_constraints)
252  {
253  (void)use_constraints;
254  Assert (use_constraints == false, ExcNotImplemented());
255 
256  // the following code is pretty
257  // much a verbatim copy of the
258  // sample code for the
259  // minimum_degree_ordering manual
260  // page from the BOOST Graph
261  // Library
262  using namespace ::boost;
263 
264  int delta = 0;
265 
266  // must be BGL directed graph now
267  typedef adjacency_list<vecS, vecS, directedS> Graph;
268 
269  int n = dof_handler.n_dofs();
270 
271  Graph G(n);
272 
273  std::vector<::types::global_dof_index> dofs_on_this_cell;
274 
275  typename DoFHandlerType::active_cell_iterator cell = dof_handler.begin_active(),
276  endc = dof_handler.end();
277 
278  for (; cell!=endc; ++cell)
279  {
280 
281  const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
282 
283  dofs_on_this_cell.resize (dofs_per_cell);
284 
285  cell->get_active_or_mg_dof_indices (dofs_on_this_cell);
286  for (unsigned int i=0; i<dofs_per_cell; ++i)
287  for (unsigned int j=0; j<dofs_per_cell; ++j)
288  if (dofs_on_this_cell[i] > dofs_on_this_cell[j])
289  {
290  add_edge (dofs_on_this_cell[i], dofs_on_this_cell[j], G);
291  add_edge (dofs_on_this_cell[j], dofs_on_this_cell[i], G);
292  }
293  }
294 
295 
296  typedef std::vector<int> Vector;
297 
298 
299  Vector inverse_perm(n, 0);
300 
301  Vector perm(n, 0);
302 
303 
304  Vector supernode_sizes(n, 1);
305  // init has to be 1
306 
307  ::boost::property_map<Graph, vertex_index_t>::type
308  id = get(vertex_index, G);
309 
310 
311  Vector degree(n, 0);
312 
313 
314  minimum_degree_ordering
315  (G,
316  make_iterator_property_map(degree.begin(), id, degree[0]),
317  inverse_perm.data(),
318  perm.data(),
319  make_iterator_property_map(supernode_sizes.begin(), id, supernode_sizes[0]),
320  delta, id);
321 
322 
323  for (int i=0; i<n; ++i)
324  {
325  Assert (std::find (perm.begin(), perm.end(), i)
326  != perm.end(),
327  ExcInternalError());
328  Assert (std::find (inverse_perm.begin(), inverse_perm.end(), i)
329  != inverse_perm.end(),
330  ExcInternalError());
331  Assert (inverse_perm[perm[i]] == i, ExcInternalError());
332  }
333 
334  if (reversed_numbering == true)
335  std::copy (perm.begin(), perm.end(),
336  new_dof_indices.begin());
337  else
338  std::copy (inverse_perm.begin(), inverse_perm.end(),
339  new_dof_indices.begin());
340  }
341 
342  } // namespace boost
343 
344 
345 
346  template <typename DoFHandlerType>
347  void
348  Cuthill_McKee (DoFHandlerType &dof_handler,
349  const bool reversed_numbering,
350  const bool use_constraints,
351  const std::vector<types::global_dof_index> &starting_indices)
352  {
353  std::vector<types::global_dof_index> renumbering(dof_handler.locally_owned_dofs().n_elements(),
355  compute_Cuthill_McKee(renumbering, dof_handler, reversed_numbering,
356  use_constraints, starting_indices);
357 
358  // actually perform renumbering;
359  // this is dimension specific and
360  // thus needs an own function
361  dof_handler.renumber_dofs (renumbering);
362  }
363 
364 
365 
366  template <typename DoFHandlerType>
367  void
368  compute_Cuthill_McKee (std::vector<types::global_dof_index> &new_indices,
369  const DoFHandlerType &dof_handler,
370  const bool reversed_numbering,
371  const bool use_constraints,
372  const std::vector<types::global_dof_index> &starting_indices)
373  {
374  // see if there is anything to do at all or whether we can skip the work on this processor
375  if (dof_handler.locally_owned_dofs().n_elements() == 0)
376  {
377  Assert (new_indices.size() == 0, ExcInternalError());
378  return;
379  }
380 
381  // make the connection graph
382  //
383  // note that if constraints are not requested, then the 'constraints'
384  // object will be empty and using it has no effect
385  IndexSet locally_relevant_dofs;
386  DoFTools::extract_locally_relevant_dofs(dof_handler, locally_relevant_dofs);
387 
388  ConstraintMatrix constraints;
389  if (use_constraints)
390  {
391  constraints.reinit(locally_relevant_dofs);
392  DoFTools::make_hanging_node_constraints (dof_handler, constraints);
393  }
394  constraints.close ();
395 
396  const IndexSet &locally_owned_dofs = dof_handler.locally_owned_dofs();
397 
398  // see if we can get away with the sequential algorithm
399  if (locally_owned_dofs.n_elements() == locally_owned_dofs.size())
400  {
401  AssertDimension(new_indices.size(), dof_handler.n_dofs());
402 
403  DynamicSparsityPattern dsp (dof_handler.n_dofs(),
404  dof_handler.n_dofs());
405  DoFTools::make_sparsity_pattern (dof_handler, dsp, constraints);
406 
407  SparsityTools::reorder_Cuthill_McKee (dsp, new_indices,
408  starting_indices);
409  if (reversed_numbering)
410  new_indices = Utilities::reverse_permutation (new_indices);
411  }
412  else
413  {
414  // we are in the parallel case where we need to work in the
415  // local index space, i.e., the locally owned part of the
416  // sparsity pattern.
417  //
418  // first figure out whether the user only gave us starting
419  // indices that are locally owned, or that are only locally
420  // relevant. in the process, also check that all indices
421  // really belong to at least the locally relevant ones
422  IndexSet locally_active_dofs;
423  DoFTools::extract_locally_active_dofs(dof_handler, locally_active_dofs);
424 
425  bool needs_locally_active = false;
426  for (unsigned int i=0; i<starting_indices.size(); ++i)
427  {
428  if ((needs_locally_active == /* previously already set to */true)
429  ||
430  (locally_owned_dofs.is_element (starting_indices[i]) == false))
431  {
432  Assert (locally_active_dofs.is_element (starting_indices[i]),
433  ExcMessage ("You specified global degree of freedom "
434  + Utilities::to_string(starting_indices[i]) +
435  " as a starting index, but this index is not among the "
436  "locally active ones on this processor, as required "
437  "for this function."));
438  needs_locally_active = true;
439  }
440  }
441 
442  const IndexSet index_set_to_use = (needs_locally_active ?
443  locally_active_dofs :
444  locally_owned_dofs);
445 
446  // then create first the global sparsity pattern, and then the local
447  // sparsity pattern from the global one by transferring its indices to
448  // processor-local (locally owned or locally active) index space
449  DynamicSparsityPattern dsp (dof_handler.n_dofs(),
450  dof_handler.n_dofs(),
451  index_set_to_use);
452  DoFTools::make_sparsity_pattern (dof_handler, dsp, constraints);
453 
454  DynamicSparsityPattern local_sparsity(index_set_to_use.n_elements(),
455  index_set_to_use.n_elements());
456  std::vector<types::global_dof_index> row_entries;
457  for (unsigned int i=0; i<index_set_to_use.n_elements(); ++i)
458  {
459  const types::global_dof_index row = index_set_to_use.nth_index_in_set(i);
460  const unsigned int row_length = dsp.row_length(row);
461  row_entries.clear();
462  for (unsigned int j=0; j<row_length; ++j)
463  {
464  const unsigned int col = dsp.column_number(row, j);
465  if (col != row && index_set_to_use.is_element(col))
466  row_entries.push_back(index_set_to_use.index_within_set(col));
467  }
468  local_sparsity.add_entries(i, row_entries.begin(), row_entries.end(),
469  true);
470  }
471 
472  // translate starting indices from global to local indices
473  std::vector<types::global_dof_index> local_starting_indices (starting_indices.size());
474  for (unsigned int i=0; i<starting_indices.size(); ++i)
475  local_starting_indices[i] = index_set_to_use.index_within_set(starting_indices[i]);
476 
477  // then do the renumbering on the locally owned portion
478  AssertDimension(new_indices.size(), locally_owned_dofs.n_elements());
479  std::vector<types::global_dof_index> my_new_indices (index_set_to_use.n_elements());
480  SparsityTools::reorder_Cuthill_McKee (local_sparsity, my_new_indices,
481  local_starting_indices);
482  if (reversed_numbering)
483  my_new_indices = Utilities::reverse_permutation (my_new_indices);
484 
485  // now that we have a re-enumeration of all DoFs, we need to throw
486  // out the ones that are not locally owned in case we have worked
487  // with the locally active ones. that's because the renumbering
488  // functions only want new indices for the locally owned DoFs (other
489  // processors are responsible for renumbering the ones that are
490  // on cell interfaces)
491  if (needs_locally_active == true)
492  {
493  // first step: figure out which DoF indices to eliminate
494  IndexSet active_but_not_owned_dofs = locally_active_dofs;
495  active_but_not_owned_dofs.subtract_set(locally_owned_dofs);
496 
497  std::set<types::global_dof_index> erase_these_indices;
498  for (const auto &p : active_but_not_owned_dofs)
499  {
500  const auto index = index_set_to_use.index_within_set(p);
501  Assert (index < index_set_to_use.n_elements(), ExcInternalError());
502  erase_these_indices.insert (my_new_indices[index]);
503  my_new_indices[index] = numbers::invalid_dof_index;
504  }
505  Assert (erase_these_indices.size() == active_but_not_owned_dofs.n_elements(),
506  ExcInternalError());
507  Assert (static_cast<unsigned int>(std::count (my_new_indices.begin(),
508  my_new_indices.end(),
510  == active_but_not_owned_dofs.n_elements(),
511  ExcInternalError());
512 
513  // then compute a renumbering of the remaining ones
514  std::vector<types::global_dof_index> translate_indices (my_new_indices.size());
515  {
516  std::set<types::global_dof_index>::const_iterator
517  next_erased_index = erase_these_indices.begin();
518  types::global_dof_index next_new_index = 0;
519  for (unsigned int i=0; i<translate_indices.size(); ++i)
520  if ((next_erased_index != erase_these_indices.end())
521  &&
522  (*next_erased_index == i))
523  {
524  translate_indices[i] = numbers::invalid_dof_index;
525  ++next_erased_index;
526  }
527  else
528  {
529  translate_indices[i] = next_new_index;
530  ++next_new_index;
531  }
532  Assert (next_new_index == locally_owned_dofs.n_elements(),
533  ExcInternalError());
534  }
535 
536  // and then do the renumbering of the result of the
537  // Cuthill-McKee algorithm above, right into the output array
538  new_indices.clear();
539  new_indices.reserve(locally_owned_dofs.n_elements());
540  for (const auto &p : my_new_indices)
542  {
543  Assert (translate_indices[p] != numbers::invalid_dof_index,
544  ExcInternalError());
545  new_indices.push_back (translate_indices[p]);
546  }
547  Assert (new_indices.size() == locally_owned_dofs.n_elements(),
548  ExcInternalError());
549  }
550  else
551  new_indices = std::move (my_new_indices);
552 
553  // convert indices back to global index space. in both of the branches
554  // above, we ended up with new_indices only containing the local
555  // indices of the locally-owned DoFs. so that's where we get the
556  // indices
557  for (std::size_t i=0; i<new_indices.size(); ++i)
558  new_indices[i] = locally_owned_dofs.nth_index_in_set(new_indices[i]);
559  }
560  }
561 
562 
563 
564  template <typename DoFHandlerType>
565  void Cuthill_McKee (DoFHandlerType &dof_handler,
566  const unsigned int level,
567  const bool reversed_numbering,
568  const std::vector<types::global_dof_index> &starting_indices)
569  {
570  Assert(dof_handler.n_dofs(level) != numbers::invalid_dof_index,
572 
573  // make the connection graph
574  DynamicSparsityPattern dsp (dof_handler.n_dofs(level),
575  dof_handler.n_dofs(level));
576  MGTools::make_sparsity_pattern (dof_handler, dsp, level);
577 
578  std::vector<types::global_dof_index> new_indices(dsp.n_rows());
579  SparsityTools::reorder_Cuthill_McKee (dsp, new_indices,
580  starting_indices);
581 
582  if (reversed_numbering)
583  new_indices = Utilities::reverse_permutation (new_indices);
584 
585  // actually perform renumbering;
586  // this is dimension specific and
587  // thus needs an own function
588  dof_handler.renumber_dofs (level, new_indices);
589  }
590 
591 
592 
593  template <typename DoFHandlerType>
594  void
595  component_wise (DoFHandlerType &dof_handler,
596  const std::vector<unsigned int> &component_order_arg)
597  {
598  std::vector<types::global_dof_index> renumbering (dof_handler.n_locally_owned_dofs(),
600 
601  typename DoFHandlerType::active_cell_iterator
602  start = dof_handler.begin_active();
603  const typename DoFHandlerType::level_cell_iterator
604  end = dof_handler.end();
605 
606  const types::global_dof_index result =
607  compute_component_wise<DoFHandlerType::dimension,DoFHandlerType::space_dimension>
608  (renumbering, start, end, component_order_arg, false);
609  if (result == 0)
610  return;
611 
612  // verify that the last numbered
613  // degree of freedom is either
614  // equal to the number of degrees
615  // of freedom in total (the
616  // sequential case) or in the
617  // distributed case at least
618  // makes sense
619  Assert ((result == dof_handler.n_locally_owned_dofs())
620  ||
621  ((dof_handler.n_locally_owned_dofs() < dof_handler.n_dofs())
622  &&
623  (result <= dof_handler.n_dofs())),
624  ExcInternalError());
625 
626  dof_handler.renumber_dofs (renumbering);
627  }
628 
629 
630 
631  template <typename DoFHandlerType>
632  void
633  component_wise (DoFHandlerType &dof_handler,
634  const unsigned int level,
635  const std::vector<unsigned int> &component_order_arg)
636  {
637  Assert(dof_handler.n_dofs(level) != numbers::invalid_dof_index,
639 
640  std::vector<types::global_dof_index> renumbering (dof_handler.n_dofs(level),
642 
643  typename DoFHandlerType::level_cell_iterator start =dof_handler.begin(level);
644  typename DoFHandlerType::level_cell_iterator end = dof_handler.end(level);
645 
646  const types::global_dof_index result =
647  compute_component_wise<DoFHandlerType::dimension, DoFHandlerType::space_dimension>
648  (renumbering, start, end, component_order_arg, true);
649 
650  if (result == 0) return;
651 
652  Assert (result == dof_handler.n_dofs(level),
653  ExcInternalError());
654 
655  if (renumbering.size()!=0)
656  dof_handler.renumber_dofs (level, renumbering);
657  }
658 
659 
660 
661  template <int dim, int spacedim, typename CellIterator>
663  compute_component_wise (std::vector<types::global_dof_index> &new_indices,
664  const CellIterator &start,
665  const typename identity<CellIterator>::type &end,
666  const std::vector<unsigned int> &component_order_arg,
667  const bool is_level_operation)
668  {
670  fe_collection (start->get_dof_handler().get_fe_collection ());
671 
672  // do nothing if the FE has only
673  // one component
674  if (fe_collection.n_components() == 1)
675  {
676  new_indices.resize(0);
677  return 0;
678  }
679 
680  // Copy last argument into a
681  // writable vector.
682  std::vector<unsigned int> component_order (component_order_arg);
683  // If the last argument was an
684  // empty vector, set up things to
685  // store components in the order
686  // found in the system.
687  if (component_order.size() == 0)
688  for (unsigned int i=0; i<fe_collection.n_components(); ++i)
689  component_order.push_back (i);
690 
691  Assert (component_order.size() == fe_collection.n_components(),
692  ExcDimensionMismatch(component_order.size(), fe_collection.n_components()));
693 
694  for (unsigned int i=0; i<component_order.size(); ++i)
695  Assert(component_order[i] < fe_collection.n_components(),
696  ExcIndexRange(component_order[i], 0, fe_collection.n_components()));
697 
698  // vector to hold the dof indices on
699  // the cell we visit at a time
700  std::vector<types::global_dof_index> local_dof_indices;
701 
702  // prebuilt list to which component
703  // a given dof on a cell
704  // should go. note that we get into
705  // trouble here if the shape
706  // function is not primitive, since
707  // then there is no single vector
708  // component to which it
709  // belongs. in this case, assign it
710  // to the first vector component to
711  // which it belongs
712  std::vector<std::vector<unsigned int> > component_list (fe_collection.size());
713  for (unsigned int f=0; f<fe_collection.size(); ++f)
714  {
715  const FiniteElement<dim,spacedim> &fe = fe_collection[f];
716  const unsigned int dofs_per_cell = fe.dofs_per_cell;
717  component_list[f].resize(dofs_per_cell);
718  for (unsigned int i=0; i<dofs_per_cell; ++i)
719  if (fe.is_primitive(i))
720  component_list[f][i]
721  = component_order[fe.system_to_component_index(i).first];
722  else
723  {
724  const unsigned int comp
726 
727  // then associate this degree
728  // of freedom with this
729  // component
730  component_list[f][i] = component_order[comp];
731  }
732  }
733 
734  // set up a map where for each
735  // component the respective degrees
736  // of freedom are collected.
737  //
738  // note that this map is sorted by
739  // component but that within each
740  // component it is NOT sorted by
741  // dof index. note also that some
742  // dof indices are entered
743  // multiply, so we will have to
744  // take care of that
745  std::vector<std::vector<types::global_dof_index> >
746  component_to_dof_map (fe_collection.n_components());
747  for (CellIterator cell=start; cell!=end; ++cell)
748  {
749  if (is_level_operation)
750  {
751  //we are dealing with mg dofs, skip foreign level cells:
752  if (!cell->is_locally_owned_on_level())
753  continue;
754  }
755  else
756  {
757  //we are dealing with active dofs, skip the loop if not locally
758  // owned:
759  if (!cell->is_locally_owned())
760  continue;
761  }
762  // on each cell: get dof indices
763  // and insert them into the global
764  // list using their component
765  const unsigned int fe_index = cell->active_fe_index();
766  const unsigned int dofs_per_cell = fe_collection[fe_index].dofs_per_cell;
767  local_dof_indices.resize (dofs_per_cell);
768  cell->get_active_or_mg_dof_indices (local_dof_indices);
769  for (unsigned int i=0; i<dofs_per_cell; ++i)
770  if (start->get_dof_handler().locally_owned_dofs().is_element(local_dof_indices[i]))
771  component_to_dof_map[component_list[fe_index][i]].
772  push_back (local_dof_indices[i]);
773  }
774 
775  // now we've got all indices sorted
776  // into buckets labeled by their
777  // target component number. we've
778  // only got to traverse this list
779  // and assign the new indices
780  //
781  // however, we first want to sort
782  // the indices entered into the
783  // buckets to preserve the order
784  // within each component and during
785  // this also remove duplicate
786  // entries
787  //
788  // note that we no longer have to
789  // care about non-primitive shape
790  // functions since the buckets
791  // corresponding to the second and
792  // following vector components of a
793  // non-primitive FE will simply be
794  // empty, everything being shoved
795  // into the first one. The same
796  // holds if several components were
797  // joined into a single target.
798  for (unsigned int component=0; component<fe_collection.n_components();
799  ++component)
800  {
801  std::sort (component_to_dof_map[component].begin(),
802  component_to_dof_map[component].end());
803  component_to_dof_map[component]
804  .erase (std::unique (component_to_dof_map[component].begin(),
805  component_to_dof_map[component].end()),
806  component_to_dof_map[component].end());
807  }
808 
809  // calculate the number of locally owned
810  // DoFs per bucket
811  const unsigned int n_buckets = fe_collection.n_components();
812  std::vector<types::global_dof_index> shifts(n_buckets);
813 
815  = (dynamic_cast<const parallel::Triangulation<dim,spacedim>*>
816  (&start->get_dof_handler().get_triangulation())))
817  {
818 #ifdef DEAL_II_WITH_MPI
819  std::vector<types::global_dof_index> local_dof_count(n_buckets);
820 
821  for (unsigned int c=0; c<n_buckets; ++c)
822  local_dof_count[c] = component_to_dof_map[c].size();
823 
824 
825  // gather information from all CPUs
826  std::vector<types::global_dof_index>
827  all_dof_counts(fe_collection.n_components() *
828  Utilities::MPI::n_mpi_processes (tria->get_communicator()));
829 
830  const int ierr = MPI_Allgather ( local_dof_count.data(),
831  n_buckets, DEAL_II_DOF_INDEX_MPI_TYPE,
832  all_dof_counts.data(),
833  n_buckets, DEAL_II_DOF_INDEX_MPI_TYPE,
834  tria->get_communicator());
835  AssertThrowMPI(ierr);
836 
837  for (unsigned int i=0; i<n_buckets; ++i)
838  Assert (all_dof_counts[n_buckets*tria->locally_owned_subdomain()+i]
839  ==
840  local_dof_count[i],
841  ExcInternalError());
842 
843  //calculate shifts
844  unsigned int cumulated = 0;
845  for (unsigned int c=0; c<n_buckets; ++c)
846  {
847  shifts[c]=cumulated;
848  for (types::subdomain_id i=0; i<tria->locally_owned_subdomain(); ++i)
849  shifts[c] += all_dof_counts[c+n_buckets*i];
850  for (unsigned int i=0; i<Utilities::MPI::n_mpi_processes (tria->get_communicator()); ++i)
851  cumulated += all_dof_counts[c+n_buckets*i];
852  }
853 #else
854  (void)tria;
855  Assert (false, ExcInternalError());
856 #endif
857  }
858  else
859  {
860  shifts[0] = 0;
861  for (unsigned int c=1; c<fe_collection.n_components(); ++c)
862  shifts[c] = shifts[c-1] + component_to_dof_map[c-1].size();
863  }
864 
865 
866 
867 
868  // now concatenate all the
869  // components in the order the user
870  // desired to see
871  types::global_dof_index next_free_index = 0;
872  for (unsigned int component=0; component<fe_collection.n_components(); ++component)
873  {
874  const typename std::vector<types::global_dof_index>::const_iterator
875  begin_of_component = component_to_dof_map[component].begin(),
876  end_of_component = component_to_dof_map[component].end();
877 
878  next_free_index = shifts[component];
879 
880  for (typename std::vector<types::global_dof_index>::const_iterator
881  dof_index = begin_of_component;
882  dof_index != end_of_component; ++dof_index)
883  {
884  Assert (start->get_dof_handler().locally_owned_dofs()
885  .index_within_set(*dof_index)
886  <
887  new_indices.size(),
888  ExcInternalError());
889  new_indices[start->get_dof_handler().locally_owned_dofs()
890  .index_within_set(*dof_index)]
891  = next_free_index++;
892  }
893  }
894 
895  return next_free_index;
896  }
897 
898 
899 
900  template <int dim, int spacedim>
901  void
903  {
904  std::vector<types::global_dof_index> renumbering (dof_handler.n_locally_owned_dofs(),
906 
908  start = dof_handler.begin_active();
909  const typename DoFHandler<dim,spacedim>::level_cell_iterator
910  end = dof_handler.end();
911 
912  const types::global_dof_index result =
913  compute_block_wise<dim, spacedim, typename DoFHandler<dim,spacedim>::active_cell_iterator,
914  typename DoFHandler<dim,spacedim>::level_cell_iterator>
915  (renumbering, start, end, false);
916  if (result == 0)
917  return;
918 
919  // verify that the last numbered
920  // degree of freedom is either
921  // equal to the number of degrees
922  // of freedom in total (the
923  // sequential case) or in the
924  // distributed case at least
925  // makes sense
926  Assert ((result == dof_handler.n_locally_owned_dofs())
927  ||
928  ((dof_handler.n_locally_owned_dofs() < dof_handler.n_dofs())
929  &&
930  (result <= dof_handler.n_dofs())),
931  ExcInternalError());
932 
933  dof_handler.renumber_dofs (renumbering);
934  }
935 
936 
937 
938  template <int dim, int spacedim>
939  void
941  {
942  std::vector<types::global_dof_index> renumbering (dof_handler.n_dofs(),
944 
946  start = dof_handler.begin_active();
947  const typename hp::DoFHandler<dim,spacedim>::level_cell_iterator
948  end = dof_handler.end();
949 
950  const types::global_dof_index result =
951  compute_block_wise<dim, spacedim, typename hp::DoFHandler<dim,spacedim>::active_cell_iterator,
952  typename hp::DoFHandler<dim,spacedim>::level_cell_iterator>(renumbering,
953  start, end, false);
954 
955  if (result == 0)
956  return;
957 
958  Assert (result == dof_handler.n_dofs(),
959  ExcInternalError());
960 
961  dof_handler.renumber_dofs (renumbering);
962  }
963 
964 
965 
966  template <int dim, int spacedim>
967  void
969  const unsigned int level)
970  {
971  Assert(dof_handler.n_dofs(level) != numbers::invalid_dof_index,
973 
974  std::vector<types::global_dof_index> renumbering (dof_handler.n_dofs(level),
976 
977  typename DoFHandler<dim, spacedim>::level_cell_iterator
978  start =dof_handler.begin(level);
979  typename DoFHandler<dim, spacedim>::level_cell_iterator
980  end = dof_handler.end(level);
981 
982  const types::global_dof_index result =
983  compute_block_wise<dim, spacedim, typename DoFHandler<dim, spacedim>::level_cell_iterator,
984  typename DoFHandler<dim, spacedim>::level_cell_iterator>(
985  renumbering, start, end, true);
986 
987  if (result == 0) return;
988 
989  Assert (result == dof_handler.n_dofs(level),
990  ExcInternalError());
991 
992  if (renumbering.size()!=0)
993  dof_handler.renumber_dofs (level, renumbering);
994  }
995 
996 
997 
998  template <int dim, int spacedim, class ITERATOR, class ENDITERATOR>
1000  compute_block_wise (std::vector<types::global_dof_index> &new_indices,
1001  const ITERATOR &start,
1002  const ENDITERATOR &end,
1003  const bool is_level_operation)
1004  {
1006  fe_collection (start->get_dof_handler().get_fe_collection ());
1007 
1008  // do nothing if the FE has only
1009  // one component
1010  if (fe_collection.n_blocks() == 1)
1011  {
1012  new_indices.resize(0);
1013  return 0;
1014  }
1015 
1016  // vector to hold the dof indices on
1017  // the cell we visit at a time
1018  std::vector<types::global_dof_index> local_dof_indices;
1019 
1020  // prebuilt list to which block
1021  // a given dof on a cell
1022  // should go.
1023  std::vector<std::vector<types::global_dof_index> > block_list (fe_collection.size());
1024  for (unsigned int f=0; f<fe_collection.size(); ++f)
1025  {
1026  const FiniteElement<dim,spacedim> &fe = fe_collection[f];
1027  block_list[f].resize(fe.dofs_per_cell);
1028  for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
1029  block_list[f][i]
1030  = fe.system_to_block_index(i).first;
1031  }
1032 
1033  // set up a map where for each
1034  // block the respective degrees
1035  // of freedom are collected.
1036  //
1037  // note that this map is sorted by
1038  // block but that within each
1039  // block it is NOT sorted by
1040  // dof index. note also that some
1041  // dof indices are entered
1042  // multiply, so we will have to
1043  // take care of that
1044  std::vector<std::vector<types::global_dof_index> >
1045  block_to_dof_map (fe_collection.n_blocks());
1046  for (ITERATOR cell=start; cell!=end; ++cell)
1047  {
1048  if (is_level_operation)
1049  {
1050  //we are dealing with mg dofs, skip foreign level cells:
1051  if (!cell->is_locally_owned_on_level())
1052  continue;
1053  }
1054  else
1055  {
1056  //we are dealing with active dofs, skip the loop if not locally
1057  // owned:
1058  if (!cell->is_locally_owned())
1059  continue;
1060  }
1061 
1062  // on each cell: get dof indices
1063  // and insert them into the global
1064  // list using their component
1065  const unsigned int fe_index = cell->active_fe_index();
1066  const unsigned int dofs_per_cell =fe_collection[fe_index].dofs_per_cell;
1067  local_dof_indices.resize (dofs_per_cell);
1068  cell->get_active_or_mg_dof_indices (local_dof_indices);
1069  for (unsigned int i=0; i<dofs_per_cell; ++i)
1070  if (start->get_dof_handler().locally_owned_dofs().is_element(local_dof_indices[i]))
1071  block_to_dof_map[block_list[fe_index][i]].
1072  push_back (local_dof_indices[i]);
1073  }
1074 
1075  // now we've got all indices sorted
1076  // into buckets labeled by their
1077  // target block number. we've
1078  // only got to traverse this list
1079  // and assign the new indices
1080  //
1081  // however, we first want to sort
1082  // the indices entered into the
1083  // buckets to preserve the order
1084  // within each component and during
1085  // this also remove duplicate
1086  // entries
1087  for (unsigned int block=0; block<fe_collection.n_blocks();
1088  ++block)
1089  {
1090  std::sort (block_to_dof_map[block].begin(),
1091  block_to_dof_map[block].end());
1092  block_to_dof_map[block]
1093  .erase (std::unique (block_to_dof_map[block].begin(),
1094  block_to_dof_map[block].end()),
1095  block_to_dof_map[block].end());
1096  }
1097 
1098  // calculate the number of locally owned
1099  // DoFs per bucket
1100  const unsigned int n_buckets = fe_collection.n_blocks();
1101  std::vector<types::global_dof_index> shifts(n_buckets);
1102 
1104  = (dynamic_cast<const parallel::Triangulation<dim,spacedim>*>
1105  (&start->get_dof_handler().get_triangulation())))
1106  {
1107 #ifdef DEAL_II_WITH_MPI
1108  std::vector<types::global_dof_index> local_dof_count(n_buckets);
1109 
1110  for (unsigned int c=0; c<n_buckets; ++c)
1111  local_dof_count[c] = block_to_dof_map[c].size();
1112 
1113 
1114  // gather information from all CPUs
1115  std::vector<types::global_dof_index>
1116  all_dof_counts(fe_collection.n_components() *
1117  Utilities::MPI::n_mpi_processes (tria->get_communicator()));
1118 
1119  const int ierr = MPI_Allgather ( local_dof_count.data(),
1120  n_buckets, DEAL_II_DOF_INDEX_MPI_TYPE,
1121  all_dof_counts.data(),
1122  n_buckets, DEAL_II_DOF_INDEX_MPI_TYPE,
1123  tria->get_communicator());
1124  AssertThrowMPI(ierr);
1125 
1126  for (unsigned int i=0; i<n_buckets; ++i)
1127  Assert (all_dof_counts[n_buckets*tria->locally_owned_subdomain()+i]
1128  ==
1129  local_dof_count[i],
1130  ExcInternalError());
1131 
1132  //calculate shifts
1133  types::global_dof_index cumulated = 0;
1134  for (unsigned int c=0; c<n_buckets; ++c)
1135  {
1136  shifts[c]=cumulated;
1137  for (types::subdomain_id i=0; i<tria->locally_owned_subdomain(); ++i)
1138  shifts[c] += all_dof_counts[c+n_buckets*i];
1139  for (unsigned int i=0; i<Utilities::MPI::n_mpi_processes (tria->get_communicator()); ++i)
1140  cumulated += all_dof_counts[c+n_buckets*i];
1141  }
1142 #else
1143  (void)tria;
1144  Assert (false, ExcInternalError());
1145 #endif
1146  }
1147  else
1148  {
1149  shifts[0] = 0;
1150  for (unsigned int c=1; c<fe_collection.n_blocks(); ++c)
1151  shifts[c] = shifts[c-1] + block_to_dof_map[c-1].size();
1152  }
1153 
1154 
1155 
1156 
1157  // now concatenate all the
1158  // components in the order the user
1159  // desired to see
1160  types::global_dof_index next_free_index = 0;
1161  for (unsigned int block=0; block<fe_collection.n_blocks(); ++block)
1162  {
1163  const typename std::vector<types::global_dof_index>::const_iterator
1164  begin_of_component = block_to_dof_map[block].begin(),
1165  end_of_component = block_to_dof_map[block].end();
1166 
1167  next_free_index = shifts[block];
1168 
1169  for (typename std::vector<types::global_dof_index>::const_iterator
1170  dof_index = begin_of_component;
1171  dof_index != end_of_component; ++dof_index)
1172  {
1173  Assert (start->get_dof_handler().locally_owned_dofs()
1174  .index_within_set(*dof_index)
1175  <
1176  new_indices.size(),
1177  ExcInternalError());
1178  new_indices[start->get_dof_handler().locally_owned_dofs()
1179  .index_within_set(*dof_index)]
1180  = next_free_index++;
1181  }
1182  }
1183 
1184  return next_free_index;
1185  }
1186 
1187 
1188 
1189  namespace
1190  {
1191  // Helper function for DoFRenumbering::hierarchical(). this function recurses into
1192  // the given cell or, if that should be an active (terminal) cell, renumbers DoF
1193  // indices on it. The function starts renumbering with 'next_free_dof_index' and
1194  // returns the first still unused DoF index at the end of its operation.
1195  template <int dim, class CellIteratorType>
1197  compute_hierarchical_recursive (const types::global_dof_index next_free_dof_offset,
1198  const types::global_dof_index my_starting_index,
1199  const CellIteratorType &cell,
1200  const IndexSet &locally_owned_dof_indices,
1201  std::vector<types::global_dof_index> &new_indices)
1202  {
1203  types::global_dof_index current_next_free_dof_offset = next_free_dof_offset;
1204 
1205  if (cell->has_children())
1206  {
1207  // recursion
1208  for (unsigned int c = 0; c < GeometryInfo<dim>::max_children_per_cell; ++c)
1209  current_next_free_dof_offset
1210  = compute_hierarchical_recursive<dim> (current_next_free_dof_offset,
1211  my_starting_index,
1212  cell->child (c),
1213  locally_owned_dof_indices,
1214  new_indices);
1215  }
1216  else
1217  {
1218  // this is a terminal cell. we need to renumber its DoF indices. there
1219  // are now three cases to decide:
1220  // - this is a sequential triangulation: we can just go ahead and number
1221  // the DoFs in the order in which we encounter cells. in this case,
1222  // all cells are actually locally owned
1223  // - if this is a parallel::distributed::Triangulation, then we only
1224  // need to work on the locally owned cells since they contain
1225  // all locally owned DoFs.
1226  // - if this is a parallel::shared::Triangulation, then the same applies
1227  //
1228  // in all cases, each processor starts new indices so that we get
1229  // a consecutive numbering on each processor, and disjoint ownership
1230  // of the global range of DoF indices
1231  if (cell->is_locally_owned())
1232  {
1233  // first get the existing DoF indices
1234  const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
1235  std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
1236  cell->get_dof_indices (local_dof_indices);
1237 
1238  // then loop over the existing DoF indices on this cell
1239  // and see whether it has already been re-numbered (it
1240  // may have been on a face or vertex to a neighboring
1241  // cell that we have encountered before). if not,
1242  // give it a new number and store that number in the
1243  // output array (new_indices)
1244  //
1245  // if this is a parallel triangulation and a DoF index is
1246  // not locally owned, then don't touch it. since
1247  // we don't actually *change* DoF indices (just record new
1248  // numbers in an array), we don't need to worry about
1249  // the decision whether a DoF is locally owned or not changing
1250  // as we progress in renumbering DoFs -- all adjacent cells
1251  // will always agree that a DoF is locally owned or not.
1252  // that said, the first cell to encounter a locally owned DoF
1253  // gets to number it, so the order in which we traverse cells
1254  // matters
1255  for (unsigned int i = 0; i < dofs_per_cell; ++i)
1256  if (locally_owned_dof_indices.is_element (local_dof_indices[i]))
1257  {
1258  // this is a locally owned DoF, assign new number if not assigned a number yet
1259  const unsigned int idx = locally_owned_dof_indices.index_within_set (local_dof_indices[i]);
1260  if (new_indices[idx] == numbers::invalid_dof_index)
1261  {
1262  new_indices[idx] = my_starting_index + current_next_free_dof_offset;
1263  ++current_next_free_dof_offset;
1264  }
1265  }
1266  }
1267  }
1268 
1269  return current_next_free_dof_offset;
1270  }
1271  }
1272 
1273 
1274 
1275  template <int dim>
1276  void
1278  {
1279  std::vector<types::global_dof_index> renumbering (dof_handler.n_locally_owned_dofs(),
1281 
1282  types::global_dof_index next_free_dof_offset = 0;
1283  const IndexSet locally_owned = dof_handler.locally_owned_dofs();
1284 
1285  // in the function we call recursively, we want to number DoFs so
1286  // that global cell zero starts with DoF zero, regardless of how
1287  // DoFs were previously numbered. to this end, we need to figure
1288  // out which DoF index the current processor should start with.
1289  //
1290  // if this is a sequential triangulation, then obviously the starting
1291  // index is zero. otherwise, make sure we get contiguous, successive
1292  // ranges on each processor. note that since the number of locally owned
1293  // DoFs is an invariant under renumbering, we can easily compute this
1294  // starting index by just accumulating over the number of locally owned
1295  // DoFs for all previous processes
1296  types::global_dof_index my_starting_index = 0;
1297 
1298  if (const parallel::Triangulation<dim> *tria
1299  = dynamic_cast<const parallel::Triangulation<dim>*>
1300  (&dof_handler.get_triangulation()))
1301  {
1302  const std::vector<types::global_dof_index> &
1303  n_locally_owned_dofs_per_processor = dof_handler.n_locally_owned_dofs_per_processor();
1304  my_starting_index = std::accumulate (n_locally_owned_dofs_per_processor.begin(),
1305  n_locally_owned_dofs_per_processor.begin()
1306  + tria->locally_owned_subdomain(),
1308  }
1309 
1311  = dynamic_cast<const parallel::distributed::Triangulation<dim>*>
1312  (&dof_handler.get_triangulation()))
1313  {
1314 #ifdef DEAL_II_WITH_P4EST
1315  // this is a distributed Triangulation. we need to traverse the coarse
1316  // cells in the order p4est does to match the z-order actually used
1317  // by p4est. this requires using the renumbering of coarse cells
1318  // we do before we hand things off to p4est
1319  for (unsigned int c = 0; c < tria->n_cells (0); ++c)
1320  {
1321  const unsigned int coarse_cell_index =
1322  tria->get_p4est_tree_to_coarse_cell_permutation() [c];
1323 
1325  this_cell (tria, 0, coarse_cell_index, &dof_handler);
1326 
1327  next_free_dof_offset = compute_hierarchical_recursive<dim> (next_free_dof_offset,
1328  my_starting_index,
1329  this_cell,
1330  locally_owned,
1331  renumbering);
1332  }
1333 #else
1334  Assert (false, ExcNotImplemented());
1335 #endif
1336  }
1337  else
1338  {
1339  // this is not a distributed Triangulation, so we can traverse coarse
1340  // cells in the normal order
1341  for (typename DoFHandler<dim>::cell_iterator cell = dof_handler.begin (0);
1342  cell != dof_handler.end (0); ++cell)
1343  next_free_dof_offset = compute_hierarchical_recursive<dim> (next_free_dof_offset,
1344  my_starting_index,
1345  cell,
1346  locally_owned,
1347  renumbering);
1348  }
1349 
1350  // verify that the last numbered degree of freedom is either
1351  // equal to the number of degrees of freedom in total (the
1352  // sequential case) or in the distributed case at least
1353  // makes sense
1354  Assert ((next_free_dof_offset == dof_handler.n_locally_owned_dofs())
1355  ||
1356  ((dof_handler.n_locally_owned_dofs() < dof_handler.n_dofs())
1357  &&
1358  (next_free_dof_offset <= dof_handler.n_dofs())),
1359  ExcInternalError());
1360 
1361  // make sure that all local DoFs got new numbers assigned
1362  Assert (std::find (renumbering.begin(), renumbering.end(),
1364  == renumbering.end(),
1365  ExcInternalError());
1366 
1367  dof_handler.renumber_dofs(renumbering);
1368  }
1369 
1370 
1371 
1372  template <typename DoFHandlerType>
1373  void
1374  sort_selected_dofs_back (DoFHandlerType &dof_handler,
1375  const std::vector<bool> &selected_dofs)
1376  {
1377  std::vector<types::global_dof_index> renumbering(dof_handler.n_dofs(),
1379  compute_sort_selected_dofs_back(renumbering, dof_handler, selected_dofs);
1380 
1381  dof_handler.renumber_dofs(renumbering);
1382  }
1383 
1384 
1385 
1386  template <typename DoFHandlerType>
1387  void
1388  sort_selected_dofs_back (DoFHandlerType &dof_handler,
1389  const std::vector<bool> &selected_dofs,
1390  const unsigned int level)
1391  {
1392  Assert(dof_handler.n_dofs(level) != numbers::invalid_dof_index,
1394 
1395  std::vector<types::global_dof_index> renumbering(dof_handler.n_dofs(level),
1397  compute_sort_selected_dofs_back(renumbering, dof_handler, selected_dofs, level);
1398 
1399  dof_handler.renumber_dofs(level, renumbering);
1400  }
1401 
1402 
1403 
1404  template <typename DoFHandlerType>
1405  void
1406  compute_sort_selected_dofs_back (std::vector<types::global_dof_index> &new_indices,
1407  const DoFHandlerType &dof_handler,
1408  const std::vector<bool> &selected_dofs)
1409  {
1410  const types::global_dof_index n_dofs = dof_handler.n_dofs();
1411  Assert (selected_dofs.size() == n_dofs,
1412  ExcDimensionMismatch (selected_dofs.size(), n_dofs));
1413 
1414  // re-sort the dofs according to
1415  // their selection state
1416  Assert (new_indices.size() == n_dofs,
1417  ExcDimensionMismatch(new_indices.size(), n_dofs));
1418 
1419  const types::global_dof_index n_selected_dofs = std::count (selected_dofs.begin(),
1420  selected_dofs.end(),
1421  false);
1422 
1423  types::global_dof_index next_unselected = 0;
1424  types::global_dof_index next_selected = n_selected_dofs;
1425  for (types::global_dof_index i=0; i<n_dofs; ++i)
1426  if (selected_dofs[i] == false)
1427  {
1428  new_indices[i] = next_unselected;
1429  ++next_unselected;
1430  }
1431  else
1432  {
1433  new_indices[i] = next_selected;
1434  ++next_selected;
1435  };
1436  Assert (next_unselected == n_selected_dofs, ExcInternalError());
1437  Assert (next_selected == n_dofs, ExcInternalError());
1438  }
1439 
1440 
1441 
1442  template <typename DoFHandlerType>
1443  void
1444  compute_sort_selected_dofs_back (std::vector<types::global_dof_index> &new_indices,
1445  const DoFHandlerType &dof_handler,
1446  const std::vector<bool> &selected_dofs,
1447  const unsigned int level)
1448  {
1449  Assert(dof_handler.n_dofs(level) != numbers::invalid_dof_index,
1451 
1452  const unsigned int n_dofs = dof_handler.n_dofs(level);
1453  Assert (selected_dofs.size() == n_dofs,
1454  ExcDimensionMismatch (selected_dofs.size(), n_dofs));
1455 
1456  // re-sort the dofs according to
1457  // their selection state
1458  Assert (new_indices.size() == n_dofs,
1459  ExcDimensionMismatch(new_indices.size(), n_dofs));
1460 
1461  const unsigned int n_selected_dofs = std::count (selected_dofs.begin(),
1462  selected_dofs.end(),
1463  false);
1464 
1465  unsigned int next_unselected = 0;
1466  unsigned int next_selected = n_selected_dofs;
1467  for (unsigned int i=0; i<n_dofs; ++i)
1468  if (selected_dofs[i] == false)
1469  {
1470  new_indices[i] = next_unselected;
1471  ++next_unselected;
1472  }
1473  else
1474  {
1475  new_indices[i] = next_selected;
1476  ++next_selected;
1477  };
1478  Assert (next_unselected == n_selected_dofs, ExcInternalError());
1479  Assert (next_selected == n_dofs, ExcInternalError());
1480  }
1481 
1482 
1483 
1484  template <typename DoFHandlerType>
1485  void
1486  cell_wise (DoFHandlerType &dof,
1487  const std::vector<typename DoFHandlerType::active_cell_iterator> &cells)
1488  {
1489  std::vector<types::global_dof_index> renumbering(dof.n_dofs());
1490  std::vector<types::global_dof_index> reverse(dof.n_dofs());
1491  compute_cell_wise(renumbering, reverse, dof, cells);
1492 
1493  dof.renumber_dofs(renumbering);
1494  }
1495 
1496 
1497  template <typename DoFHandlerType>
1498  void
1500  (std::vector<types::global_dof_index> &new_indices,
1501  std::vector<types::global_dof_index> &reverse,
1502  const DoFHandlerType &dof,
1503  const typename std::vector<typename DoFHandlerType::active_cell_iterator> &cells)
1504  {
1505  Assert(cells.size() == dof.get_triangulation().n_active_cells(),
1506  ExcDimensionMismatch(cells.size(),
1507  dof.get_triangulation().n_active_cells()));
1508 
1509  types::global_dof_index n_global_dofs = dof.n_dofs();
1510 
1511  // Actually, we compute the
1512  // inverse of the reordering
1513  // vector, called reverse here.
1514  // Later, irs inverse is computed
1515  // into new_indices, which is the
1516  // return argument.
1517 
1518  Assert(new_indices.size() == n_global_dofs,
1519  ExcDimensionMismatch(new_indices.size(), n_global_dofs));
1520  Assert(reverse.size() == n_global_dofs,
1521  ExcDimensionMismatch(reverse.size(), n_global_dofs));
1522 
1523  // For continuous elements, we must
1524  // make sure, that each dof is
1525  // reordered only once.
1526  std::vector<bool> already_sorted(n_global_dofs, false);
1527  std::vector<types::global_dof_index> cell_dofs;
1528 
1529  unsigned int global_index = 0;
1530 
1531  typename std::vector<typename DoFHandlerType::active_cell_iterator>::const_iterator cell;
1532 
1533  for (cell = cells.begin(); cell != cells.end(); ++cell)
1534  {
1535  // Determine the number of dofs
1536  // on this cell and reinit the
1537  // vector storing these
1538  // numbers.
1539  unsigned int n_cell_dofs = (*cell)->get_fe().n_dofs_per_cell();
1540  cell_dofs.resize(n_cell_dofs);
1541 
1542  (*cell)->get_active_or_mg_dof_indices(cell_dofs);
1543 
1544  // Sort here to make sure that
1545  // degrees of freedom inside a
1546  // single cell are in the same
1547  // order after renumbering.
1548  std::sort(cell_dofs.begin(), cell_dofs.end());
1549 
1550  for (unsigned int i=0; i<n_cell_dofs; ++i)
1551  {
1552  if (!already_sorted[cell_dofs[i]])
1553  {
1554  already_sorted[cell_dofs[i]] = true;
1555  reverse[global_index++] = cell_dofs[i];
1556  }
1557  }
1558  }
1559  Assert(global_index == n_global_dofs,
1560  ExcMessage("Traversing over the given set of cells did not cover all "
1561  "degrees of freedom in the DoFHandler. Does the set of cells "
1562  "not include all active cells?"));
1563 
1564  for (types::global_dof_index i=0; i<reverse.size(); ++i)
1565  new_indices[reverse[i]] = i;
1566  }
1567 
1568 
1569 
1570  template <typename DoFHandlerType>
1571  void cell_wise
1572  (DoFHandlerType &dof,
1573  const unsigned int level,
1574  const typename std::vector<typename DoFHandlerType::level_cell_iterator> &cells)
1575  {
1576  Assert(dof.n_dofs(level) != numbers::invalid_dof_index,
1578 
1579  std::vector<types::global_dof_index> renumbering(dof.n_dofs(level));
1580  std::vector<types::global_dof_index> reverse(dof.n_dofs(level));
1581 
1582  compute_cell_wise(renumbering, reverse, dof, level, cells);
1583  dof.renumber_dofs(level, renumbering);
1584  }
1585 
1586 
1587 
1588  template <typename DoFHandlerType>
1589  void compute_cell_wise
1590  (std::vector<types::global_dof_index> &new_order,
1591  std::vector<types::global_dof_index> &reverse,
1592  const DoFHandlerType &dof,
1593  const unsigned int level,
1594  const typename std::vector<typename DoFHandlerType::level_cell_iterator> &cells)
1595  {
1596  Assert(cells.size() == dof.get_triangulation().n_cells(level),
1597  ExcDimensionMismatch(cells.size(),
1598  dof.get_triangulation().n_cells(level)));
1599  Assert (new_order.size() == dof.n_dofs(level),
1600  ExcDimensionMismatch(new_order.size(), dof.n_dofs(level)));
1601  Assert (reverse.size() == dof.n_dofs(level),
1602  ExcDimensionMismatch(reverse.size(), dof.n_dofs(level)));
1603 
1604  unsigned int n_global_dofs = dof.n_dofs(level);
1605  unsigned int n_cell_dofs = dof.get_fe().n_dofs_per_cell();
1606 
1607  std::vector<bool> already_sorted(n_global_dofs, false);
1608  std::vector<types::global_dof_index> cell_dofs(n_cell_dofs);
1609 
1610  unsigned int global_index = 0;
1611 
1612  typename std::vector<typename DoFHandlerType::level_cell_iterator>::const_iterator cell;
1613 
1614  for (cell = cells.begin(); cell != cells.end(); ++cell)
1615  {
1616  Assert ((*cell)->level() == (int) level, ExcInternalError());
1617 
1618  (*cell)->get_active_or_mg_dof_indices(cell_dofs);
1619  std::sort(cell_dofs.begin(), cell_dofs.end());
1620 
1621  for (unsigned int i=0; i<n_cell_dofs; ++i)
1622  {
1623  if (!already_sorted[cell_dofs[i]])
1624  {
1625  already_sorted[cell_dofs[i]] = true;
1626  reverse[global_index++] = cell_dofs[i];
1627  }
1628  }
1629  }
1630  Assert(global_index == n_global_dofs,
1631  ExcMessage("Traversing over the given set of cells did not cover all "
1632  "degrees of freedom in the DoFHandler. Does the set of cells "
1633  "not include all cells of the specified level?"));
1634 
1635  for (types::global_dof_index i=0; i<new_order.size(); ++i)
1636  new_order[reverse[i]] = i;
1637  }
1638 
1639 
1640 
1641  template <typename DoFHandlerType>
1642  void
1643  downstream (DoFHandlerType &dof,
1645  const bool dof_wise_renumbering)
1646  {
1647  std::vector<types::global_dof_index> renumbering(dof.n_dofs());
1648  std::vector<types::global_dof_index> reverse(dof.n_dofs());
1649  compute_downstream(renumbering, reverse, dof, direction,
1650  dof_wise_renumbering);
1651 
1652  dof.renumber_dofs(renumbering);
1653  }
1654 
1655 
1656 
1657  template <typename DoFHandlerType>
1658  void
1660  (std::vector<types::global_dof_index> &new_indices,
1661  std::vector<types::global_dof_index> &reverse,
1662  const DoFHandlerType &dof,
1664  const bool dof_wise_renumbering)
1665  {
1667  (&dof.get_triangulation())
1668  == nullptr),
1669  ExcNotImplemented());
1670 
1671  if (dof_wise_renumbering == false)
1672  {
1673  std::vector<typename DoFHandlerType::active_cell_iterator> ordered_cells;
1674  ordered_cells.reserve(dof.get_triangulation().n_active_cells());
1675  const CompareDownstream<typename DoFHandlerType::active_cell_iterator,
1676  DoFHandlerType::space_dimension> comparator(direction);
1677 
1678  typename DoFHandlerType::active_cell_iterator p = dof.begin_active();
1679  typename DoFHandlerType::active_cell_iterator end = dof.end();
1680 
1681  while (p!=end)
1682  {
1683  ordered_cells.push_back(p);
1684  ++p;
1685  }
1686  std::sort (ordered_cells.begin(), ordered_cells.end(), comparator);
1687 
1688  compute_cell_wise(new_indices, reverse, dof, ordered_cells);
1689  }
1690  else
1691  {
1692  // similar code as for
1693  // DoFTools::map_dofs_to_support_points, but
1694  // need to do this for general DoFHandlerType classes and
1695  // want to be able to sort the result
1696  // (otherwise, could use something like
1697  // DoFTools::map_support_points_to_dofs)
1698  const unsigned int n_dofs = dof.n_dofs();
1699  std::vector<std::pair<Point<DoFHandlerType::space_dimension>,unsigned int> > support_point_list
1700  (n_dofs);
1701 
1702  const hp::FECollection<DoFHandlerType::dimension> &fe_collection = dof.get_fe_collection();
1703  Assert (fe_collection[0].has_support_points(),
1705  hp::QCollection<DoFHandlerType::dimension> quadrature_collection;
1706  for (unsigned int comp=0; comp<fe_collection.size(); ++comp)
1707  {
1708  Assert (fe_collection[comp].has_support_points(),
1710  quadrature_collection.push_back
1711  (Quadrature<DoFHandlerType::dimension> (fe_collection[comp].
1712  get_unit_support_points()));
1713  }
1715  hp_fe_values (fe_collection, quadrature_collection,
1717 
1718  std::vector<bool> already_touched (n_dofs, false);
1719 
1720  std::vector<types::global_dof_index> local_dof_indices;
1721  typename DoFHandlerType::active_cell_iterator begin = dof.begin_active();
1722  typename DoFHandlerType::active_cell_iterator end = dof.end();
1723  for ( ; begin != end; ++begin)
1724  {
1725  const unsigned int dofs_per_cell = begin->get_fe().dofs_per_cell;
1726  local_dof_indices.resize (dofs_per_cell);
1727  hp_fe_values.reinit (begin);
1728  const FEValues<DoFHandlerType::dimension> &fe_values =
1729  hp_fe_values.get_present_fe_values ();
1730  begin->get_active_or_mg_dof_indices(local_dof_indices);
1731  const std::vector<Point<DoFHandlerType::space_dimension> > &points
1732  = fe_values.get_quadrature_points ();
1733  for (unsigned int i=0; i<dofs_per_cell; ++i)
1734  if (!already_touched[local_dof_indices[i]])
1735  {
1736  support_point_list[local_dof_indices[i]].first = points[i];
1737  support_point_list[local_dof_indices[i]].second =
1738  local_dof_indices[i];
1739  already_touched[local_dof_indices[i]] = true;
1740  }
1741  }
1742 
1744  std::sort (support_point_list.begin(), support_point_list.end(),
1745  comparator);
1746  for (types::global_dof_index i=0; i<n_dofs; ++i)
1747  new_indices[support_point_list[i].second] = i;
1748  }
1749  }
1750 
1751 
1752 
1753  template <typename DoFHandlerType>
1754  void downstream (DoFHandlerType &dof,
1755  const unsigned int level,
1757  const bool dof_wise_renumbering)
1758  {
1759  std::vector<types::global_dof_index> renumbering(dof.n_dofs(level));
1760  std::vector<types::global_dof_index> reverse(dof.n_dofs(level));
1761  compute_downstream(renumbering, reverse, dof, level, direction,
1762  dof_wise_renumbering);
1763 
1764  dof.renumber_dofs(level, renumbering);
1765  }
1766 
1767 
1768 
1769  template <typename DoFHandlerType>
1770  void
1772  (std::vector<types::global_dof_index> &new_indices,
1773  std::vector<types::global_dof_index> &reverse,
1774  const DoFHandlerType &dof,
1775  const unsigned int level,
1777  const bool dof_wise_renumbering)
1778  {
1779  if (dof_wise_renumbering == false)
1780  {
1781  std::vector<typename DoFHandlerType::level_cell_iterator> ordered_cells;
1782  ordered_cells.reserve (dof.get_triangulation().n_cells(level));
1783  const CompareDownstream<typename DoFHandlerType::level_cell_iterator,
1784  DoFHandlerType::space_dimension> comparator(direction);
1785 
1786  typename DoFHandlerType::level_cell_iterator p = dof.begin(level);
1787  typename DoFHandlerType::level_cell_iterator end = dof.end(level);
1788 
1789  while (p!=end)
1790  {
1791  ordered_cells.push_back(p);
1792  ++p;
1793  }
1794  std::sort (ordered_cells.begin(), ordered_cells.end(), comparator);
1795 
1796  compute_cell_wise(new_indices, reverse, dof, level, ordered_cells);
1797  }
1798  else
1799  {
1800  Assert (dof.get_fe().has_support_points(),
1802  const unsigned int n_dofs = dof.n_dofs(level);
1803  std::vector<std::pair<Point<DoFHandlerType::space_dimension>,unsigned int> > support_point_list
1804  (n_dofs);
1805 
1806  Quadrature<DoFHandlerType::dimension> q_dummy(dof.get_fe().get_unit_support_points());
1809 
1810  std::vector<bool> already_touched (dof.n_dofs(), false);
1811 
1812  const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
1813  std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
1814  typename DoFHandlerType::level_cell_iterator begin = dof.begin(level);
1815  typename DoFHandlerType::level_cell_iterator end = dof.end(level);
1816  for ( ; begin != end; ++begin)
1817  {
1818  const typename Triangulation<DoFHandlerType::dimension,
1819  DoFHandlerType::space_dimension>::cell_iterator &begin_tria = begin;
1820  begin->get_active_or_mg_dof_indices(local_dof_indices);
1821  fe_values.reinit (begin_tria);
1822  const std::vector<Point<DoFHandlerType::space_dimension> > &points
1823  = fe_values.get_quadrature_points ();
1824  for (unsigned int i=0; i<dofs_per_cell; ++i)
1825  if (!already_touched[local_dof_indices[i]])
1826  {
1827  support_point_list[local_dof_indices[i]].first = points[i];
1828  support_point_list[local_dof_indices[i]].second =
1829  local_dof_indices[i];
1830  already_touched[local_dof_indices[i]] = true;
1831  }
1832  }
1833 
1835  std::sort (support_point_list.begin(), support_point_list.end(),
1836  comparator);
1837  for (types::global_dof_index i=0; i<n_dofs; ++i)
1838  new_indices[support_point_list[i].second] = i;
1839  }
1840  }
1841 
1842 
1843 
1847  namespace internal
1848  {
1849  template <int dim>
1850  struct ClockCells
1851  {
1855  const Point<dim> &center;
1859  bool counter;
1860 
1864  ClockCells (const Point<dim> &center, bool counter) :
1865  center(center),
1866  counter(counter)
1867  {}
1868 
1872  template <class DHCellIterator>
1873  bool operator () (const DHCellIterator &c1,
1874  const DHCellIterator &c2) const
1875  {
1876  // dispatch to
1877  // dimension-dependent functions
1878  return compare (c1, c2, std::integral_constant<int, dim>());
1879  }
1880 
1881  private:
1885  template <class DHCellIterator, int xdim>
1886  bool compare (const DHCellIterator &c1,
1887  const DHCellIterator &c2,
1888  std::integral_constant<int, xdim>) const
1889  {
1890  const Tensor<1,dim> v1 = c1->center() - center;
1891  const Tensor<1,dim> v2 = c2->center() - center;
1892  const double s1 = std::atan2(v1[0], v1[1]);
1893  const double s2 = std::atan2(v2[0], v2[1]);
1894  return ( counter ? (s1>s2) : (s2>s1));
1895  }
1896 
1897 
1902  template <class DHCellIterator>
1903  bool compare (const DHCellIterator &,
1904  const DHCellIterator &,
1905  std::integral_constant<int, 1>) const
1906  {
1907  Assert (dim >= 2,
1908  ExcMessage ("This operation only makes sense for dim>=2."));
1909  return false;
1910  }
1911 
1912  };
1913  }
1914 
1915 
1916 
1917  template <typename DoFHandlerType>
1918  void
1920  DoFHandlerType &dof,
1922  const bool counter)
1923  {
1924  std::vector<types::global_dof_index> renumbering(dof.n_dofs());
1925  compute_clockwise_dg(renumbering, dof, center, counter);
1926 
1927  dof.renumber_dofs(renumbering);
1928  }
1929 
1930 
1931 
1932  template <typename DoFHandlerType>
1933  void
1935  (std::vector<types::global_dof_index> &new_indices,
1936  const DoFHandlerType &dof,
1938  const bool counter)
1939  {
1940  std::vector<typename DoFHandlerType::active_cell_iterator> ordered_cells;
1941  ordered_cells.reserve (dof.get_triangulation().n_active_cells());
1942  internal::ClockCells<DoFHandlerType::space_dimension> comparator(center, counter);
1943 
1944  typename DoFHandlerType::active_cell_iterator p = dof.begin_active();
1945  typename DoFHandlerType::active_cell_iterator end = dof.end();
1946 
1947  while (p!=end)
1948  {
1949  ordered_cells.push_back(p);
1950  ++p;
1951  }
1952  std::sort (ordered_cells.begin(), ordered_cells.end(), comparator);
1953 
1954  std::vector<types::global_dof_index> reverse(new_indices.size());
1955  compute_cell_wise(new_indices, reverse, dof, ordered_cells);
1956  }
1957 
1958 
1959 
1960  template <typename DoFHandlerType>
1961  void clockwise_dg (DoFHandlerType &dof,
1962  const unsigned int level,
1964  const bool counter)
1965  {
1966  std::vector<typename DoFHandlerType::level_cell_iterator> ordered_cells;
1967  ordered_cells.reserve(dof.get_triangulation().n_active_cells());
1968  internal::ClockCells<DoFHandlerType::space_dimension> comparator(center, counter);
1969 
1970  typename DoFHandlerType::level_cell_iterator p = dof.begin(level);
1971  typename DoFHandlerType::level_cell_iterator end = dof.end(level);
1972 
1973  while (p!=end)
1974  {
1975  ordered_cells.push_back(p);
1976  ++p;
1977  }
1978  std::sort (ordered_cells.begin(), ordered_cells.end(), comparator);
1979 
1980  cell_wise(dof, level, ordered_cells);
1981  }
1982 
1983 
1984 
1985  template <typename DoFHandlerType>
1986  void
1987  random (DoFHandlerType &dof_handler)
1988  {
1989  std::vector<types::global_dof_index> renumbering(dof_handler.n_dofs(),
1991  compute_random(renumbering, dof_handler);
1992 
1993  dof_handler.renumber_dofs(renumbering);
1994  }
1995 
1996 
1997 
1998  template <typename DoFHandlerType>
1999  void
2001  std::vector<types::global_dof_index> &new_indices,
2002  const DoFHandlerType &dof_handler)
2003  {
2004  const types::global_dof_index n_dofs = dof_handler.n_dofs();
2005  Assert(new_indices.size() == n_dofs,
2006  ExcDimensionMismatch(new_indices.size(), n_dofs));
2007 
2008  for (unsigned int i=0; i<n_dofs; ++i)
2009  new_indices[i] = i;
2010 
2011  // shuffle the elements; the following is essentially std::shuffle (which
2012  // is new in C++11) but with a boost URNG
2013  ::boost::mt19937 random_number_generator;
2014  for (unsigned int i=1; i<n_dofs; ++i)
2015  {
2016  // get a random number between 0 and i (inclusive)
2017  const unsigned int j
2018  = ::boost::random::uniform_int_distribution<>(0, i)(random_number_generator);
2019 
2020  // if possible, swap the elements
2021  if (i != j)
2022  std::swap (new_indices[i], new_indices[j]);
2023  }
2024  }
2025 
2026 
2027 
2028  template <typename DoFHandlerType>
2029  void
2030  subdomain_wise (DoFHandlerType &dof_handler)
2031  {
2032  Assert((!dynamic_cast<const parallel::Triangulation<DoFHandlerType::dimension,DoFHandlerType::space_dimension>*> (&dof_handler.get_triangulation())),
2033  ExcMessage("Parallel triangulations are already enumerated according to their MPI process id."));
2034 
2035  std::vector<types::global_dof_index> renumbering(dof_handler.n_dofs(),
2037  compute_subdomain_wise(renumbering, dof_handler);
2038 
2039  dof_handler.renumber_dofs(renumbering);
2040  }
2041 
2042 
2043 
2044  template <typename DoFHandlerType>
2045  void
2046  compute_subdomain_wise (std::vector<types::global_dof_index> &new_dof_indices,
2047  const DoFHandlerType &dof_handler)
2048  {
2049  const types::global_dof_index n_dofs = dof_handler.n_dofs();
2050  Assert (new_dof_indices.size() == n_dofs,
2051  ExcDimensionMismatch (new_dof_indices.size(), n_dofs));
2052 
2053  // first get the association of each dof
2054  // with a subdomain and determine the total
2055  // number of subdomain ids used
2056  std::vector<types::subdomain_id> subdomain_association (n_dofs);
2058  subdomain_association);
2059  const unsigned int n_subdomains
2060  = *std::max_element (subdomain_association.begin(),
2061  subdomain_association.end()) + 1;
2062 
2063  // then renumber the subdomains by first
2064  // looking at those belonging to subdomain
2065  // 0, then those of subdomain 1, etc. note
2066  // that the algorithm is stable, i.e. if
2067  // two dofs i,j have i<j and belong to the
2068  // same subdomain, then they will be in
2069  // this order also after reordering
2070  std::fill (new_dof_indices.begin(), new_dof_indices.end(),
2072  types::global_dof_index next_free_index = 0;
2073  for (types::subdomain_id subdomain=0; subdomain<n_subdomains; ++subdomain)
2074  for (types::global_dof_index i=0; i<n_dofs; ++i)
2075  if (subdomain_association[i] == subdomain)
2076  {
2077  Assert (new_dof_indices[i] == numbers::invalid_dof_index,
2078  ExcInternalError());
2079  new_dof_indices[i] = next_free_index;
2080  ++next_free_index;
2081  }
2082 
2083  // we should have numbered all dofs
2084  Assert (next_free_index == n_dofs, ExcInternalError());
2085  Assert (std::find (new_dof_indices.begin(), new_dof_indices.end(),
2087  == new_dof_indices.end(),
2088  ExcInternalError());
2089  }
2090 
2091 } // namespace DoFRenumbering
2092 
2093 
2094 
2095 /*-------------- Explicit Instantiations -------------------------------*/
2096 #include "dof_renumbering.inst"
2097 
2098 
2099 DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcFEHasNoSupportPoints()
void compute_downstream(std::vector< types::global_dof_index > &new_dof_indices, std::vector< types::global_dof_index > &reverse, const DoFHandlerType &dof_handler, const Tensor< 1, DoFHandlerType::space_dimension > &direction, const bool dof_wise_renumbering)
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1248
void downstream(DoFHandlerType &dof_handler, const Tensor< 1, DoFHandlerType::space_dimension > &direction, const bool dof_wise_renumbering=false)
cell_iterator begin(const unsigned int level=0) const
Definition: dof_handler.cc:723
void minimum_degree(DoFHandlerType &dof_handler, const bool reversed_numbering=false, const bool use_constraints=false)
void renumber_dofs(const std::vector< types::global_dof_index > &new_numbers)
void compute_cell_wise(std::vector< types::global_dof_index > &renumbering, std::vector< types::global_dof_index > &inverse_renumbering, const DoFHandlerType &dof_handler, const std::vector< typename DoFHandlerType::active_cell_iterator > &cell_order)
size_type nth_index_in_set(const unsigned int local_index) const
Definition: index_set.h:1769
void compute_king_ordering(std::vector< types::global_dof_index > &new_dof_indices, const DoFHandlerType &, const bool reversed_numbering=false, const bool use_constraints=false)
void sort_selected_dofs_back(DoFHandlerType &dof_handler, const std::vector< bool > &selected_dofs)
void get_subdomain_association(const DoFHandlerType &dof_handler, std::vector< types::subdomain_id > &subdomain)
Definition: dof_tools.cc:1430
void hierarchical(DoFHandler< dim > &dof_handler)
cell_iterator end() const
Definition: dof_handler.cc:751
void make_sparsity_pattern(const DoFHandlerType &dof_handler, SparsityPatternType &sparsity, const unsigned int level)
Definition: mg_tools.cc:540
void reorder_Cuthill_McKee(const DynamicSparsityPattern &sparsity, std::vector< DynamicSparsityPattern::size_type > &new_indices, const std::vector< DynamicSparsityPattern::size_type > &starting_indices=std::vector< DynamicSparsityPattern::size_type >())
active_cell_iterator begin_active(const unsigned int level=0) const
const FiniteElement< dim, spacedim > & get_fe() const
void component_wise(DoFHandlerType &dof_handler, const std::vector< unsigned int > &target_component=std::vector< unsigned int >())
ActiveSelector::active_cell_iterator active_cell_iterator
Definition: dof_handler.h:229
STL namespace.
unsigned int size() const
Transformed quadrature points.
types::global_dof_index compute_component_wise(std::vector< types::global_dof_index > &new_dof_indices, const CellIterator &start, const typename identity< CellIterator >::type &end, const std::vector< unsigned int > &target_component, const bool is_level_operation)
bool is_primitive() const
Definition: fe.h:3228
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:107
static ::ExceptionBase & ExcDoFHandlerNotInitialized()
ActiveSelector::active_cell_iterator active_cell_iterator
Definition: dof_handler.h:186
const ::FEValues< dim, spacedim > & get_present_fe_values() const
Definition: fe_values.h:598
size_type size() const
Definition: index_set.h:1575
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: dof_handler.cc:735
const std::vector< Point< spacedim > > & get_quadrature_points() const
unsigned int n_locally_owned_dofs() const
void reinit(const TriaIterator< DoFCellAccessor< DoFHandlerType, lda > > cell, const unsigned int q_index=numbers::invalid_unsigned_int, const unsigned int mapping_index=numbers::invalid_unsigned_int, const unsigned int fe_index=numbers::invalid_unsigned_int)
Definition: fe_values.cc:144
void make_hanging_node_constraints(const DoFHandlerType &dof_handler, ConstraintMatrix &constraints)
void random(DoFHandlerType &dof_handler)
const std::vector< types::global_dof_index > & n_locally_owned_dofs_per_processor() const
static ::ExceptionBase & ExcMessage(std::string arg1)
void compute_minimum_degree(std::vector< types::global_dof_index > &new_dof_indices, const DoFHandlerType &, const bool reversed_numbering=false, const bool use_constraints=false)
void Cuthill_McKee(DoFHandlerType &dof_handler, const bool reversed_numbering=false, const bool use_constraints=false)
unsigned int global_dof_index
Definition: types.h:88
void subtract_set(const IndexSet &other)
Definition: index_set.cc:288
#define Assert(cond, exc)
Definition: exceptions.h:1142
void compute_subdomain_wise(std::vector< types::global_dof_index > &new_dof_indices, const DoFHandlerType &dof_handler)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
size_type index_within_set(const size_type global_index) const
Definition: index_set.h:1811
const ComponentMask & get_nonzero_components(const unsigned int i) const
Definition: fe.h:3206
types::global_dof_index n_dofs() const
void extract_locally_relevant_dofs(const DoFHandlerType &dof_handler, IndexSet &dof_set)
Definition: dof_tools.cc:1087
void compute_random(std::vector< types::global_dof_index > &new_dof_indices, const DoFHandlerType &dof_handler)
unsigned int subdomain_id
Definition: types.h:42
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
Definition: mpi.cc:65
void compute_sort_selected_dofs_back(std::vector< types::global_dof_index > &new_dof_indices, const DoFHandlerType &dof_handler, const std::vector< bool > &selected_dofs)
const unsigned int dofs_per_cell
Definition: fe_base.h:295
void renumber_dofs(const std::vector< types::global_dof_index > &new_numbers)
void swap(Vector< Number > &u, Vector< Number > &v)
Definition: vector.h:1312
void extract_locally_active_dofs(const DoFHandlerType &dof_handler, IndexSet &dof_set)
Definition: dof_tools.cc:1051
std::pair< unsigned int, unsigned int > system_to_component_index(const unsigned int index) const
Definition: fe.h:3032
#define AssertThrowMPI(error_code)
Definition: exceptions.h:1314
void make_sparsity_pattern(const DoFHandlerType &dof_handler, SparsityPatternType &sparsity_pattern, const ConstraintMatrix &constraints=ConstraintMatrix(), const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
void compute_clockwise_dg(std::vector< types::global_dof_index > &new_dof_indices, const DoFHandlerType &dof_handler, const Point< DoFHandlerType::space_dimension > &center, const bool counter)
Definition: mpi.h:53
void king_ordering(DoFHandlerType &dof_handler, const bool reversed_numbering=false, const bool use_constraints=false)
std::pair< unsigned int, types::global_dof_index > system_to_block_index(const unsigned int component) const
Definition: fe.h:3176
void block_wise(DoFHandler< dim, spacedim > &dof_handler)
unsigned int first_selected_component(const unsigned int overall_number_of_components=numbers::invalid_unsigned_int) const
Definition: fe.h:33
void compute_Cuthill_McKee(std::vector< types::global_dof_index > &new_dof_indices, const DoFHandlerType &, const bool reversed_numbering=false, const bool use_constraints=false)
types::global_dof_index n_dofs() const
std::vector< unsigned int > reverse_permutation(const std::vector< unsigned int > &permutation)
Definition: utilities.cc:495
static ::ExceptionBase & ExcNotImplemented()
const Triangulation< dim, spacedim > & get_triangulation() const
TrilinosWrappers::types::int_type global_index(const Epetra_BlockMap &map, const ::types::global_dof_index i)
bool is_element(const size_type index) const
Definition: index_set.h:1645
void reinit(const IndexSet &local_constraints=IndexSet())
void subdomain_wise(DoFHandlerType &dof_handler)
void clockwise_dg(DoFHandlerType &dof_handler, const Point< DoFHandlerType::space_dimension > &center, const bool counter=false)
const types::global_dof_index invalid_dof_index
Definition: types.h:187
const IndexSet & locally_owned_dofs() const
types::global_dof_index compute_block_wise(std::vector< types::global_dof_index > &new_dof_indices, const ITERATOR &start, const ENDITERATOR &end, bool is_level_operation)
size_type n_elements() const
Definition: index_set.h:1717
void push_back(const Quadrature< dim > &new_quadrature)
Definition: q_collection.h:196
cell_iterator end() const
static ::ExceptionBase & ExcInternalError()
void cell_wise(DoFHandlerType &dof_handler, const std::vector< typename DoFHandlerType::active_cell_iterator > &cell_order)