Reference documentation for deal.II version 8.4.2
dof_handler.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2003 - 2016 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/memory_consumption.h>
17 #include <deal.II/base/geometry_info.h>
18 #include <deal.II/base/thread_management.h>
19 #include <deal.II/base/std_cxx11/bind.h>
20 #include <deal.II/hp/dof_handler.h>
21 #include <deal.II/hp/dof_level.h>
22 #include <deal.II/hp/dof_faces.h>
23 #include <deal.II/dofs/dof_accessor.h>
24 #include <deal.II/grid/tria_accessor.h>
25 #include <deal.II/grid/tria_iterator.h>
26 #include <deal.II/grid/tria_levels.h>
27 #include <deal.II/grid/tria.h>
28 #include <deal.II/fe/fe.h>
29 #include <deal.II/distributed/shared_tria.h>
30 #include <deal.II/distributed/tria.h>
31 
32 #include <set>
33 #include <algorithm>
34 #include <functional>
35 
36 DEAL_II_NAMESPACE_OPEN
37 
38 // The following is necessary for compilation under Visual Studio which is unable to correctly
39 // distinguish between ::DoFHandler and ::hp::DoFHandler.
40 // Plus it makes code in dof_handler.cc easier to read.
41 // Requires C++11 support which is in Visual Studio 2013 and newer.
42 #if _MSC_VER >= 1800
43 template <int dim, int spacedim> using HpDoFHandler = ::hp::DoFHandler<dim, spacedim>;
44 #else
45 // When using older Visual Studio or a different compiler just fall back.
46 #define HpDoFHandler DoFHandler
47 #endif
48 
49 namespace parallel
50 {
51  namespace distributed
52  {
53  template <int, int> class Triangulation;
54  }
55 }
56 
57 
58 namespace internal
59 {
60  namespace hp
61  {
62  typedef
63  std::vector<std::pair<unsigned int, unsigned int> > DoFIdentities;
64 
65 
81  template <int structdim, int dim, int spacedim>
82  void
83  ensure_existence_of_dof_identities (const FiniteElement<dim,spacedim> &fe1,
84  const FiniteElement<dim,spacedim> &fe2,
85  std_cxx11::shared_ptr<DoFIdentities> &identities)
86  {
87  // see if we need to fill this
88  // entry, or whether it already
89  // exists
90  if (identities.get() == 0)
91  {
92  switch (structdim)
93  {
94  case 0:
95  {
96  identities =
97  std_cxx11::shared_ptr<DoFIdentities>
98  (new DoFIdentities(fe1.hp_vertex_dof_identities(fe2)));
99  break;
100  }
101 
102  case 1:
103  {
104  identities =
105  std_cxx11::shared_ptr<DoFIdentities>
106  (new DoFIdentities(fe1.hp_line_dof_identities(fe2)));
107  break;
108  }
109 
110  case 2:
111  {
112  identities =
113  std_cxx11::shared_ptr<DoFIdentities>
114  (new DoFIdentities(fe1.hp_quad_dof_identities(fe2)));
115  break;
116  }
117 
118  default:
119  Assert (false, ExcNotImplemented());
120  }
121 
122  // double check whether the
123  // newly created entries
124  // make any sense at all
125  for (unsigned int i=0; i<identities->size(); ++i)
126  {
127  Assert ((*identities)[i].first < fe1.template n_dofs_per_object<structdim>(),
128  ExcInternalError());
129  Assert ((*identities)[i].second < fe2.template n_dofs_per_object<structdim>(),
130  ExcInternalError());
131  }
132  }
133  }
134 
135 
136 
146  template <int dim, int spacedim, typename iterator>
147  unsigned int
148  get_most_dominating_fe_index (const iterator &object)
149  {
150  unsigned int dominating_fe_index = 0;
151  for (; dominating_fe_index<object->n_active_fe_indices();
152  ++dominating_fe_index)
153  {
154  const FiniteElement<dim, spacedim> &this_fe
155  = object->get_fe (object->nth_active_fe_index(dominating_fe_index));
156 
158  domination = FiniteElementDomination::either_element_can_dominate;
159  for (unsigned int other_fe_index=0;
160  other_fe_index<object->n_active_fe_indices();
161  ++other_fe_index)
162  if (other_fe_index != dominating_fe_index)
163  {
165  &that_fe
166  = object->get_fe (object->nth_active_fe_index(other_fe_index));
167 
168  domination = domination &
169  this_fe.compare_for_face_domination(that_fe);
170  }
171 
172  // see if this element is
173  // able to dominate all the
174  // other ones, and if so
175  // take it
176  if ((domination == FiniteElementDomination::this_element_dominates)
177  ||
178  (domination == FiniteElementDomination::either_element_can_dominate)
179  ||
180  (domination == FiniteElementDomination::no_requirements))
181  break;
182  }
183 
184  // check that we have
185  // found one such fe
186  if (dominating_fe_index != object->n_active_fe_indices())
187  {
188  // return the finite element
189  // index used on it. note
190  // that only a single fe can
191  // be active on such subfaces
192  return object->nth_active_fe_index(dominating_fe_index);
193  }
194  else
195  {
196  // if we couldn't find the most dominating object
198  }
199  }
200  }
201 }
202 
203 
204 
205 namespace internal
206 {
207  namespace hp
208  {
209  namespace DoFHandler
210  {
211  // access class
212  // ::hp::DoFHandler instead of
213  // namespace internal::hp::DoFHandler, etc
214  using ::hp::DoFHandler;
215 
221  {
229  template<int dim, int spacedim>
230  static
231  void
233  {
234  // The final step is allocating
235  // memory is to set up vertex dof
236  // information. since vertices
237  // are sequentially numbered,
238  // what we do first is to set up
239  // an array in which we record
240  // whether a vertex is associated
241  // with any of the given fe's, by
242  // setting a bit. in a later
243  // step, we then actually
244  // allocate memory for the
245  // required dofs
246  std::vector<std::vector<bool> >
247  vertex_fe_association (dof_handler.finite_elements->size(),
248  std::vector<bool> (dof_handler.tria->n_vertices(), false));
249 
250  for (typename HpDoFHandler<dim,spacedim>::active_cell_iterator
251  cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell)
252  for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
253  vertex_fe_association[cell->active_fe_index()][cell->vertex_index(v)]
254  = true;
255 
256  // in debug mode, make sure
257  // that each vertex is
258  // associated with at least one
259  // fe (note that except for
260  // unused vertices, all
261  // vertices are actually
262  // active)
263 #ifdef DEBUG
264  for (unsigned int v=0; v<dof_handler.tria->n_vertices(); ++v)
265  if (dof_handler.tria->vertex_used(v) == true)
266  {
267  unsigned int fe=0;
268  for (; fe<dof_handler.finite_elements->size(); ++fe)
269  if (vertex_fe_association[fe][v] == true)
270  break;
271  Assert (fe != dof_handler.finite_elements->size(), ExcInternalError());
272  }
273 #endif
274 
275  // next count how much memory
276  // we actually need. for each
277  // vertex, we need one slot per
278  // fe to store the fe_index,
279  // plus dofs_per_vertex for
280  // this fe. in addition, we
281  // need one slot as the end
282  // marker for the
283  // fe_indices. at the same time
284  // already fill the
285  // vertex_dofs_offsets field
286  dof_handler.vertex_dofs_offsets.resize (dof_handler.tria->n_vertices(),
288 
289  unsigned int vertex_slots_needed = 0;
290  for (unsigned int v=0; v<dof_handler.tria->n_vertices(); ++v)
291  if (dof_handler.tria->vertex_used(v) == true)
292  {
293  dof_handler.vertex_dofs_offsets[v] = vertex_slots_needed;
294 
295  for (unsigned int fe=0; fe<dof_handler.finite_elements->size(); ++fe)
296  if (vertex_fe_association[fe][v] == true)
297  vertex_slots_needed += (*dof_handler.finite_elements)[fe].dofs_per_vertex + 1;
298  ++vertex_slots_needed;
299  }
300 
301  // now allocate the space we
302  // have determined we need, and
303  // set up the linked lists for
304  // each of the vertices
305  dof_handler.vertex_dofs.resize (vertex_slots_needed,
307  for (unsigned int v=0; v<dof_handler.tria->n_vertices(); ++v)
308  if (dof_handler.tria->vertex_used(v) == true)
309  {
310  types::global_dof_index pointer = dof_handler.vertex_dofs_offsets[v];
311  for (unsigned int fe=0; fe<dof_handler.finite_elements->size(); ++fe)
312  if (vertex_fe_association[fe][v] == true)
313  {
314  // if this vertex
315  // uses this fe,
316  // then set the
317  // fe_index and
318  // move the pointer
319  // ahead
320  dof_handler.vertex_dofs[pointer] = fe;
321  pointer += (*dof_handler.finite_elements)[fe].dofs_per_vertex + 1;
322  }
323  // finally place the end
324  // marker
325  dof_handler.vertex_dofs[pointer] = numbers::invalid_dof_index;
326  }
327  }
328 
329 
330 
345  template <int spacedim>
346  static
348  distribute_dofs_on_cell (const typename ::hp::DoFHandler<1,spacedim>::active_cell_iterator &cell,
349  types::global_dof_index next_free_dof)
350  {
351  const unsigned int dim = 1;
352 
353  const FiniteElement<dim,spacedim> &fe = cell->get_fe();
354  const unsigned int fe_index = cell->active_fe_index ();
355 
356  // number dofs on vertices. to do
357  // so, check whether dofs for
358  // this vertex have been
359  // distributed and for the
360  // present fe (only check the
361  // first dof), and if this isn't
362  // the case distribute new ones
363  // there
364  if (fe.dofs_per_vertex > 0)
365  for (unsigned int vertex=0; vertex<GeometryInfo<1>::vertices_per_cell; ++vertex)
366  if (cell->vertex_dof_index(vertex, 0, fe_index) ==
368  for (unsigned int d=0; d<fe.dofs_per_vertex; ++d, ++next_free_dof)
369  cell->set_vertex_dof_index (vertex, d, next_free_dof, fe_index);
370 
371  // finally for the line. this one
372  // shouldn't be numbered yet
373  if (fe.dofs_per_line > 0)
374  {
375  Assert ((cell->dof_index(0, fe_index) ==
377  ExcInternalError());
378 
379  for (unsigned int d=0; d<fe.dofs_per_line; ++d, ++next_free_dof)
380  cell->set_dof_index (d, next_free_dof, fe_index);
381  }
382 
383  // note that this cell has been processed
384  cell->set_user_flag ();
385 
386  return next_free_dof;
387  }
388 
389 
390  template <int spacedim>
391  static
393  distribute_dofs_on_cell (const typename ::hp::DoFHandler<2,spacedim>::active_cell_iterator &cell,
394  types::global_dof_index next_free_dof)
395  {
396  const unsigned int dim = 2;
397 
398  const FiniteElement<dim,spacedim> &fe = cell->get_fe();
399  const unsigned int fe_index = cell->active_fe_index ();
400 
401  // number dofs on vertices. to do
402  // so, check whether dofs for
403  // this vertex have been
404  // distributed and for the
405  // present fe (only check the
406  // first dof), and if this isn't
407  // the case distribute new ones
408  // there
409  if (fe.dofs_per_vertex > 0)
410  for (unsigned int vertex=0; vertex<GeometryInfo<2>::vertices_per_cell; ++vertex)
411  if (cell->vertex_dof_index(vertex, 0, fe_index) ==
413  for (unsigned int d=0; d<fe.dofs_per_vertex; ++d, ++next_free_dof)
414  cell->set_vertex_dof_index (vertex, d, next_free_dof, fe_index);
415 
416  // next the sides. do the
417  // same as above: check whether
418  // the line is already numbered
419  // for the present fe_index, and
420  // if not do it
421  if (fe.dofs_per_line > 0)
422  for (unsigned int l=0; l<GeometryInfo<2>::lines_per_cell; ++l)
423  {
424  typename HpDoFHandler<dim,spacedim>::line_iterator
425  line = cell->line(l);
426 
427  if (line->dof_index(0,fe_index) ==
429  for (unsigned int d=0; d<fe.dofs_per_line; ++d, ++next_free_dof)
430  line->set_dof_index (d, next_free_dof, fe_index);
431  }
432 
433 
434  // finally for the quad. this one
435  // shouldn't be numbered yet
436  if (fe.dofs_per_quad > 0)
437  {
438  Assert ((cell->dof_index(0, fe_index) ==
440  ExcInternalError());
441 
442  for (unsigned int d=0; d<fe.dofs_per_quad; ++d, ++next_free_dof)
443  cell->set_dof_index (d, next_free_dof, fe_index);
444  }
445 
446  // note that this cell has been processed
447  cell->set_user_flag ();
448 
449  return next_free_dof;
450  }
451 
452 
453  template <int spacedim>
454  static
456  distribute_dofs_on_cell (const typename ::hp::DoFHandler<3,spacedim>::active_cell_iterator &cell,
457  types::global_dof_index next_free_dof)
458  {
459  const unsigned int dim = 3;
460 
461  const FiniteElement<dim,spacedim> &fe = cell->get_fe();
462  const unsigned int fe_index = cell->active_fe_index ();
463 
464  // number dofs on vertices. to do
465  // so, check whether dofs for
466  // this vertex have been
467  // distributed and for the
468  // present fe (only check the
469  // first dof), and if this isn't
470  // the case distribute new ones
471  // there
472  if (fe.dofs_per_vertex > 0)
473  for (unsigned int vertex=0; vertex<GeometryInfo<3>::vertices_per_cell; ++vertex)
474  if (cell->vertex_dof_index(vertex, 0, fe_index) ==
476  for (unsigned int d=0; d<fe.dofs_per_vertex; ++d, ++next_free_dof)
477  cell->set_vertex_dof_index (vertex, d, next_free_dof, fe_index);
478 
479  // next the four lines. do the
480  // same as above: check whether
481  // the line is already numbered
482  // for the present fe_index, and
483  // if not do it
484  if (fe.dofs_per_line > 0)
485  for (unsigned int l=0; l<GeometryInfo<3>::lines_per_cell; ++l)
486  {
487  typename HpDoFHandler<dim,spacedim>::line_iterator
488  line = cell->line(l);
489 
490  if (line->dof_index(0,fe_index) ==
492  for (unsigned int d=0; d<fe.dofs_per_line; ++d, ++next_free_dof)
493  line->set_dof_index (d, next_free_dof, fe_index);
494  }
495 
496  // same for quads
497  if (fe.dofs_per_quad > 0)
498  for (unsigned int q=0; q<GeometryInfo<3>::quads_per_cell; ++q)
499  {
500  typename HpDoFHandler<dim,spacedim>::quad_iterator
501  quad = cell->quad(q);
502 
503  if (quad->dof_index(0,fe_index) ==
505  for (unsigned int d=0; d<fe.dofs_per_quad; ++d, ++next_free_dof)
506  quad->set_dof_index (d, next_free_dof, fe_index);
507  }
508 
509 
510  // finally for the hex. this one
511  // shouldn't be numbered yet
512  if (fe.dofs_per_hex > 0)
513  {
514  Assert ((cell->dof_index(0, fe_index) ==
516  ExcInternalError());
517 
518  for (unsigned int d=0; d<fe.dofs_per_hex; ++d, ++next_free_dof)
519  cell->set_dof_index (d, next_free_dof, fe_index);
520  }
521 
522  // note that this cell has been processed
523  cell->set_user_flag ();
524 
525  return next_free_dof;
526  }
527 
528 
538  template <int spacedim>
539  static
540  void
542  {
543  const unsigned int dim = 1;
544 
545  typedef DoFHandler<dim,spacedim> BaseClass;
546 
547  Assert (dof_handler.finite_elements != 0,
548  typename BaseClass::ExcNoFESelected());
549  Assert (dof_handler.finite_elements->size() > 0,
550  typename BaseClass::ExcNoFESelected());
551  Assert (dof_handler.tria->n_levels() > 0,
552  typename
553  BaseClass::ExcInvalidTriangulation());
554  Assert (dof_handler.tria->n_levels() == dof_handler.levels.size (),
555  ExcInternalError ());
556 
557  // Release all space except the
558  // active_fe_indices field which
559  // we have to backup before
560  {
561  std::vector<std::vector<DoFLevel::active_fe_index_type> >
562  active_fe_backup(dof_handler.levels.size ());
563  for (unsigned int level = 0; level<dof_handler.levels.size (); ++level)
564  std::swap (dof_handler.levels[level]->active_fe_indices,
565  active_fe_backup[level]);
566 
567  // delete all levels and set them up
568  // newly, since vectors are
569  // troublesome if you want to change
570  // their size
571  dof_handler.clear_space ();
572 
573  for (unsigned int level=0; level<dof_handler.tria->n_levels(); ++level)
574  {
575  dof_handler.levels.push_back (new internal::hp::DoFLevel);
576  std::swap (active_fe_backup[level],
577  dof_handler.levels[level]->active_fe_indices);
578  }
579  }
580 
581  // LINE (CELL) DOFs
582 
583  // count how much space we need
584  // on each level for the cell
585  // dofs and set the
586  // dof_*_offsets
587  // data. initially set the latter
588  // to an invalid index, and only
589  // later set it to something
590  // reasonable for active dof_handler.cells
591  //
592  // note that for dof_handler.cells, the
593  // situation is simpler than for
594  // other (lower dimensional)
595  // objects since exactly one
596  // finite element is used for it
597  for (unsigned int level=0; level<dof_handler.tria->n_levels(); ++level)
598  {
599  dof_handler.levels[level]->dof_offsets
600  = std::vector<DoFLevel::offset_type> (
601  dof_handler.tria->n_raw_lines(level),
602  (DoFLevel::offset_type)(-1));
603  dof_handler.levels[level]->cell_cache_offsets
604  = std::vector<DoFLevel::offset_type> (
605  dof_handler.tria->n_raw_lines(level),
606  (DoFLevel::offset_type)(-1));
607 
608  types::global_dof_index next_free_dof = 0;
609  types::global_dof_index cache_size = 0;
610  for (typename HpDoFHandler<dim,spacedim>::active_cell_iterator
611  cell=dof_handler.begin_active(level);
612  cell!=dof_handler.end_active(level); ++cell)
613  if (!cell->has_children())
614  {
615  dof_handler.levels[level]->dof_offsets[cell->index()] = next_free_dof;
616  next_free_dof += cell->get_fe().dofs_per_line;
617 
618  dof_handler.levels[level]->cell_cache_offsets[cell->index()] = cache_size;
619  cache_size += cell->get_fe().dofs_per_cell;
620  }
621 
622  dof_handler.levels[level]->dof_indices
623  = std::vector<types::global_dof_index> (next_free_dof,
625  dof_handler.levels[level]->cell_dof_indices_cache
626  = std::vector<types::global_dof_index> (cache_size,
628  }
629 
630  // safety check: make sure that
631  // the number of DoFs we
632  // allocated is actually correct
633  // (above we have also set the
634  // dof_*_offsets field, so
635  // we couldn't use this simpler
636  // algorithm)
637 #ifdef DEBUG
638  for (unsigned int level=0; level<dof_handler.tria->n_levels(); ++level)
639  {
640  types::global_dof_index counter = 0;
641  for (typename HpDoFHandler<dim,spacedim>::cell_iterator
642  cell=dof_handler.begin_active(level);
643  cell!=dof_handler.end_active(level); ++cell)
644  if (!cell->has_children())
645  counter += cell->get_fe().dofs_per_line;
646 
647  Assert (dof_handler.levels[level]->dof_indices.size() == counter,
648  ExcInternalError());
649  Assert (static_cast<unsigned int>
650  (std::count (dof_handler.levels[level]->dof_offsets.begin(),
651  dof_handler.levels[level]->dof_offsets.end(),
652  (DoFLevel::offset_type)(-1)))
653  ==
654  dof_handler.tria->n_raw_lines(level) - dof_handler.tria->n_active_lines(level),
655  ExcInternalError());
656  }
657 #endif
658 
659 
660  // VERTEX DOFS
661  reserve_space_vertices (dof_handler);
662  }
663 
664 
665  template <int spacedim>
666  static
667  void
668  reserve_space (DoFHandler<2,spacedim> &dof_handler)
669  {
670  const unsigned int dim = 2;
671 
672  typedef DoFHandler<dim,spacedim> BaseClass;
673 
674  Assert (dof_handler.finite_elements != 0,
675  typename BaseClass::ExcNoFESelected());
676  Assert (dof_handler.finite_elements->size() > 0,
677  typename BaseClass::ExcNoFESelected());
678  Assert (dof_handler.tria->n_levels() > 0,
679  typename BaseClass::ExcInvalidTriangulation());
680  Assert (dof_handler.tria->n_levels() == dof_handler.levels.size (),
681  ExcInternalError ());
682 
683  // Release all space except the
684  // active_fe_indices field which
685  // we have to backup before
686  {
687  std::vector<std::vector<DoFLevel::active_fe_index_type> >
688  active_fe_backup(dof_handler.levels.size ());
689  for (unsigned int level = 0; level<dof_handler.levels.size (); ++level)
690  std::swap (dof_handler.levels[level]->active_fe_indices,
691  active_fe_backup[level]);
692 
693  // delete all levels and set them up
694  // newly, since vectors are
695  // troublesome if you want to change
696  // their size
697  dof_handler.clear_space ();
698 
699  for (unsigned int level=0; level<dof_handler.tria->n_levels(); ++level)
700  {
701  dof_handler.levels.push_back (new internal::hp::DoFLevel);
702  std::swap (active_fe_backup[level],
703  dof_handler.levels[level]->active_fe_indices);
704  }
705  dof_handler.faces = new internal::hp::DoFIndicesOnFaces<2>;
706  }
707 
708 
709  // QUAD (CELL) DOFs
710 
711  // count how much space we need
712  // on each level for the cell
713  // dofs and set the
714  // dof_*_offsets
715  // data. initially set the latter
716  // to an invalid index, and only
717  // later set it to something
718  // reasonable for active dof_handler.cells
719  //
720  // note that for dof_handler.cells, the
721  // situation is simpler than for
722  // other (lower dimensional)
723  // objects since exactly one
724  // finite element is used for it
725  for (unsigned int level=0; level<dof_handler.tria->n_levels(); ++level)
726  {
727  dof_handler.levels[level]->dof_offsets
728  = std::vector<DoFLevel::offset_type> (
729  dof_handler.tria->n_raw_quads(level),
730  (DoFLevel::offset_type)(-1));
731  dof_handler.levels[level]->cell_cache_offsets
732  = std::vector<DoFLevel::offset_type> (
733  dof_handler.tria->n_raw_quads(level),
734  (DoFLevel::offset_type)(-1));
735 
736  types::global_dof_index next_free_dof = 0;
737  types::global_dof_index cache_size = 0;
738  for (typename HpDoFHandler<dim, spacedim>::active_cell_iterator
739  cell=dof_handler.begin_active(level);
740  cell!=dof_handler.end_active(level); ++cell)
741  if (!cell->has_children())
742  {
743  dof_handler.levels[level]->dof_offsets[cell->index()] = next_free_dof;
744  next_free_dof += cell->get_fe().dofs_per_quad;
745 
746  dof_handler.levels[level]->cell_cache_offsets[cell->index()] = cache_size;
747  cache_size += cell->get_fe().dofs_per_cell;
748  }
749 
750  dof_handler.levels[level]->dof_indices
751  = std::vector<types::global_dof_index> (next_free_dof,
753  dof_handler.levels[level]->cell_dof_indices_cache
754  = std::vector<types::global_dof_index> (cache_size,
756  }
757 
758  // safety check: make sure that
759  // the number of DoFs we
760  // allocated is actually correct
761  // (above we have also set the
762  // dof_*_offsets field, so
763  // we couldn't use this simpler
764  // algorithm)
765 #ifdef DEBUG
766  for (unsigned int level=0; level<dof_handler.tria->n_levels(); ++level)
767  {
768  types::global_dof_index counter = 0;
769  for (typename HpDoFHandler<dim,spacedim>::cell_iterator
770  cell=dof_handler.begin_active(level);
771  cell!=dof_handler.end_active(level); ++cell)
772  if (!cell->has_children())
773  counter += cell->get_fe().dofs_per_quad;
774 
775  Assert (dof_handler.levels[level]->dof_indices.size() == counter,
776  ExcInternalError());
777  Assert (static_cast<unsigned int>
778  (std::count (dof_handler.levels[level]->dof_offsets.begin(),
779  dof_handler.levels[level]->dof_offsets.end(),
780  (DoFLevel::offset_type)(-1)))
781  ==
782  dof_handler.tria->n_raw_quads(level) - dof_handler.tria->n_active_quads(level),
783  ExcInternalError());
784  }
785 #endif
786 
787 
788  // LINE DOFS
789  //
790  // same here: count line dofs,
791  // then allocate as much space as
792  // we need and prime the linked
793  // list for lines (see the
794  // description in hp::DoFLevel)
795  // with the indices we will
796  // need. note that our task is
797  // more complicated since two
798  // adjacent dof_handler.cells may have
799  // different active_fe_indices,
800  // in which case we need to
801  // allocate *two* sets of line
802  // dofs for the same line
803  //
804  // the way we do things is that
805  // we loop over all active dof_handler.cells
806  // (these are the ones that have
807  // DoFs only anyway) and all
808  // their dof_handler.faces. We note in the
809  // user flags whether we have
810  // previously visited a face and
811  // if so skip it (consequently,
812  // we have to save and later
813  // restore the line flags)
814  {
815  std::vector<bool> saved_line_user_flags;
816  const_cast<::Triangulation<dim,spacedim>&>(*dof_handler.tria)
817  .save_user_flags_line (saved_line_user_flags);
818  const_cast<::Triangulation<dim,spacedim>&>(*dof_handler.tria)
819  .clear_user_flags_line ();
820 
821  // an array to hold how many
822  // slots (see the hp::DoFLevel
823  // class) we will have to store
824  // on each level
825  unsigned int n_line_slots = 0;
826 
827  for (typename HpDoFHandler<dim,spacedim>::active_cell_iterator
828  cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell)
829  for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
830  if (! cell->face(face)->user_flag_set())
831  {
832  // ok, face has not been
833  // visited. so we need to
834  // allocate space for it. let's
835  // see how much we need: we need
836  // one set if a) there is no
837  // neighbor behind this face, or
838  // b) the neighbor is either
839  // coarser or finer than we are,
840  // or c) the neighbor is neither
841  // coarser nor finer, but has
842  // happens to have the same
843  // active_fe_index:
844  if (cell->at_boundary(face)
845  ||
846  cell->face(face)->has_children()
847  ||
848  cell->neighbor_is_coarser(face)
849  ||
850  (!cell->at_boundary(face)
851  &&
852  (cell->active_fe_index() == cell->neighbor(face)->active_fe_index())))
853  // ok, one set of
854  // dofs. that makes
855  // one index, 1 times
856  // dofs_per_line
857  // dofs, and one stop
858  // index
859  n_line_slots
860  += (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line + 2;
861 
862  // otherwise we do
863  // indeed need two
864  // sets, i.e. two
865  // indices, two sets of
866  // dofs, and one stop
867  // index:
868  else
869  n_line_slots
870  += ((*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line
871  +
872  (*dof_handler.finite_elements)[cell->neighbor(face)->active_fe_index()]
873  .dofs_per_line
874  +
875  3);
876 
877  // mark this face as
878  // visited
879  cell->face(face)->set_user_flag ();
880  }
881 
882  // now that we know how many
883  // line dofs we will have to
884  // have on each level, allocate
885  // the memory. note that we
886  // allocate offsets for all
887  // lines, though only the
888  // active ones will have a
889  // non-invalid value later on
890  dof_handler.faces->lines.dof_offsets
891  = std::vector<unsigned int> (dof_handler.tria->n_raw_lines(),
892  (unsigned int)(-1));
893  dof_handler.faces->lines.dofs
894  = std::vector<types::global_dof_index> (n_line_slots,
896 
897  // with the memory now
898  // allocated, loop over the
899  // dof_handler.cells again and prime the
900  // _offset values as well as
901  // the fe_index fields
902  const_cast<::Triangulation<dim,spacedim>&>(*dof_handler.tria)
903  .clear_user_flags_line ();
904 
905  unsigned int next_free_line_slot = 0;
906 
907  for (typename HpDoFHandler<dim,spacedim>::active_cell_iterator
908  cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell)
909  for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
910  if (! cell->face(face)->user_flag_set())
911  {
912  // same decision tree
913  // as before
914  if (cell->at_boundary(face)
915  ||
916  cell->face(face)->has_children()
917  ||
918  cell->neighbor_is_coarser(face)
919  ||
920  (!cell->at_boundary(face)
921  &&
922  (cell->active_fe_index() == cell->neighbor(face)->active_fe_index())))
923  {
924  dof_handler.faces
925  ->lines.dof_offsets[cell->face(face)->index()]
926  = next_free_line_slot;
927 
928  // set first slot
929  // for this line to
930  // active_fe_index
931  // of this face
932  dof_handler.faces
933  ->lines.dofs[next_free_line_slot]
934  = cell->active_fe_index();
935 
936  // the next
937  // dofs_per_line
938  // indices remain
939  // unset for the
940  // moment (i.e. at
941  // invalid_dof_index).
942  // following this
943  // comes the stop
944  // index, which
945  // also is
946  // invalid_dof_index
947  // and therefore
948  // does not have to
949  // be explicitly
950  // set
951 
952  // finally, mark
953  // those slots as
954  // used
955  next_free_line_slot
956  += (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line + 2;
957  }
958  else
959  {
960  dof_handler.faces
961  ->lines.dof_offsets[cell->face(face)->index()]
962  = next_free_line_slot;
963 
964  // set first slot
965  // for this line to
966  // active_fe_index
967  // of this face
968  dof_handler.faces
969  ->lines.dofs[next_free_line_slot]
970  = cell->active_fe_index();
971 
972  // the next
973  // dofs_per_line
974  // indices remain
975  // unset for the
976  // moment (i.e. at
977  // invalid_dof_index).
978  //
979  // then comes the
980  // fe_index for the
981  // neighboring
982  // cell:
983  dof_handler.faces
984  ->lines.dofs[next_free_line_slot
985  +
986  (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line
987  +
988  1]
989  = cell->neighbor(face)->active_fe_index();
990  // then again a set
991  // of dofs that we
992  // need not set
993  // right now
994  //
995  // following this
996  // comes the stop
997  // index, which
998  // also is
999  // invalid_dof_index
1000  // and therefore
1001  // does not have to
1002  // be explicitly
1003  // set
1004 
1005  // finally, mark
1006  // those slots as
1007  // used
1008  next_free_line_slot
1009  += ((*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_line
1010  +
1011  (*dof_handler.finite_elements)[cell->neighbor(face)->active_fe_index()]
1012  .dofs_per_line
1013  +
1014  3);
1015  }
1016 
1017  // mark this face as
1018  // visited
1019  cell->face(face)->set_user_flag ();
1020  }
1021 
1022  // we should have moved the
1023  // cursor for each level to the
1024  // total number of dofs on that
1025  // level. check that
1026  Assert (next_free_line_slot == n_line_slots,
1027  ExcInternalError());
1028 
1029  // at the end, restore the user
1030  // flags for the lines
1031  const_cast<::Triangulation<dim,spacedim>&>(*dof_handler.tria)
1032  .load_user_flags_line (saved_line_user_flags);
1033  }
1034 
1035 
1036  // VERTEX DOFS
1037  reserve_space_vertices (dof_handler);
1038  }
1039 
1040 
1041  template <int spacedim>
1042  static
1043  void
1044  reserve_space (DoFHandler<3,spacedim> &dof_handler)
1045  {
1046  const unsigned int dim = 3;
1047 
1048  typedef DoFHandler<dim,spacedim> BaseClass;
1049 
1050  Assert (dof_handler.finite_elements != 0,
1051  typename BaseClass::ExcNoFESelected());
1052  Assert (dof_handler.finite_elements->size() > 0,
1053  typename BaseClass::ExcNoFESelected());
1054  Assert (dof_handler.tria->n_levels() > 0,
1055  typename BaseClass::ExcInvalidTriangulation());
1056  Assert (dof_handler.tria->n_levels() == dof_handler.levels.size (),
1057  ExcInternalError ());
1058 
1059  // Release all space except the
1060  // active_fe_indices field which
1061  // we have to backup before
1062  {
1063  std::vector<std::vector<DoFLevel::active_fe_index_type> >
1064  active_fe_backup(dof_handler.levels.size ());
1065  for (unsigned int level = 0; level<dof_handler.levels.size (); ++level)
1066  std::swap (dof_handler.levels[level]->active_fe_indices,
1067  active_fe_backup[level]);
1068 
1069  // delete all levels and set them up
1070  // newly, since vectors are
1071  // troublesome if you want to change
1072  // their size
1073  dof_handler.clear_space ();
1074 
1075  for (unsigned int level=0; level<dof_handler.tria->n_levels(); ++level)
1076  {
1077  dof_handler.levels.push_back (new internal::hp::DoFLevel);
1078  std::swap (active_fe_backup[level],
1079  dof_handler.levels[level]->active_fe_indices);
1080  }
1081  dof_handler.faces = new internal::hp::DoFIndicesOnFaces<3>;
1082  }
1083 
1084 
1085  // HEX (CELL) DOFs
1086 
1087  // count how much space we need
1088  // on each level for the cell
1089  // dofs and set the
1090  // dof_*_offsets
1091  // data. initially set the latter
1092  // to an invalid index, and only
1093  // later set it to something
1094  // reasonable for active dof_handler.cells
1095  //
1096  // note that for dof_handler.cells, the
1097  // situation is simpler than for
1098  // other (lower dimensional)
1099  // objects since exactly one
1100  // finite element is used for it
1101  for (unsigned int level=0; level<dof_handler.tria->n_levels(); ++level)
1102  {
1103  dof_handler.levels[level]->dof_offsets
1104  = std::vector<DoFLevel::offset_type> (
1105  dof_handler.tria->n_raw_hexs(level),
1106  (DoFLevel::offset_type)(-1));
1107  dof_handler.levels[level]->cell_cache_offsets
1108  = std::vector<DoFLevel::offset_type> (
1109  dof_handler.tria->n_raw_hexs(level),
1110  (DoFLevel::offset_type)(-1));
1111 
1112  types::global_dof_index next_free_dof = 0;
1113  types::global_dof_index cache_size = 0;
1114  for (typename HpDoFHandler<dim,spacedim>::active_cell_iterator
1115  cell=dof_handler.begin_active(level);
1116  cell!=dof_handler.end_active(level); ++cell)
1117  if (!cell->has_children())
1118  {
1119  dof_handler.levels[level]->dof_offsets[cell->index()] = next_free_dof;
1120  next_free_dof += cell->get_fe().dofs_per_hex;
1121 
1122  dof_handler.levels[level]->cell_cache_offsets[cell->index()] = cache_size;
1123  cache_size += cell->get_fe().dofs_per_cell;
1124  }
1125 
1126  dof_handler.levels[level]->dof_indices
1127  = std::vector<types::global_dof_index> (next_free_dof,
1129  dof_handler.levels[level]->cell_dof_indices_cache
1130  = std::vector<types::global_dof_index> (cache_size,
1132  }
1133 
1134  // safety check: make sure that
1135  // the number of DoFs we
1136  // allocated is actually correct
1137  // (above we have also set the
1138  // dof_*_offsets field, so
1139  // we couldn't use this simpler
1140  // algorithm)
1141 #ifdef DEBUG
1142  for (unsigned int level=0; level<dof_handler.tria->n_levels(); ++level)
1143  {
1144  types::global_dof_index counter = 0;
1145  for (typename HpDoFHandler<dim,spacedim>::cell_iterator
1146  cell=dof_handler.begin_active(level);
1147  cell!=dof_handler.end_active(level); ++cell)
1148  if (!cell->has_children())
1149  counter += cell->get_fe().dofs_per_hex;
1150 
1151  Assert (dof_handler.levels[level]->dof_indices.size() == counter,
1152  ExcInternalError());
1153  Assert (static_cast<unsigned int>
1154  (std::count (dof_handler.levels[level]->dof_offsets.begin(),
1155  dof_handler.levels[level]->dof_offsets.end(),
1156  (DoFLevel::offset_type)(-1)))
1157  ==
1158  dof_handler.tria->n_raw_hexs(level) - dof_handler.tria->n_active_hexs(level),
1159  ExcInternalError());
1160  }
1161 #endif
1162 
1163 
1164  // QUAD DOFS
1165  //
1166  // same here: count quad dofs,
1167  // then allocate as much space as
1168  // we need and prime the linked
1169  // list for quad (see the
1170  // description in hp::DoFLevel)
1171  // with the indices we will
1172  // need. note that our task is
1173  // more complicated since two
1174  // adjacent dof_handler.cells may have
1175  // different active_fe_indices,
1176  // in which case we need to
1177  // allocate *two* sets of line
1178  // dofs for the same line
1179  //
1180  // the way we do things is that
1181  // we loop over all active dof_handler.cells
1182  // (these are the ones that have
1183  // DoFs only anyway) and all
1184  // their dof_handler.faces. We note in the
1185  // user flags whether we have
1186  // previously visited a face and
1187  // if so skip it (consequently,
1188  // we have to save and later
1189  // restore the line flags)
1190  {
1191  std::vector<bool> saved_quad_user_flags;
1192  const_cast<::Triangulation<dim,spacedim>&>(*dof_handler.tria)
1193  .save_user_flags_quad (saved_quad_user_flags);
1194  const_cast<::Triangulation<dim,spacedim>&>(*dof_handler.tria)
1195  .clear_user_flags_quad ();
1196 
1197  // examine, how how many
1198  // slots (see the hp::DoFLevel
1199  // class) we will have to store
1200  unsigned int n_quad_slots = 0;
1201 
1202  for (typename HpDoFHandler<dim,spacedim>::active_cell_iterator
1203  cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell)
1204  for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
1205  if (! cell->face(face)->user_flag_set())
1206  {
1207  // ok, face has not been
1208  // visited. so we need to
1209  // allocate space for
1210  // it. let's see how much
1211  // we need: we need one
1212  // set if a) there is no
1213  // neighbor behind this
1214  // face, or b) the
1215  // neighbor is not on the
1216  // same level or further
1217  // refined, or c) the
1218  // neighbor is on the
1219  // same level, but
1220  // happens to have the
1221  // same active_fe_index:
1222  if (cell->at_boundary(face)
1223  ||
1224  cell->face(face)->has_children()
1225  ||
1226  cell->neighbor_is_coarser(face)
1227  ||
1228  (!cell->at_boundary(face)
1229  &&
1230  (cell->active_fe_index() == cell->neighbor(face)->active_fe_index())))
1231  // ok, one set of
1232  // dofs. that makes
1233  // one index, 1 times
1234  // dofs_per_quad
1235  // dofs, and one stop
1236  // index
1237  n_quad_slots
1238  += (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad + 2;
1239 
1240  // otherwise we do
1241  // indeed need two
1242  // sets, i.e. two
1243  // indices, two sets of
1244  // dofs, and one stop
1245  // index:
1246  else
1247  n_quad_slots
1248  += ((*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad
1249  +
1250  (*dof_handler.finite_elements)[cell->neighbor(face)->active_fe_index()]
1251  .dofs_per_quad
1252  +
1253  3);
1254 
1255  // mark this face as
1256  // visited
1257  cell->face(face)->set_user_flag ();
1258  }
1259 
1260  // now that we know how many
1261  // quad dofs we will have to
1262  // have, allocate
1263  // the memory. note that we
1264  // allocate offsets for all
1265  // quads, though only the
1266  // active ones will have a
1267  // non-invalid value later on
1268  if (true)
1269  {
1270  dof_handler.faces->quads.dof_offsets
1271  = std::vector<unsigned int>
1272  (dof_handler.tria->n_raw_quads(),
1273  (unsigned int)(-1));
1274  dof_handler.faces->quads.dofs
1275  = std::vector<types::global_dof_index> (n_quad_slots,
1277  }
1278 
1279  // with the memory now
1280  // allocated, loop over the
1281  // dof_handler.cells again and prime the
1282  // _offset values as well as
1283  // the fe_index fields
1284  const_cast<::Triangulation<dim,spacedim>&>(*dof_handler.tria)
1285  .clear_user_flags_quad ();
1286 
1287  unsigned int next_free_quad_slot = 0;
1288 
1289  for (typename HpDoFHandler<dim,spacedim>::active_cell_iterator
1290  cell=dof_handler.begin_active(); cell!=dof_handler.end(); ++cell)
1291  for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
1292  if (! cell->face(face)->user_flag_set())
1293  {
1294  // same decision tree
1295  // as before
1296  if (cell->at_boundary(face)
1297  ||
1298  cell->face(face)->has_children()
1299  ||
1300  cell->neighbor_is_coarser(face)
1301  ||
1302  (!cell->at_boundary(face)
1303  &&
1304  (cell->active_fe_index() == cell->neighbor(face)->active_fe_index())))
1305  {
1306  dof_handler.faces
1307  ->quads.dof_offsets[cell->face(face)->index()]
1308  = next_free_quad_slot;
1309 
1310  // set first slot
1311  // for this quad to
1312  // active_fe_index
1313  // of this face
1314  dof_handler.faces
1315  ->quads.dofs[next_free_quad_slot]
1316  = cell->active_fe_index();
1317 
1318  // the next
1319  // dofs_per_quad
1320  // indices remain
1321  // unset for the
1322  // moment (i.e. at
1323  // invalid_dof_index).
1324  // following this
1325  // comes the stop
1326  // index, which
1327  // also is
1328  // invalid_dof_index
1329  // and therefore
1330  // does not have to
1331  // be explicitly
1332  // set
1333 
1334  // finally, mark
1335  // those slots as
1336  // used
1337  next_free_quad_slot
1338  += (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad + 2;
1339  }
1340  else
1341  {
1342  dof_handler.faces
1343  ->quads.dof_offsets[cell->face(face)->index()]
1344  = next_free_quad_slot;
1345 
1346  // set first slot
1347  // for this quad to
1348  // active_fe_index
1349  // of this face
1350  dof_handler.faces
1351  ->quads.dofs[next_free_quad_slot]
1352  = cell->active_fe_index();
1353 
1354  // the next
1355  // dofs_per_quad
1356  // indices remain
1357  // unset for the
1358  // moment (i.e. at
1359  // invalid_dof_index).
1360  //
1361  // then comes the
1362  // fe_index for the
1363  // neighboring
1364  // cell:
1365  dof_handler.faces
1366  ->quads.dofs[next_free_quad_slot
1367  +
1368  (*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad
1369  +
1370  1]
1371  = cell->neighbor(face)->active_fe_index();
1372  // then again a set
1373  // of dofs that we
1374  // need not set
1375  // right now
1376  //
1377  // following this
1378  // comes the stop
1379  // index, which
1380  // also is
1381  // invalid_dof_index
1382  // and therefore
1383  // does not have to
1384  // be explicitly
1385  // set
1386 
1387  // finally, mark
1388  // those slots as
1389  // used
1390  next_free_quad_slot
1391  += ((*dof_handler.finite_elements)[cell->active_fe_index()].dofs_per_quad
1392  +
1393  (*dof_handler.finite_elements)[cell->neighbor(face)->active_fe_index()]
1394  .dofs_per_quad
1395  +
1396  3);
1397  }
1398 
1399  // mark this face as
1400  // visited
1401  cell->face(face)->set_user_flag ();
1402  }
1403 
1404  // we should have moved the
1405  // cursor to the total number
1406  // of dofs. check that
1407  Assert (next_free_quad_slot == n_quad_slots,
1408  ExcInternalError());
1409 
1410  // at the end, restore the user
1411  // flags for the quads
1412  const_cast<::Triangulation<dim,spacedim>&>(*dof_handler.tria)
1413  .load_user_flags_quad (saved_quad_user_flags);
1414  }
1415 
1416 
1417  // LINE DOFS
1418 
1419  // the situation here is pretty
1420  // much like with vertices: there
1421  // can be an arbitrary number of
1422  // finite elements associated
1423  // with each line.
1424  //
1425  // the algorithm we use is
1426  // somewhat similar to what we do
1427  // in reserve_space_vertices()
1428  if (true)
1429  {
1430  // what we do first is to set up
1431  // an array in which we record
1432  // whether a line is associated
1433  // with any of the given fe's, by
1434  // setting a bit. in a later
1435  // step, we then actually
1436  // allocate memory for the
1437  // required dofs
1438  std::vector<std::vector<bool> >
1439  line_fe_association (dof_handler.finite_elements->size(),
1440  std::vector<bool> (dof_handler.tria->n_raw_lines(),
1441  false));
1442 
1443  for (typename HpDoFHandler<dim,spacedim>::active_cell_iterator
1444  cell=dof_handler.begin_active();
1445  cell!=dof_handler.end(); ++cell)
1446  for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
1447  line_fe_association[cell->active_fe_index()][cell->line_index(l)]
1448  = true;
1449 
1450  // first check which of the
1451  // lines is used at all,
1452  // i.e. is associated with a
1453  // finite element. we do this
1454  // since not all lines may
1455  // actually be used, in which
1456  // case we do not have to
1457  // allocate any memory at
1458  // all
1459  std::vector<bool> line_is_used (dof_handler.tria->n_raw_lines(), false);
1460  for (unsigned int line=0; line<dof_handler.tria->n_raw_lines(); ++line)
1461  for (unsigned int fe=0; fe<dof_handler.finite_elements->size(); ++fe)
1462  if (line_fe_association[fe][line] == true)
1463  {
1464  line_is_used[line] = true;
1465  break;
1466  }
1467 
1468  // next count how much memory
1469  // we actually need. for each
1470  // line, we need one slot per
1471  // fe to store the fe_index,
1472  // plus dofs_per_line for
1473  // this fe. in addition, we
1474  // need one slot as the end
1475  // marker for the
1476  // fe_indices. at the same
1477  // time already fill the
1478  // line_dofs_offsets field
1479  dof_handler.faces->lines.dof_offsets
1480  .resize (dof_handler.tria->n_raw_lines(),
1482 
1483  unsigned int line_slots_needed = 0;
1484  for (unsigned int line=0; line<dof_handler.tria->n_raw_lines(); ++line)
1485  if (line_is_used[line] == true)
1486  {
1487  dof_handler.faces->lines.dof_offsets[line] = line_slots_needed;
1488 
1489  for (unsigned int fe=0; fe<dof_handler.finite_elements->size(); ++fe)
1490  if (line_fe_association[fe][line] == true)
1491  line_slots_needed += (*dof_handler.finite_elements)[fe].dofs_per_line + 1;
1492  ++line_slots_needed;
1493  }
1494 
1495  // now allocate the space we
1496  // have determined we need, and
1497  // set up the linked lists for
1498  // each of the lines
1499  dof_handler.faces->lines.dofs.resize (line_slots_needed,
1501  for (unsigned int line=0; line<dof_handler.tria->n_raw_lines(); ++line)
1502  if (line_is_used[line] == true)
1503  {
1504  unsigned int pointer = dof_handler.faces->lines.dof_offsets[line];
1505  for (unsigned int fe=0; fe<dof_handler.finite_elements->size(); ++fe)
1506  if (line_fe_association[fe][line] == true)
1507  {
1508  // if this line
1509  // uses this fe,
1510  // then set the
1511  // fe_index and
1512  // move the
1513  // pointer ahead
1514  dof_handler.faces->lines.dofs[pointer] = fe;
1515  pointer += (*dof_handler.finite_elements)[fe].dofs_per_line + 1;
1516  }
1517  // finally place the end
1518  // marker
1519  dof_handler.faces->lines.dofs[pointer] = numbers::invalid_dof_index;
1520  }
1521  }
1522 
1523 
1524 
1525  // VERTEX DOFS
1526  reserve_space_vertices (dof_handler);
1527  }
1528 
1529 
1534  template <int spacedim>
1535  static
1536  unsigned int
1538  {
1539  return std::min(static_cast<types::global_dof_index> (3*
1540  dof_handler.finite_elements->max_dofs_per_vertex() +
1541  2*dof_handler.finite_elements->max_dofs_per_line()),
1542  dof_handler.n_dofs());
1543  }
1544 
1545 
1546 
1547  template <int spacedim>
1548  static
1549  unsigned int
1550  max_couplings_between_dofs (const DoFHandler<2,spacedim> &dof_handler)
1551  {
1552  // get these numbers by drawing pictures
1553  // and counting...
1554  // example:
1555  // | | |
1556  // --x-----x--x--X--
1557  // | | | |
1558  // | x--x--x
1559  // | | | |
1560  // --x--x--*--x--x--
1561  // | | | |
1562  // x--x--x |
1563  // | | | |
1564  // --X--x--x-----x--
1565  // | | |
1566  // x = vertices connected with center vertex *;
1567  // = total of 19
1568  // (the X vertices are connected with * if
1569  // the vertices adjacent to X are hanging
1570  // nodes)
1571  // count lines -> 28 (don't forget to count
1572  // mother and children separately!)
1573  types::global_dof_index max_couplings;
1574  switch (dof_handler.tria->max_adjacent_cells())
1575  {
1576  case 4:
1577  max_couplings=19*dof_handler.finite_elements->max_dofs_per_vertex() +
1578  28*dof_handler.finite_elements->max_dofs_per_line() +
1579  8*dof_handler.finite_elements->max_dofs_per_quad();
1580  break;
1581  case 5:
1582  max_couplings=21*dof_handler.finite_elements->max_dofs_per_vertex() +
1583  31*dof_handler.finite_elements->max_dofs_per_line() +
1584  9*dof_handler.finite_elements->max_dofs_per_quad();
1585  break;
1586  case 6:
1587  max_couplings=28*dof_handler.finite_elements->max_dofs_per_vertex() +
1588  42*dof_handler.finite_elements->max_dofs_per_line() +
1589  12*dof_handler.finite_elements->max_dofs_per_quad();
1590  break;
1591  case 7:
1592  max_couplings=30*dof_handler.finite_elements->max_dofs_per_vertex() +
1593  45*dof_handler.finite_elements->max_dofs_per_line() +
1594  13*dof_handler.finite_elements->max_dofs_per_quad();
1595  break;
1596  case 8:
1597  max_couplings=37*dof_handler.finite_elements->max_dofs_per_vertex() +
1598  56*dof_handler.finite_elements->max_dofs_per_line() +
1599  16*dof_handler.finite_elements->max_dofs_per_quad();
1600  break;
1601  default:
1602  Assert (false, ExcNotImplemented());
1603  max_couplings=0;
1604  };
1605  return std::min(max_couplings,dof_handler.n_dofs());
1606  }
1607 
1608 
1609  template <int spacedim>
1610  static
1611  unsigned int
1612  max_couplings_between_dofs (const DoFHandler<3,spacedim> &dof_handler)
1613  {
1614 //TODO:[?] Invent significantly better estimates than the ones in this function
1615  // doing the same thing here is a rather
1616  // complicated thing, compared to the 2d
1617  // case, since it is hard to draw pictures
1618  // with several refined hexahedra :-) so I
1619  // presently only give a coarse estimate
1620  // for the case that at most 8 hexes meet
1621  // at each vertex
1622  //
1623  // can anyone give better estimate here?
1624  const unsigned int max_adjacent_cells = dof_handler.tria->max_adjacent_cells();
1625 
1626  types::global_dof_index max_couplings;
1627  if (max_adjacent_cells <= 8)
1628  max_couplings=7*7*7*dof_handler.finite_elements->max_dofs_per_vertex() +
1629  7*6*7*3*dof_handler.finite_elements->max_dofs_per_line() +
1630  9*4*7*3*dof_handler.finite_elements->max_dofs_per_quad() +
1631  27*dof_handler.finite_elements->max_dofs_per_hex();
1632  else
1633  {
1634  Assert (false, ExcNotImplemented());
1635  max_couplings=0;
1636  }
1637 
1638  return std::min(max_couplings,dof_handler.n_dofs());
1639  }
1640  };
1641  }
1642  }
1643 }
1644 
1645 
1646 namespace hp
1647 {
1648  template<int dim, int spacedim>
1649  const unsigned int DoFHandler<dim,spacedim>::dimension;
1650 
1651  template<int dim, int spacedim>
1653 
1654  template<int dim, int spacedim>
1655  const unsigned int DoFHandler<dim,spacedim>::default_fe_index;
1656 
1657 
1658 
1659  template<int dim, int spacedim>
1661  :
1662  tria(&tria, typeid(*this).name()),
1663  faces (NULL)
1664  {
1666  (&tria)
1667  == 0),
1668  ExcMessage ("The given triangulation is parallel distributed but "
1669  "this class does not currently support this."));
1670 
1671  create_active_fe_table ();
1672 
1673  tria_listeners.push_back
1674  (tria.signals.pre_refinement
1675  .connect (std_cxx11::bind (&DoFHandler<dim,spacedim>::pre_refinement_action,
1676  std_cxx11::ref(*this))));
1677  tria_listeners.push_back
1678  (tria.signals.post_refinement
1679  .connect (std_cxx11::bind (&DoFHandler<dim,spacedim>::post_refinement_action,
1680  std_cxx11::ref(*this))));
1681  tria_listeners.push_back
1682  (tria.signals.create
1683  .connect (std_cxx11::bind (&DoFHandler<dim,spacedim>::post_refinement_action,
1684  std_cxx11::ref(*this))));
1685  }
1686 
1687 
1688  template<int dim, int spacedim>
1690  {
1691  // unsubscribe as a listener to refinement
1692  // of the underlying triangulation
1693  for (unsigned int i=0; i<tria_listeners.size(); ++i)
1694  tria_listeners[i].disconnect ();
1695  tria_listeners.clear ();
1696 
1697  // ...and release allocated memory
1698  clear ();
1699  }
1700 
1701 
1702  /*------------------------ Cell iterator functions ------------------------*/
1703 
1704  template <int dim, int spacedim>
1706  DoFHandler<dim, spacedim>::begin(const unsigned int level) const
1707  {
1708  return cell_iterator (*this->get_triangulation().begin(level),
1709  this);
1710  }
1711 
1712 
1713 
1714  template <int dim, int spacedim>
1716  DoFHandler<dim,spacedim>::begin_active (const unsigned int level) const
1717  {
1718  // level is checked in begin
1719  cell_iterator i = begin (level);
1720  if (i.state() != IteratorState::valid)
1721  return i;
1722  while (i->has_children())
1723  if ((++i).state() != IteratorState::valid)
1724  return i;
1725  return i;
1726  }
1727 
1728 
1729 
1730  template <int dim, int spacedim>
1733  {
1734  return cell_iterator (&this->get_triangulation(),
1735  -1,
1736  -1,
1737  this);
1738  }
1739 
1740 
1741  template <int dim, int spacedim>
1743  DoFHandler<dim,spacedim>::end (const unsigned int level) const
1744  {
1745  return (level == this->get_triangulation().n_levels()-1 ?
1746  end() :
1747  begin (level+1));
1748  }
1749 
1750 
1751  template <int dim, int spacedim>
1753  DoFHandler<dim, spacedim>::end_active (const unsigned int level) const
1754  {
1755  return (level == this->get_triangulation().n_levels()-1 ?
1757  begin_active (level+1));
1758  }
1759 
1760 
1761 
1762  template <int dim, int spacedim>
1765  {
1766  return
1768  (begin(), end());
1769  }
1770 
1771 
1772  template <int dim, int spacedim>
1775  {
1776  return
1778  (begin_active(), end());
1779  }
1780 
1781 
1782 
1783  template <int dim, int spacedim>
1786  {
1787  return
1789  (begin(level), end(level));
1790  }
1791 
1792 
1793 
1794  template <int dim, int spacedim>
1797  {
1798  return
1800  (begin_active(level), end_active(level));
1801  }
1802 
1803 
1804 
1805 
1806 //------------------------------------------------------------------
1807 
1808 
1809  template <>
1811  {
1812  Assert (finite_elements != 0, ExcNoFESelected());
1813 
1816 
1817  // search left-most cell
1818  cell = this->begin_active();
1819  while (!cell->at_boundary(0))
1820  cell = cell->neighbor(0);
1821  n += cell->get_fe().dofs_per_vertex;
1822 
1823  // same with right-most cell
1824  cell = this->begin_active();
1825  while (!cell->at_boundary(1))
1826  cell = cell->neighbor(1);
1827  n += cell->get_fe().dofs_per_vertex;
1828 
1829  return n;
1830  }
1831 
1832 
1833 
1834  template <>
1836  {
1837  Assert (finite_elements != 0, ExcNoFESelected());
1838 
1839  // check that only boundary
1840  // indicators 0 and 1 are allowed
1841  // in 1d
1842  for (FunctionMap::const_iterator i=boundary_ids.begin();
1843  i!=boundary_ids.end(); ++i)
1844  Assert ((i->first == 0) || (i->first == 1),
1845  ExcInvalidBoundaryIndicator());
1846 
1849 
1850  // search left-most cell
1851  if (boundary_ids.find (0) != boundary_ids.end())
1852  {
1853  cell = this->begin_active();
1854  while (!cell->at_boundary(0))
1855  cell = cell->neighbor(0);
1856  n += cell->get_fe().dofs_per_vertex;
1857  }
1858 
1859  // same with right-most cell
1860  if (boundary_ids.find (1) != boundary_ids.end())
1861  {
1862  cell = this->begin_active();
1863  while (!cell->at_boundary(1))
1864  cell = cell->neighbor(1);
1865  n += cell->get_fe().dofs_per_vertex;
1866  }
1867 
1868  return n;
1869  }
1870 
1871 
1872 
1873  template <>
1874  types::global_dof_index DoFHandler<1>::n_boundary_dofs (const std::set<types::boundary_id> &boundary_ids) const
1875  {
1876  Assert (finite_elements != 0, ExcNoFESelected());
1877 
1878  // check that only boundary
1879  // indicators 0 and 1 are allowed
1880  // in 1d
1881  for (std::set<types::boundary_id>::const_iterator i=boundary_ids.begin();
1882  i!=boundary_ids.end(); ++i)
1883  Assert ((*i == 0) || (*i == 1),
1884  ExcInvalidBoundaryIndicator());
1885 
1888 
1889  // search left-most cell
1890  if (boundary_ids.find (0) != boundary_ids.end())
1891  {
1892  cell = this->begin_active();
1893  while (!cell->at_boundary(0))
1894  cell = cell->neighbor(0);
1895  n += cell->get_fe().dofs_per_vertex;
1896  }
1897 
1898  // same with right-most cell
1899  if (boundary_ids.find (1) != boundary_ids.end())
1900  {
1901  cell = this->begin_active();
1902  while (!cell->at_boundary(1))
1903  cell = cell->neighbor(1);
1904  n += cell->get_fe().dofs_per_vertex;
1905  }
1906 
1907  return n;
1908  }
1909 
1910 
1911  template <>
1913  {
1914  Assert(false,ExcNotImplemented());
1915  return 0;
1916  }
1917 
1918  template <>
1920  {
1921  Assert(false,ExcNotImplemented());
1922  return 0;
1923  }
1924 
1925  template <>
1926  types::global_dof_index DoFHandler<1,2>::n_boundary_dofs (const std::set<types::boundary_id> &) const
1927  {
1928  Assert(false,ExcNotImplemented());
1929  return 0;
1930  }
1931 
1932 
1933 
1934  template <>
1936  {
1937  Assert(false,ExcNotImplemented());
1938  return 0;
1939  }
1940 
1941  template <>
1943  {
1944  Assert(false,ExcNotImplemented());
1945  return 0;
1946  }
1947 
1948  template <>
1949  types::global_dof_index DoFHandler<1,3>::n_boundary_dofs (const std::set<types::boundary_id> &) const
1950  {
1951  Assert(false,ExcNotImplemented());
1952  return 0;
1953  }
1954 
1955 
1956  template<int dim, int spacedim>
1958  {
1959  Assert (finite_elements != 0, ExcNoFESelected());
1960 
1961  std::set<types::global_dof_index> boundary_dofs;
1962  std::vector<types::global_dof_index> dofs_on_face;
1963  dofs_on_face.reserve (this->get_fe ().max_dofs_per_face());
1964 
1965  // loop over all faces to check
1966  // whether they are at a
1967  // boundary. note that we need not
1968  // take special care of single
1969  // lines in 3d (using
1970  // @p{cell->has_boundary_lines}),
1971  // since we do not support
1972  // boundaries of dimension dim-2,
1973  // and so every boundary line is
1974  // also part of a boundary face.
1975  typename HpDoFHandler<dim,spacedim>::active_cell_iterator cell = this->begin_active (),
1976  endc = this->end();
1977  for (; cell!=endc; ++cell)
1978  for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
1979  if (cell->at_boundary(f))
1980  {
1981  const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
1982  dofs_on_face.resize (dofs_per_face);
1983 
1984  cell->face(f)->get_dof_indices (dofs_on_face,
1985  cell->active_fe_index());
1986  for (unsigned int i=0; i<dofs_per_face; ++i)
1987  boundary_dofs.insert(dofs_on_face[i]);
1988  };
1989  return boundary_dofs.size();
1990  }
1991 
1992 
1993 
1994  template<int dim, int spacedim>
1997  {
1998  Assert (finite_elements != 0, ExcNoFESelected());
1999  Assert (boundary_ids.find(numbers::internal_face_boundary_id) == boundary_ids.end(),
2000  ExcInvalidBoundaryIndicator());
2001 
2002  // same as above, but with
2003  // additional checks for set of
2004  // boundary indicators
2005  std::set<types::global_dof_index> boundary_dofs;
2006  std::vector<types::global_dof_index> dofs_on_face;
2007  dofs_on_face.reserve (this->get_fe ().max_dofs_per_face());
2008 
2009  typename HpDoFHandler<dim,spacedim>::active_cell_iterator cell = this->begin_active (),
2010  endc = this->end();
2011  for (; cell!=endc; ++cell)
2012  for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
2013  if (cell->at_boundary(f) &&
2014  (boundary_ids.find(cell->face(f)->boundary_id()) !=
2015  boundary_ids.end()))
2016  {
2017  const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
2018  dofs_on_face.resize (dofs_per_face);
2019 
2020  cell->face(f)->get_dof_indices (dofs_on_face,
2021  cell->active_fe_index());
2022  for (unsigned int i=0; i<dofs_per_face; ++i)
2023  boundary_dofs.insert(dofs_on_face[i]);
2024  }
2025  return boundary_dofs.size();
2026  }
2027 
2028 
2029 
2030  template<int dim, int spacedim>
2032  DoFHandler<dim,spacedim>::n_boundary_dofs (const std::set<types::boundary_id> &boundary_ids) const
2033  {
2034  Assert (finite_elements != 0, ExcNoFESelected());
2035  Assert (boundary_ids.find (numbers::internal_face_boundary_id) == boundary_ids.end(),
2036  ExcInvalidBoundaryIndicator());
2037 
2038  // same as above, but with
2039  // additional checks for set of
2040  // boundary indicators
2041  std::set<types::global_dof_index> boundary_dofs;
2042  std::vector<types::global_dof_index> dofs_on_face;
2043  dofs_on_face.reserve (this->get_fe ().max_dofs_per_face());
2044 
2045  typename HpDoFHandler<dim,spacedim>::active_cell_iterator cell = this->begin_active (),
2046  endc = this->end();
2047  for (; cell!=endc; ++cell)
2048  for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
2049  if (cell->at_boundary(f) &&
2050  (boundary_ids.find(cell->face(f)->boundary_id()) !=
2051  boundary_ids.end()))
2052  {
2053  const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
2054  dofs_on_face.resize (dofs_per_face);
2055 
2056  cell->face(f)->get_dof_indices (dofs_on_face,
2057  cell->active_fe_index());
2058  for (unsigned int i=0; i<dofs_per_face; ++i)
2059  boundary_dofs.insert(dofs_on_face[i]);
2060  };
2061  return boundary_dofs.size();
2062  }
2063 
2064 
2065 
2066  template <>
2068  {
2069  Assert(false,ExcNotImplemented());
2070  return 0;
2071  }
2072 
2073 
2074 
2075  template <>
2077  {
2078  Assert(false,ExcNotImplemented());
2079  return 0;
2080  }
2081 
2082 
2083 
2084  template <>
2085  types::global_dof_index DoFHandler<2,3>::n_boundary_dofs (const std::set<types::boundary_id> &) const
2086  {
2087  Assert(false,ExcNotImplemented());
2088  return 0;
2089  }
2090 
2091 
2092 
2093  template<int dim, int spacedim>
2094  std::size_t
2096  {
2097  std::size_t mem = (MemoryConsumption::memory_consumption (tria) +
2098  MemoryConsumption::memory_consumption (finite_elements) +
2104  MemoryConsumption::memory_consumption (vertex_dofs_offsets) +
2105  MemoryConsumption::memory_consumption (has_children));
2106  for (unsigned int i=0; i<levels.size(); ++i)
2109 
2110  return mem;
2111  }
2112 
2113 
2114 
2115  template<int dim, int spacedim>
2116  void
2118  compute_vertex_dof_identities (std::vector<types::global_dof_index> &new_dof_indices) const
2119  {
2120  // Note: we may wish to have
2121  // something here similar to what
2122  // we do for lines and quads,
2123  // namely that we only identify
2124  // dofs for any fe towards the
2125  // most dominating one. however,
2126  // it is not clear whether this
2127  // is actually necessary for
2128  // vertices at all, I can't think
2129  // of a finite element that would
2130  // make that necessary...
2132  vertex_dof_identities (get_fe().size(),
2133  get_fe().size());
2134 
2135  // loop over all vertices and
2136  // see which one we need to
2137  // work on
2138  for (unsigned int vertex_index=0; vertex_index<get_tria().n_vertices();
2139  ++vertex_index)
2140  {
2141  const unsigned int n_active_fe_indices
2142  = ::internal::DoFAccessor::Implementation::
2143  n_active_vertex_fe_indices (*this, vertex_index);
2144  if (n_active_fe_indices > 1)
2145  {
2146  const unsigned int
2147  first_fe_index
2148  = ::internal::DoFAccessor::Implementation::
2149  nth_active_vertex_fe_index (*this, vertex_index, 0);
2150 
2151  // loop over all the
2152  // other FEs with which
2153  // we want to identify
2154  // the DoF indices of
2155  // the first FE of
2156  for (unsigned int f=1; f<n_active_fe_indices; ++f)
2157  {
2158  const unsigned int
2159  other_fe_index
2160  = ::internal::DoFAccessor::Implementation::
2161  nth_active_vertex_fe_index (*this, vertex_index, f);
2162 
2163  // make sure the
2164  // entry in the
2165  // equivalence
2166  // table exists
2167  ::internal::hp::ensure_existence_of_dof_identities<0>
2168  (get_fe()[first_fe_index],
2169  get_fe()[other_fe_index],
2170  vertex_dof_identities[first_fe_index][other_fe_index]);
2171 
2172  // then loop
2173  // through the
2174  // identities we
2175  // have. first get
2176  // the global
2177  // numbers of the
2178  // dofs we want to
2179  // identify and
2180  // make sure they
2181  // are not yet
2182  // constrained to
2183  // anything else,
2184  // except for to
2185  // each other. use
2186  // the rule that we
2187  // will always
2188  // constrain the
2189  // dof with the
2190  // higher fe
2191  // index to the
2192  // one with the
2193  // lower, to avoid
2194  // circular
2195  // reasoning.
2196  ::internal::hp::DoFIdentities &identities
2197  = *vertex_dof_identities[first_fe_index][other_fe_index];
2198  for (unsigned int i=0; i<identities.size(); ++i)
2199  {
2200  const types::global_dof_index lower_dof_index
2201  = ::internal::DoFAccessor::Implementation::
2202  get_vertex_dof_index (*this,
2203  vertex_index,
2204  first_fe_index,
2205  identities[i].first);
2206  const types::global_dof_index higher_dof_index
2207  = ::internal::DoFAccessor::Implementation::
2208  get_vertex_dof_index (*this,
2209  vertex_index,
2210  other_fe_index,
2211  identities[i].second);
2212 
2213  Assert ((new_dof_indices[higher_dof_index] ==
2215  ||
2216  (new_dof_indices[higher_dof_index] ==
2217  lower_dof_index),
2218  ExcInternalError());
2219 
2220  new_dof_indices[higher_dof_index] = lower_dof_index;
2221  }
2222  }
2223  }
2224  }
2225  }
2226 
2227 
2228  template <>
2229  void
2231  compute_line_dof_identities (std::vector<types::global_dof_index> &) const
2232  {}
2233 
2234 
2235 
2236  template <>
2237  void
2239  compute_line_dof_identities (std::vector<types::global_dof_index> &) const
2240  {}
2241 
2242  template <>
2243  void
2245  compute_line_dof_identities (std::vector<types::global_dof_index> &) const
2246  {}
2247 
2248 
2249  template<int dim, int spacedim>
2250  void
2252  compute_line_dof_identities (std::vector<types::global_dof_index> &new_dof_indices) const
2253  {
2254  // we will mark lines that we have already treated, so first save and clear
2255  // the user flags on lines and later restore them
2256  std::vector<bool> user_flags;
2257  this->get_triangulation().save_user_flags_line(user_flags);
2258  const_cast<Triangulation<dim,spacedim> &>(this->get_triangulation()).clear_user_flags_line ();
2259 
2260  // An implementation of the algorithm described in the hp paper, including
2261  // the modification mentioned later in the "complications in 3-d" subsections
2262  //
2263  // as explained there, we do something only if there are exactly 2 finite
2264  // elements associated with an object. if there is only one, then there is
2265  // nothing to do anyway, and if there are 3 or more, then we can get into
2266  // trouble. note that this only happens for lines in 3d and higher, and for
2267  // quads only in 4d and higher, so this isn't a particularly frequent case
2268  //
2269  // there is one case, however, that we would like to handle (see, for
2270  // example, the hp/crash_15 testcase): if we have FESystem(FE_Q(2),FE_DGQ(i))
2271  // elements for a bunch of values 'i', then we should be able to handle this
2272  // because we can simply unify *all* dofs, not only a some. so what we do
2273  // is to first treat all pairs of finite elements that have *identical* dofs,
2274  // and then only deal with those that are not identical of which we can
2275  // handle at most 2
2277  line_dof_identities (finite_elements->size(),
2278  finite_elements->size());
2279 
2280  for (active_cell_iterator cell=begin_active(); cell!=end(); ++cell)
2281  for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
2282  if (cell->line(l)->user_flag_set() == false)
2283  {
2284  const line_iterator line = cell->line(l);
2285  line->set_user_flag ();
2286 
2287  unsigned int unique_sets_of_dofs
2288  = line->n_active_fe_indices();
2289 
2290  // do a first loop over all sets of dofs and do identity
2291  // uniquification
2292  for (unsigned int f=0; f<line->n_active_fe_indices(); ++f)
2293  for (unsigned int g=f+1; g<line->n_active_fe_indices(); ++g)
2294  {
2295  const unsigned int fe_index_1 = line->nth_active_fe_index (f),
2296  fe_index_2 = line->nth_active_fe_index (g);
2297 
2298  if (((*finite_elements)[fe_index_1].dofs_per_line
2299  ==
2300  (*finite_elements)[fe_index_2].dofs_per_line)
2301  &&
2302  ((*finite_elements)[fe_index_1].dofs_per_line > 0))
2303  {
2304  internal::hp::ensure_existence_of_dof_identities<1>
2305  ((*finite_elements)[fe_index_1],
2306  (*finite_elements)[fe_index_2],
2307  line_dof_identities[fe_index_1][fe_index_2]);
2308  // see if these sets of dofs are identical. the first
2309  // condition for this is that indeed there are n identities
2310  if (line_dof_identities[fe_index_1][fe_index_2]->size()
2311  ==
2312  (*finite_elements)[fe_index_1].dofs_per_line)
2313  {
2314  unsigned int i=0;
2315  for (; i<(*finite_elements)[fe_index_1].dofs_per_line; ++i)
2316  if (((*(line_dof_identities[fe_index_1][fe_index_2]))[i].first != i)
2317  &&
2318  ((*(line_dof_identities[fe_index_1][fe_index_2]))[i].second != i))
2319  // not an identity
2320  break;
2321 
2322  if (i == (*finite_elements)[fe_index_1].dofs_per_line)
2323  {
2324  // The line dofs (i.e., the ones interior to a line) of these two finite elements are identical.
2325  // Note that there could be situations when one element still dominates another, e.g.:
2326  // FE_Q(2) x FE_Nothing(dominate) vs
2327  // FE_Q(2) x FE_Q(1)
2328 
2329  --unique_sets_of_dofs;
2330 
2331  for (unsigned int j=0; j<(*finite_elements)[fe_index_1].dofs_per_line; ++j)
2332  {
2333  const types::global_dof_index master_dof_index
2334  = line->dof_index (j, fe_index_1);
2335  const types::global_dof_index slave_dof_index
2336  = line->dof_index (j, fe_index_2);
2337 
2338  // if master dof was already constrained,
2339  // constrain to that one, otherwise constrain
2340  // slave to master
2341  if (new_dof_indices[master_dof_index] !=
2343  {
2344  Assert (new_dof_indices[new_dof_indices[master_dof_index]] ==
2346  ExcInternalError());
2347 
2348  new_dof_indices[slave_dof_index]
2349  = new_dof_indices[master_dof_index];
2350  }
2351  else
2352  {
2353  Assert ((new_dof_indices[master_dof_index] ==
2355  ||
2356  (new_dof_indices[slave_dof_index] ==
2357  master_dof_index),
2358  ExcInternalError());
2359 
2360  new_dof_indices[slave_dof_index] = master_dof_index;
2361  }
2362  }
2363  }
2364  }
2365  }
2366  }
2367 
2368  // if at this point, there is only one unique set of dofs left, then
2369  // we have taken care of everything above. if there are two, then we
2370  // need to deal with them here. if there are more, then we punt, as
2371  // described in the paper (and mentioned above)
2372 //TODO: The check for 'dim==2' was inserted by intuition. It fixes
2373 // the previous problems with @ref step_27 "step-27" in 3D. But an explanation
2374 // for this is still required, and what we do here is not what we
2375 // describe in the paper!.
2376  if ((unique_sets_of_dofs == 2) && (dim == 2))
2377  {
2378  // find out which is the most dominating finite element of the
2379  // ones that are used on this line
2380  const unsigned int most_dominating_fe_index
2381  = internal::hp::get_most_dominating_fe_index<dim,spacedim> (line);
2382 
2383  // if we found the most dominating element, then use this to eliminate some of
2384  // the degrees of freedom by identification. otherwise, the code that computes
2385  // hanging node constraints will have to deal with it by computing
2386  // appropriate constraints along this face/edge
2387  if (most_dominating_fe_index != numbers::invalid_unsigned_int)
2388  {
2389  const unsigned int n_active_fe_indices
2390  = line->n_active_fe_indices ();
2391 
2392  // loop over the indices of all the finite elements that are not
2393  // dominating, and identify their dofs to the most dominating
2394  // one
2395  for (unsigned int f=0; f<n_active_fe_indices; ++f)
2396  if (line->nth_active_fe_index (f) !=
2397  most_dominating_fe_index)
2398  {
2399  const unsigned int
2400  other_fe_index = line->nth_active_fe_index (f);
2401 
2402  internal::hp::ensure_existence_of_dof_identities<1>
2403  ((*finite_elements)[most_dominating_fe_index],
2404  (*finite_elements)[other_fe_index],
2405  line_dof_identities[most_dominating_fe_index][other_fe_index]);
2406 
2407  internal::hp::DoFIdentities &identities
2408  = *line_dof_identities[most_dominating_fe_index][other_fe_index];
2409  for (unsigned int i=0; i<identities.size(); ++i)
2410  {
2411  const types::global_dof_index master_dof_index
2412  = line->dof_index (identities[i].first, most_dominating_fe_index);
2413  const types::global_dof_index slave_dof_index
2414  = line->dof_index (identities[i].second, other_fe_index);
2415 
2416  Assert ((new_dof_indices[master_dof_index] ==
2418  ||
2419  (new_dof_indices[slave_dof_index] ==
2420  master_dof_index),
2421  ExcInternalError());
2422 
2423  new_dof_indices[slave_dof_index] = master_dof_index;
2424  }
2425  }
2426  }
2427  }
2428  }
2429 
2430  // finally restore the user flags
2431  const_cast<Triangulation<dim,spacedim> &>(this->get_triangulation())
2432  .load_user_flags_line(user_flags);
2433  }
2434 
2435 
2436 
2437  template <int dim, int spacedim>
2438  void
2440  compute_quad_dof_identities (std::vector<types::global_dof_index> &) const
2441  {
2442  // this function should only be called for dim<3 where there are
2443  // no quad dof identies. for dim>=3, the specialization below should
2444  // take care of it
2445  Assert (dim < 3, ExcInternalError());
2446  }
2447 
2448 
2449  template <>
2450  void
2452  compute_quad_dof_identities (std::vector<types::global_dof_index> &new_dof_indices) const
2453  {
2454  const int dim = 3;
2455  const int spacedim = 3;
2456 
2457  // we will mark quads that we
2458  // have already treated, so first
2459  // save and clear the user flags
2460  // on quads and later restore
2461  // them
2462  std::vector<bool> user_flags;
2463  this->get_triangulation().save_user_flags_quad(user_flags);
2464  const_cast<Triangulation<dim,spacedim> &>(this->get_triangulation()).clear_user_flags_quad ();
2465 
2466  // An implementation of the
2467  // algorithm described in the hp
2468  // paper, including the
2469  // modification mentioned later
2470  // in the "complications in 3-d"
2471  // subsections
2472  //
2473  // as explained there, we do
2474  // something only if there are
2475  // exactly 2 finite elements
2476  // associated with an object. if
2477  // there is only one, then there
2478  // is nothing to do anyway, and
2479  // if there are 3 or more, then
2480  // we can get into trouble. note
2481  // that this only happens for
2482  // lines in 3d and higher, and
2483  // for quads only in 4d and
2484  // higher, so this isn't a
2485  // particularly frequent case
2487  quad_dof_identities (finite_elements->size(),
2488  finite_elements->size());
2489 
2490  for (active_cell_iterator cell=begin_active(); cell!=end(); ++cell)
2491  for (unsigned int q=0; q<GeometryInfo<dim>::quads_per_cell; ++q)
2492  if ((cell->quad(q)->user_flag_set() == false)
2493  &&
2494  (cell->quad(q)->n_active_fe_indices() == 2))
2495  {
2496  const quad_iterator quad = cell->quad(q);
2497  quad->set_user_flag ();
2498 
2499  // find out which is the
2500  // most dominating finite
2501  // element of the ones that
2502  // are used on this quad
2503  const unsigned int most_dominating_fe_index
2504  = internal::hp::get_most_dominating_fe_index<dim,spacedim> (quad);
2505 
2506  // if we found the most dominating element, then use this to eliminate some of
2507  // the degrees of freedom by identification. otherwise, the code that computes
2508  // hanging node constraints will have to deal with it by computing
2509  // appropriate constraints along this face/edge
2510  if (most_dominating_fe_index != numbers::invalid_unsigned_int)
2511  {
2512  const unsigned int n_active_fe_indices
2513  = quad->n_active_fe_indices ();
2514 
2515  // loop over the indices of
2516  // all the finite elements
2517  // that are not dominating,
2518  // and identify their dofs
2519  // to the most dominating
2520  // one
2521  for (unsigned int f=0; f<n_active_fe_indices; ++f)
2522  if (quad->nth_active_fe_index (f) !=
2523  most_dominating_fe_index)
2524  {
2525  const unsigned int
2526  other_fe_index = quad->nth_active_fe_index (f);
2527 
2528  internal::hp::ensure_existence_of_dof_identities<2>
2529  ((*finite_elements)[most_dominating_fe_index],
2530  (*finite_elements)[other_fe_index],
2531  quad_dof_identities[most_dominating_fe_index][other_fe_index]);
2532 
2533  internal::hp::DoFIdentities &identities
2534  = *quad_dof_identities[most_dominating_fe_index][other_fe_index];
2535  for (unsigned int i=0; i<identities.size(); ++i)
2536  {
2537  const types::global_dof_index master_dof_index
2538  = quad->dof_index (identities[i].first, most_dominating_fe_index);
2539  const types::global_dof_index slave_dof_index
2540  = quad->dof_index (identities[i].second, other_fe_index);
2541 
2542  Assert ((new_dof_indices[master_dof_index] ==
2544  ||
2545  (new_dof_indices[slave_dof_index] ==
2546  master_dof_index),
2547  ExcInternalError());
2548 
2549  new_dof_indices[slave_dof_index] = master_dof_index;
2550  }
2551  }
2552  }
2553  }
2554 
2555  // finally restore the user flags
2556  const_cast<Triangulation<dim,spacedim> &>(this->get_triangulation())
2557  .load_user_flags_quad(user_flags);
2558  }
2559 
2560 
2561 
2562  template <int dim, int spacedim>
2563  void DoFHandler<dim,spacedim>::set_active_fe_indices (const std::vector<unsigned int> &active_fe_indices)
2564  {
2565  Assert(active_fe_indices.size()==get_tria().n_active_cells(),
2566  ExcDimensionMismatch(active_fe_indices.size(), get_tria().n_active_cells()));
2567 
2568  create_active_fe_table ();
2569  // we could set the values directly, since
2570  // they are stored as protected data of
2571  // this object, but for simplicity we use
2572  // the cell-wise access. this way we also
2573  // have to pass some debug-mode tests which
2574  // we would have to duplicate ourselves
2575  // otherwise
2577  endc=end();
2578  for (unsigned int i=0; cell!=endc; ++cell, ++i)
2579  cell->set_active_fe_index(active_fe_indices[i]);
2580  }
2581 
2582 
2583 
2584  template <int dim, int spacedim>
2585  void DoFHandler<dim,spacedim>::get_active_fe_indices (std::vector<unsigned int> &active_fe_indices) const
2586  {
2587  active_fe_indices.resize(get_tria().n_active_cells());
2588 
2589  // we could try to extract the values directly, since
2590  // they are stored as protected data of
2591  // this object, but for simplicity we use
2592  // the cell-wise access.
2594  endc=end();
2595  for (unsigned int i=0; cell!=endc; ++cell, ++i)
2596  active_fe_indices[i]=cell->active_fe_index();
2597  }
2598 
2599 
2600 
2601  template<int dim, int spacedim>
2603  {
2604  Assert (tria->n_levels() > 0, ExcInvalidTriangulation());
2605 
2606  finite_elements = &ff;
2607 
2608  // This call ensures that the
2609  // active_fe_indices vectors are
2610  // initialized correctly.
2611  create_active_fe_table ();
2612 
2613  // up front make sure that the fe
2614  // collection is large enough to
2615  // cover all fe indices presently
2616  // in use on the mesh
2617  for (active_cell_iterator cell = begin_active(); cell != end(); ++cell)
2618  Assert (cell->active_fe_index() < finite_elements->size(),
2619  ExcInvalidFEIndex (cell->active_fe_index(),
2620  finite_elements->size()));
2621 
2622 
2623  // then allocate space for all
2624  // the other tables
2626 
2627  // Clear user flags because we will
2628  // need them. But first we save
2629  // them and make sure that we
2630  // restore them later such that at
2631  // the end of this function the
2632  // Triangulation will be in the
2633  // same state as it was at the
2634  // beginning of this function.
2635  std::vector<bool> user_flags;
2636  tria->save_user_flags(user_flags);
2637  const_cast<Triangulation<dim,spacedim> &>(*tria).clear_user_flags ();
2638 
2639 
2641 
2642  // Step 1: distribute DoFs on all
2643  // active entities
2644  {
2645  types::global_dof_index next_free_dof = 0;
2647  endc = end();
2648 
2649  for (; cell != endc; ++cell)
2650  next_free_dof
2651  = ::internal::hp::DoFHandler::Implementation::distribute_dofs_on_cell<spacedim> (cell,
2652  next_free_dof);
2653 
2654  number_cache.n_global_dofs = next_free_dof;
2655  }
2656 
2657 
2659 
2660  // Step 2: identify certain dofs
2661  // if the finite element tells us
2662  // that they should have the same
2663  // value. only pertinent for
2664  // faces and other
2665  // lower-dimensional objects
2666  // where elements come together
2667  std::vector<types::global_dof_index>
2668  constrained_indices (number_cache.n_global_dofs, numbers::invalid_dof_index);
2669  compute_vertex_dof_identities (constrained_indices);
2670  compute_line_dof_identities (constrained_indices);
2671  compute_quad_dof_identities (constrained_indices);
2672 
2673  // loop over all dofs and assign
2674  // new numbers to those which are
2675  // not constrained
2676  std::vector<types::global_dof_index>
2678  types::global_dof_index next_free_dof = 0;
2680  if (constrained_indices[i] == numbers::invalid_dof_index)
2681  {
2682  new_dof_indices[i] = next_free_dof;
2683  ++next_free_dof;
2684  }
2685 
2686  // then loop over all those that
2687  // are constrained and record the
2688  // new dof number for those:
2690  if (constrained_indices[i] != numbers::invalid_dof_index)
2691  {
2692  Assert (new_dof_indices[constrained_indices[i]] !=
2694  ExcInternalError());
2695 
2696  new_dof_indices[i] = new_dof_indices[constrained_indices[i]];
2697  }
2698 
2700  {
2701  Assert (new_dof_indices[i] != numbers::invalid_dof_index,
2702  ExcInternalError());
2703  Assert (new_dof_indices[i] < next_free_dof,
2704  ExcInternalError());
2705  }
2706 
2707  // finally, do the renumbering
2708  // and set the number of actually
2709  // used dof indices
2710  renumber_dofs_internal (new_dof_indices, ::internal::int2type<dim>());
2711 
2712  // now set the elements of the
2713  // number cache appropriately
2714  number_cache.n_global_dofs = next_free_dof;
2716 
2717  if (dynamic_cast<const parallel::shared::Triangulation< dim, spacedim >*>
2718  (&this->get_triangulation())
2719  == 0)
2720  {
2725  Assert (number_cache.n_global_dofs < std::numeric_limits<unsigned int>::max (),
2726  ExcMessage ("Global number of degrees of freedom is too large."));
2728  = std::vector<types::global_dof_index> (1,
2730  }
2731  else
2732  {
2733  AssertThrow(false, ExcNotImplemented() );
2734  //number_cache.locally_owned_dofs = ::DoFTools::locally_owned_dofs_with_subdomain(this,tria->locally_owned_subdomain() );
2735  //TODO: update n_locally_owned_dofs_per_processor as well
2736  }
2737 
2739  = std::vector<IndexSet> (1,
2741 
2742  // update the cache used for cell dof indices and compress the data on the levels. do
2743  // the latter on separate tasks to gain parallelism, starting with the highest
2744  // level (there is most to do there, so start it first)
2745  for (active_cell_iterator cell = begin_active();
2746  cell != end(); ++cell)
2747  cell->update_cell_dof_indices_cache ();
2748 
2749  {
2751  for (int level=levels.size()-1; level>=0; --level)
2752  tg += Threads::new_task (&::internal::hp::DoFLevel::compress_data<dim,spacedim>,
2753  *levels[level], *finite_elements);
2754  tg.join_all ();
2755  }
2756 
2757  // finally restore the user flags
2758  const_cast<Triangulation<dim,spacedim> &>(*tria).load_user_flags(user_flags);
2759  }
2760 
2761 
2762 
2763  template<int dim, int spacedim>
2765  {
2766  // release lock to old fe
2767  finite_elements = 0;
2768 
2769  // release memory
2770  clear_space ();
2771  }
2772 
2773 
2774 
2775  template<int dim, int spacedim>
2776  void DoFHandler<dim,spacedim>::renumber_dofs (const std::vector<types::global_dof_index> &new_numbers)
2777  {
2778  Assert (new_numbers.size() == n_dofs(), ExcRenumberingIncomplete());
2779 #ifdef DEBUG
2780  // assert that the new indices are
2781  // consecutively numbered
2782  if (true)
2783  {
2784  std::vector<types::global_dof_index> tmp(new_numbers);
2785  std::sort (tmp.begin(), tmp.end());
2786  std::vector<types::global_dof_index>::const_iterator p = tmp.begin();
2788  for (; p!=tmp.end(); ++p, ++i)
2789  Assert (*p == i, ExcNewNumbersNotConsecutive(i));
2790  }
2791 #endif
2792 
2793  // uncompress the internal storage scheme of dofs on cells
2794  // so that we can access dofs in turns. uncompress in parallel, starting
2795  // with the most expensive levels (the highest ones)
2796  {
2798  for (int level=levels.size()-1; level>=0; --level)
2799  tg += Threads::new_task (&::internal::hp::DoFLevel::uncompress_data<dim,spacedim>,
2800  *levels[level], *finite_elements);
2801  tg.join_all ();
2802  }
2803 
2804  // do the renumbering
2805  renumber_dofs_internal (new_numbers, ::internal::int2type<dim>());
2806 
2807  // update the cache used for cell dof indices
2808  for (active_cell_iterator cell = begin_active();
2809  cell != end(); ++cell)
2810  cell->update_cell_dof_indices_cache ();
2811 
2812  // now re-compress the dof indices
2813  {
2815  for (int level=levels.size()-1; level>=0; --level)
2816  tg += Threads::new_task (&::internal::hp::DoFLevel::compress_data<dim,spacedim>,
2817  *levels[level], *finite_elements);
2818  tg.join_all ();
2819  }
2820  }
2821 
2822 
2823 
2824  template<int dim, int spacedim>
2825  void
2827  renumber_dofs_internal (const std::vector<types::global_dof_index> &new_numbers,
2829  {
2830  Assert (new_numbers.size() == n_dofs(), ExcRenumberingIncomplete());
2831 
2832  for (unsigned int vertex_index=0; vertex_index<get_tria().n_vertices();
2833  ++vertex_index)
2834  {
2835  const unsigned int n_active_fe_indices
2836  = ::internal::DoFAccessor::Implementation::
2837  n_active_vertex_fe_indices (*this, vertex_index);
2838 
2839  for (unsigned int f=0; f<n_active_fe_indices; ++f)
2840  {
2841  const unsigned int fe_index
2842  = ::internal::DoFAccessor::Implementation::
2843  nth_active_vertex_fe_index (*this, vertex_index, f);
2844 
2845  for (unsigned int d=0; d<(*finite_elements)[fe_index].dofs_per_vertex; ++d)
2846  {
2847  const types::global_dof_index vertex_dof_index
2848  = ::internal::DoFAccessor::Implementation::
2849  get_vertex_dof_index(*this,
2850  vertex_index,
2851  fe_index,
2852  d);
2853  ::internal::DoFAccessor::Implementation::
2854  set_vertex_dof_index (*this,
2855  vertex_index,
2856  fe_index,
2857  d,
2858  new_numbers[vertex_dof_index]);
2859  }
2860  }
2861  }
2862  }
2863 
2864 
2865 
2866  template<int dim, int spacedim>
2867  void
2869  renumber_dofs_internal (const std::vector<types::global_dof_index> &new_numbers,
2871  {
2872  Assert (new_numbers.size() == n_dofs(), ExcRenumberingIncomplete());
2873 
2874  renumber_dofs_internal (new_numbers, internal::int2type<0>());
2875 
2876  // save user flags on lines so we
2877  // can use them to mark lines
2878  // we've already treated
2879  std::vector<bool> saved_line_user_flags;
2880  const_cast<::Triangulation<dim,spacedim>&>(*tria)
2881  .save_user_flags_line (saved_line_user_flags);
2882  const_cast<::Triangulation<dim,spacedim>&>(*tria)
2884 
2885  for (active_cell_iterator cell = begin_active(); cell!=end(); ++cell)
2886  for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_cell; ++l)
2887  if (cell->line(l)->user_flag_set() == false)
2888  {
2889  const line_iterator line = cell->line(l);
2890  line->set_user_flag();
2891 
2892  const unsigned int n_active_fe_indices
2893  = line->n_active_fe_indices ();
2894 
2895  for (unsigned int f=0; f<n_active_fe_indices; ++f)
2896  {
2897  const unsigned int fe_index
2898  = line->nth_active_fe_index (f);
2899 
2900  for (unsigned int d=0; d<(*finite_elements)[fe_index].dofs_per_line; ++d)
2901  line->set_dof_index (d,
2902  new_numbers[line->dof_index(d,fe_index)],
2903  fe_index);
2904  }
2905  }
2906 
2907  // at the end, restore the user
2908  // flags for the lines
2909  const_cast<::Triangulation<dim,spacedim>&>(*tria)
2910  .load_user_flags_line (saved_line_user_flags);
2911  }
2912 
2913 
2914 
2915 //TODO: Merge the following three functions -- they are identical
2916  template<>
2917  void
2919  renumber_dofs_internal (const std::vector<types::global_dof_index> &new_numbers,
2921  {
2922  const unsigned int dim = 2;
2923  const unsigned int spacedim = 2;
2924 
2925  Assert (new_numbers.size() == n_dofs(), ExcRenumberingIncomplete());
2926 
2927  renumber_dofs_internal (new_numbers, internal::int2type<1>());
2928 
2929  // save user flags on quads so we
2930  // can use them to mark quads
2931  // we've already treated
2932  std::vector<bool> saved_quad_user_flags;
2933  const_cast<::Triangulation<dim,spacedim>&>(*tria)
2934  .save_user_flags_quad (saved_quad_user_flags);
2935  const_cast<::Triangulation<dim,spacedim>&>(*tria)
2937 
2938  for (active_cell_iterator cell = begin_active(); cell!=end(); ++cell)
2939  for (unsigned int q=0; q<GeometryInfo<dim>::quads_per_cell; ++q)
2940  if (cell->quad(q)->user_flag_set() == false)
2941  {
2942  const quad_iterator quad = cell->quad(q);
2943  quad->set_user_flag();
2944 
2945  const unsigned int n_active_fe_indices
2946  = quad->n_active_fe_indices ();
2947 
2948  for (unsigned int f=0; f<n_active_fe_indices; ++f)
2949  {
2950  const unsigned int fe_index
2951  = quad->nth_active_fe_index (f);
2952 
2953  for (unsigned int d=0; d<(*finite_elements)[fe_index].dofs_per_quad; ++d)
2954  quad->set_dof_index (d,
2955  new_numbers[quad->dof_index(d,fe_index)],
2956  fe_index);
2957  }
2958  }
2959 
2960  // at the end, restore the user
2961  // flags for the quads
2962  const_cast<::Triangulation<dim,spacedim>&>(*tria)
2963  .load_user_flags_quad (saved_quad_user_flags);
2964  }
2965 
2966 
2967 
2968  template<>
2969  void
2971  renumber_dofs_internal (const std::vector<types::global_dof_index> &new_numbers,
2973  {
2974  const unsigned int dim = 2;
2975  const unsigned int spacedim = 3;
2976 
2977  Assert (new_numbers.size() == n_dofs(), ExcRenumberingIncomplete());
2978 
2979  renumber_dofs_internal (new_numbers, internal::int2type<1>());
2980 
2981  // save user flags on quads so we
2982  // can use them to mark quads
2983  // we've already treated
2984  std::vector<bool> saved_quad_user_flags;
2985  const_cast<::Triangulation<dim,spacedim>&>(*tria)
2986  .save_user_flags_quad (saved_quad_user_flags);
2987  const_cast<::Triangulation<dim,spacedim>&>(*tria)
2989 
2990  for (active_cell_iterator cell = begin_active(); cell!=end(); ++cell)
2991  for (unsigned int q=0; q<GeometryInfo<dim>::quads_per_cell; ++q)
2992  if (cell->quad(q)->user_flag_set() == false)
2993  {
2994  const quad_iterator quad = cell->quad(q);
2995  quad->set_user_flag();
2996 
2997  const unsigned int n_active_fe_indices
2998  = quad->n_active_fe_indices ();
2999 
3000  for (unsigned int f=0; f<n_active_fe_indices; ++f)
3001  {
3002  const unsigned int fe_index
3003  = quad->nth_active_fe_index (f);
3004 
3005  for (unsigned int d=0; d<(*finite_elements)[fe_index].dofs_per_quad; ++d)
3006  quad->set_dof_index (d,
3007  new_numbers[quad->dof_index(d,fe_index)],
3008  fe_index);
3009  }
3010  }
3011 
3012  // at the end, restore the user
3013  // flags for the quads
3014  const_cast<::Triangulation<dim,spacedim>&>(*tria)
3015  .load_user_flags_quad (saved_quad_user_flags);
3016  }
3017 
3018 
3019  template<>
3020  void
3022  renumber_dofs_internal (const std::vector<types::global_dof_index> &new_numbers,
3024  {
3025  const unsigned int dim = 3;
3026  const unsigned int spacedim = 3;
3027 
3028  Assert (new_numbers.size() == n_dofs(), ExcRenumberingIncomplete());
3029 
3030  renumber_dofs_internal (new_numbers, internal::int2type<1>());
3031 
3032  // save user flags on quads so we
3033  // can use them to mark quads
3034  // we've already treated
3035  std::vector<bool> saved_quad_user_flags;
3036  const_cast<::Triangulation<dim,spacedim>&>(*tria)
3037  .save_user_flags_quad (saved_quad_user_flags);
3038  const_cast<::Triangulation<dim,spacedim>&>(*tria)
3040 
3041  for (active_cell_iterator cell = begin_active(); cell!=end(); ++cell)
3042  for (unsigned int q=0; q<GeometryInfo<dim>::quads_per_cell; ++q)
3043  if (cell->quad(q)->user_flag_set() == false)
3044  {
3045  const quad_iterator quad = cell->quad(q);
3046  quad->set_user_flag();
3047 
3048  const unsigned int n_active_fe_indices
3049  = quad->n_active_fe_indices ();
3050 
3051  for (unsigned int f=0; f<n_active_fe_indices; ++f)
3052  {
3053  const unsigned int fe_index
3054  = quad->nth_active_fe_index (f);
3055 
3056  for (unsigned int d=0; d<(*finite_elements)[fe_index].dofs_per_quad; ++d)
3057  quad->set_dof_index (d,
3058  new_numbers[quad->dof_index(d,fe_index)],
3059  fe_index);
3060  }
3061  }
3062 
3063  // at the end, restore the user
3064  // flags for the quads
3065  const_cast<::Triangulation<dim,spacedim>&>(*tria)
3066  .load_user_flags_quad (saved_quad_user_flags);
3067  }
3068 
3069 
3070  template<>
3071  void
3073  renumber_dofs_internal (const std::vector<types::global_dof_index> &new_numbers,
3075  {
3076  const unsigned int dim = 3;
3077  const unsigned int spacedim = 3;
3078 
3079  Assert (new_numbers.size() == n_dofs(), ExcRenumberingIncomplete());
3080 
3081  renumber_dofs_internal (new_numbers, internal::int2type<2>());
3082 
3083  // save user flags on hexes so we
3084  // can use them to mark hexes
3085  // we've already treated
3086  std::vector<bool> saved_hex_user_flags;
3087  const_cast<::Triangulation<dim,spacedim>&>(*tria)
3088  .save_user_flags_hex (saved_hex_user_flags);
3089  const_cast<::Triangulation<dim,spacedim>&>(*tria)
3091 
3092  // we're in 3d, so hexes are also
3093  // cells. stick with the same
3094  // kind of notation as in the
3095  // previous functions, though
3096  for (active_cell_iterator cell = begin_active(); cell!=end(); ++cell)
3097  if (cell->user_flag_set() == false)
3098  {
3099  const hex_iterator hex = cell;
3100  hex->set_user_flag();
3101 
3102  const unsigned int n_active_fe_indices
3103  = hex->n_active_fe_indices ();
3104 
3105  for (unsigned int f=0; f<n_active_fe_indices; ++f)
3106  {
3107  const unsigned int fe_index
3108  = hex->nth_active_fe_index (f);
3109 
3110  for (unsigned int d=0; d<(*finite_elements)[fe_index].dofs_per_hex; ++d)
3111  hex->set_dof_index (d,
3112  new_numbers[hex->dof_index(d,fe_index)],
3113  fe_index);
3114  }
3115  }
3116 
3117  // at the end, restore the user
3118  // flags for the hexs
3119  const_cast<::Triangulation<dim,spacedim>&>(*tria)
3120  .load_user_flags_hex (saved_hex_user_flags);
3121  }
3122 
3123 
3124 
3125  template <int dim, int spacedim>
3126  unsigned int
3128  {
3129  Assert (finite_elements != 0, ExcNoFESelected());
3130  return ::internal::hp::DoFHandler::Implementation::max_couplings_between_dofs (*this);
3131  }
3132 
3133 
3134 
3135  template <int dim, int spacedim>
3136  unsigned int
3138  {
3139  Assert (finite_elements != 0, ExcNoFESelected());
3140 
3141  switch (dim)
3142  {
3143  case 1:
3144  return finite_elements->max_dofs_per_vertex();
3145  case 2:
3146  return (3*finite_elements->max_dofs_per_vertex()
3147  +
3148  2*finite_elements->max_dofs_per_line());
3149  case 3:
3150  // we need to take refinement of
3151  // one boundary face into consideration
3152  // here; in fact, this function returns
3153  // what #max_coupling_between_dofs<2>
3154  // returns
3155  //
3156  // we assume here, that only four faces
3157  // meet at the boundary; this assumption
3158  // is not justified and needs to be
3159  // fixed some time. fortunately, omitting
3160  // it for now does no harm since the
3161  // matrix will cry foul if its requirements
3162  // are not satisfied
3163  return (19*finite_elements->max_dofs_per_vertex() +
3164  28*finite_elements->max_dofs_per_line() +
3165  8*finite_elements->max_dofs_per_quad());
3166  default:
3167  Assert (false, ExcNotImplemented());
3168  return 0;
3169  }
3170  }
3171 
3172 
3173 
3174  template<int dim, int spacedim>
3176  {
3177  // Create sufficiently many
3178  // hp::DoFLevels.
3179  while (levels.size () < tria->n_levels ())
3180  levels.push_back (new ::internal::hp::DoFLevel);
3181 
3182  // then make sure that on each
3183  // level we have the appropriate
3184  // size of active_fe_indices;
3185  // preset them to zero, i.e. the
3186  // default FE
3187  for (unsigned int level=0; level<levels.size(); ++level)
3188  {
3189  if (levels[level]->active_fe_indices.size () == 0)
3190  levels[level]->active_fe_indices.resize (tria->n_raw_cells(level),
3191  0);
3192  else
3193  {
3194  // Either the
3195  // active_fe_indices have
3196  // size zero because they
3197  // were just created, or
3198  // the correct
3199  // size. Other sizes
3200  // indicate that
3201  // something went wrong.
3202  Assert (levels[level]->active_fe_indices.size () ==
3203  tria->n_raw_cells(level),
3204  ExcInternalError ());
3205  }
3206  }
3207  }
3208 
3209 
3210  template <int dim, int spacedim>
3212  {
3213  create_active_fe_table ();
3214 
3215  // Remember if the cells already have
3216  // children. That will make the transfer
3217  // of the active_fe_index to the finer
3218  // levels easier.
3219  Assert (has_children.size () == 0, ExcInternalError ());
3220  for (unsigned int i=0; i<levels.size(); ++i)
3221  {
3222  const unsigned int cells_on_level = tria->n_raw_cells(i);
3223  std::vector<bool> *has_children_level =
3224  new std::vector<bool> (cells_on_level);
3225 
3226  // Check for each cell, if it has children. in 1d,
3227  // we don't store refinement cases, so use the 'children'
3228  // vector instead
3229  if (dim == 1)
3230  std::transform (tria->levels[i]->cells.children.begin (),
3231  tria->levels[i]->cells.children.end (),
3232  has_children_level->begin (),
3233  std::bind2nd (std::not_equal_to<int>(), -1));
3234  else
3235  std::transform (tria->levels[i]->cells.refinement_cases.begin (),
3236  tria->levels[i]->cells.refinement_cases.end (),
3237  has_children_level->begin (),
3238  std::bind2nd (std::not_equal_to<unsigned char>(),
3239  static_cast<unsigned char>(RefinementCase<dim>::no_refinement)));
3240 
3241  has_children.push_back (has_children_level);
3242  }
3243  }
3244 
3245 
3246 
3247  template<int dim, int spacedim>
3248  void
3250  {
3251  Assert (has_children.size () == levels.size (), ExcInternalError ());
3252 
3253  // Normally only one level is added, but if this Triangulation
3254  // is created by copy_triangulation, it can be more than one level.
3255  while (levels.size () < tria->n_levels ())
3256  levels.push_back (new ::internal::hp::DoFLevel);
3257 
3258  // Coarsening can lead to the loss
3259  // of levels. Hence remove them.
3260  while (levels.size () > tria->n_levels ())
3261  {
3262  delete levels[levels.size ()-1];
3263  levels.pop_back ();
3264  }
3265 
3266  Assert(levels.size () == tria->n_levels (), ExcInternalError());
3267 
3268  // Resize active_fe_indices
3269  // vectors. use zero indicator to
3270  // extend
3271  for (unsigned int i=0; i<levels.size(); ++i)
3272  levels[i]->active_fe_indices.resize (tria->n_raw_cells(i), 0);
3273 
3274  // if a finite element collection
3275  // has already been set, then
3276  // actually try to set
3277  // active_fe_indices for child
3278  // cells of refined cells to the
3279  // active_fe_index of the mother
3280  // cell. if no finite element
3281  // collection has been assigned
3282  // yet, then all indicators are
3283  // zero anyway, and there is no
3284  // point trying to set anything
3285  // (besides, we would trip over
3286  // an assertion in
3287  // set_active_fe_index)
3288  if (finite_elements != 0)
3289  {
3290  cell_iterator cell = begin(),
3291  endc = end ();
3292  for (; cell != endc; ++cell)
3293  {
3294  // Look if the cell got children during refinement by
3295  // checking whether it has children now but didn't have
3296  // children before refinement (the has_children array is
3297  // set in pre-refinement action)
3298  //
3299  // Note: Although one level is added to
3300  // the DoFHandler levels, when the
3301  // triangulation got one, for the buffer
3302  // has_children this new level is not
3303  // required, because the cells on the
3304  // finest level never have children. Hence
3305  // cell->has_children () will always return
3306  // false on that level, which would cause
3307  // shortcut evaluation of the following
3308  // expression. Thus an index error in
3309  // has_children should never occur.
3310  if (cell->has_children () &&
3311  !(*has_children [cell->level ()])[cell->index ()])
3312  {
3313  // Set active_fe_index in children to the same value
3314  // as in the parent cell. we can't access the
3315  // active_fe_index in the parent cell any more through
3316  // cell->active_fe_index() since that function is not
3317  // allowed for inactive cells, but we can access this
3318  // information from the DoFLevels directly
3319  for (unsigned int i = 0; i < cell->n_children(); ++i)
3320  cell->child (i)->set_active_fe_index
3321  (levels[cell->level()]->active_fe_index (cell->index()));
3322  }
3323  }
3324  }
3325 
3326  // Free buffer objects
3327  std::vector<std::vector<bool> *>::iterator children_level;
3328  for (children_level = has_children.begin ();
3329  children_level != has_children.end ();
3330  ++children_level)
3331  delete (*children_level);
3332  has_children.clear ();
3333  }
3334 
3335 
3336  template <int dim, int spacedim>
3337  template <int structdim>
3339  DoFHandler<dim,spacedim>::get_dof_index (const unsigned int,
3340  const unsigned int,
3341  const unsigned int,
3342  const unsigned int) const
3343  {
3344  Assert (false, ExcNotImplemented());
3346  }
3347 
3348 
3349  template <int dim, int spacedim>
3350  template <int structdim>
3351  void
3352  DoFHandler<dim,spacedim>::set_dof_index (const unsigned int,
3353  const unsigned int,
3354  const unsigned int,
3355  const unsigned int,
3356  const types::global_dof_index) const
3357  {
3358  Assert (false, ExcNotImplemented());
3359  }
3360 
3361 
3362  template<int dim, int spacedim>
3364  {
3365  for (unsigned int i=0; i<levels.size(); ++i)
3366  delete levels[i];
3367  levels.resize (0);
3368  delete faces;
3369  faces = NULL;
3370 
3371  {
3372  std::vector<types::global_dof_index> tmp;
3373  std::swap (vertex_dofs, tmp);
3374  }
3375 
3376  {
3377  std::vector<types::global_dof_index> tmp;
3378  std::swap (vertex_dofs_offsets, tmp);
3379  }
3380  }
3381 }
3382 
3383 
3384 
3385 /*-------------- Explicit Instantiations -------------------------------*/
3386 #include "dof_handler.inst"
3387 
3388 
3389 DEAL_II_NAMESPACE_CLOSE
IteratorRange< active_cell_iterator > active_cell_iterators_on_level(const unsigned int level) const
Definition: dof_handler.cc:974
unsigned int max_couplings_between_dofs() const
static const unsigned int invalid_unsigned_int
Definition: types.h:164
void load_user_flags_line(std::istream &in)
Definition: tria.cc:9753
void clear_user_flags()
Definition: tria.cc:9618
cell_iterator begin(const unsigned int level=0) const
Definition: dof_handler.cc:833
unsigned int offset_type
Definition: dof_level.h:109
void save_user_flags_quad(std::ostream &out) const
Definition: tria.cc:9852
void load_user_flags(std::istream &in)
Definition: tria.cc:9675
::ExceptionBase & ExcMessage(std::string arg1)
cell_iterator end() const
Definition: dof_handler.cc:861
virtual void clear()
const unsigned int dofs_per_quad
Definition: fe_base.h:238
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_quad_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe.cc:924
void clear_user_flags_quad()
Definition: tria.cc:9578
unsigned int max_dofs_per_face(const DoFHandler< dim, spacedim > &dh)
std::vector<::internal::DoFHandler::DoFLevel< dim > * > levels
Definition: dof_handler.h:1068
ActiveSelector::active_cell_iterator active_cell_iterator
Definition: dof_handler.h:221
SmartPointer< const Triangulation< dim, spacedim >, DoFHandler< dim, spacedim > > tria
Definition: dof_handler.h:914
unsigned int max_dofs_per_vertex(const DoFHandler< dim, spacedim > &dh)
#define AssertThrow(cond, exc)
Definition: exceptions.h:358
virtual std::size_t memory_consumption() const
::internal::DoFHandler::NumberCache number_cache
Definition: dof_handler.h:940
static unsigned int max_couplings_between_dofs(const DoFHandler< 1, spacedim > &dof_handler)
const FiniteElement< dim, spacedim > & get_fe() const
const unsigned int dofs_per_line
Definition: fe_base.h:232
void load_user_flags_quad(std::istream &in)
Definition: tria.cc:9863
ActiveSelector::active_cell_iterator active_cell_iterator
Definition: dof_handler.h:157
types::global_dof_index n_locally_owned_dofs
Definition: number_cache.h:63
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: dof_handler.cc:845
const hp::FECollection< dim, spacedim > & get_fe() const
void load_user_flags_hex(std::istream &in)
Definition: tria.cc:9926
ActiveSelector::cell_iterator cell_iterator
Definition: dof_handler.h:249
void save_user_flags_line(std::ostream &out) const
Definition: tria.cc:9742
void clear_user_flags_hex()
Definition: tria.cc:9610
unsigned int global_dof_index
Definition: types.h:88
static types::global_dof_index distribute_dofs_on_cell(const typename ::hp::DoFHandler< 1, spacedim >::active_cell_iterator &cell, types::global_dof_index next_free_dof)
Definition: dof_handler.cc:348
const unsigned int dofs_per_hex
Definition: fe_base.h:244
#define Assert(cond, exc)
Definition: exceptions.h:294
Signals signals
Definition: tria.h:2078
IteratorRange< active_cell_iterator > active_cell_iterators() const
Definition: dof_handler.cc:940
active_cell_iterator end_active(const unsigned int level) const
Definition: dof_handler.cc:883
types::global_dof_index n_boundary_dofs() const
types::global_dof_index n_dofs() const
static void reserve_space_vertices(DoFHandler< dim, spacedim > &dof_handler)
Definition: dof_handler.cc:232
::internal::DoFHandler::DoFFaces< dim > * faces
Definition: dof_handler.h:1077
ActiveSelector::cell_iterator cell_iterator
Definition: dof_handler.h:191
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_vertex_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe.cc:902
static void reserve_space(DoFHandler< 1, spacedim > &dof_handler)
Definition: dof_handler.cc:541
void save_user_flags_hex(std::ostream &out) const
Definition: tria.cc:9915
Definition: hp.h:102
virtual ~DoFHandler()
Definition: dof_handler.cc:793
void add_range(const size_type begin, const size_type end)
Definition: index_set.cc:86
void renumber_dofs(const std::vector< types::global_dof_index > &new_numbers)
std_cxx11::enable_if< std_cxx11::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
const Triangulation< dim, spacedim > & get_tria() const DEAL_II_DEPRECATED
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_line_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe.cc:913
std::vector< types::global_dof_index > n_locally_owned_dofs_per_processor
Definition: number_cache.h:77
void clear_space()
virtual void distribute_dofs(const FiniteElement< dim, spacedim > &fe)
FunctionMap< dim >::type FunctionMap
Definition: dof_handler.h:208
IteratorRange< cell_iterator > cell_iterators_on_level(const unsigned int level) const
Definition: dof_handler.cc:963
const Triangulation< dim, spacedim > & get_triangulation() const
Iterator points to a valid object.
const unsigned int dofs_per_vertex
Definition: fe_base.h:226
std::vector< IndexSet > locally_owned_dofs_per_processor
Definition: number_cache.h:84
Definition: table.h:33
const types::boundary_id internal_face_boundary_id
Definition: types.h:210
types::global_dof_index n_global_dofs
Definition: number_cache.h:57
unsigned int max_couplings_between_boundary_dofs() const
void clear_user_flags_line()
Definition: tria.cc:9546
const types::global_dof_index invalid_dof_index
Definition: types.h:178
IteratorRange< cell_iterator > cell_iterators() const
Definition: dof_handler.cc:930
virtual FiniteElementDomination::Domination compare_for_face_domination(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe.cc:935
std::vector< types::global_dof_index > vertex_dofs
Definition: dof_handler.h:1056
Task< RT > new_task(const std_cxx11::function< RT()> &function)