]> https://gitweb.dealii.org/ - dealii-svn.git/commitdiff
Split two more files into three files each.
authorkronbichler <kronbichler@0785d39b-7218-0410-832d-ea1e28bc413d>
Thu, 22 Aug 2013 04:19:24 +0000 (04:19 +0000)
committerkronbichler <kronbichler@0785d39b-7218-0410-832d-ea1e28bc413d>
Thu, 22 Aug 2013 04:19:24 +0000 (04:19 +0000)
git-svn-id: https://svn.dealii.org/trunk@30407 0785d39b-7218-0410-832d-ea1e28bc413d

16 files changed:
deal.II/include/deal.II/fe/component_mask.h
deal.II/include/deal.II/numerics/vector_tools.h
deal.II/include/deal.II/numerics/vector_tools.templates.h
deal.II/source/dofs/CMakeLists.txt
deal.II/source/dofs/dof_accessor.cc
deal.II/source/dofs/dof_accessor.inst.in
deal.II/source/dofs/dof_accessor_get.cc [new file with mode: 0644]
deal.II/source/dofs/dof_accessor_get.inst.in [new file with mode: 0644]
deal.II/source/dofs/dof_accessor_set.cc [new file with mode: 0644]
deal.II/source/dofs/dof_accessor_set.inst.in [new file with mode: 0644]
deal.II/source/dofs/dof_tools.cc
deal.II/source/dofs/dof_tools.inst.in
deal.II/source/dofs/dof_tools_constraints.cc [new file with mode: 0644]
deal.II/source/dofs/dof_tools_constraints.inst.in [new file with mode: 0644]
deal.II/source/dofs/dof_tools_sparsity.cc [new file with mode: 0644]
deal.II/source/dofs/dof_tools_sparsity.inst.in [new file with mode: 0644]

index 0661aa2c63794beae4605e836bab3c17134c3879..bb60046fc4da7d48918eef1ac80e1e879459768e 100644 (file)
@@ -209,6 +209,11 @@ public:
   std::size_t
   memory_consumption () const;
 
+  /**
+   * Exception
+   */
+  DeclException0 (ExcNoComponentSelected);
+
 private:
   /**
    * The actual component mask.
index d7cf41a6ed1579e8da9a9571a938605043a830d6..1121e1ff66043eb084e0dcc5f526321d764f6c5a 100644 (file)
@@ -2418,11 +2418,6 @@ namespace VectorTools
    * Exception
    */
   DeclException0 (ExcNonInterpolatingFE);
-
-  /**
-   * Exception
-   */
-  DeclException0 (ExcNoComponentSelected);
 }
 
 
index 0c0799fc5d3d80b28f82b8b67459dce9e98cb432..32bd4679056ff4b47d588f3b67c1b0839ade323e 100644 (file)
@@ -1524,7 +1524,7 @@ namespace VectorTools
                                            boundary_function.n_components));
 
               Assert (component_mask.n_selected_components(fe.n_components()) > 0,
-                      ExcNoComponentSelected());
+                      ComponentMask::ExcNoComponentSelected());
 
               // now set the value of
               // the vertex degree of
@@ -5482,7 +5482,7 @@ namespace VectorTools
             }
         // Error out if we have not constrained anything. Note that in this
         // case the vector v is always nonempty.
-        Assert (n == 0 || counter > 0, ExcNoComponentSelected());
+        Assert (n == 0 || counter > 0, ComponentMask::ExcNoComponentSelected());
 
         s /= counter;
 
index f791bd398eaab9db171fe0ae3996ecd5d506853f..e3bf9d563148cd69c2e6ddb8dbe15af5ff90810e 100644 (file)
@@ -23,23 +23,31 @@ FILE(GLOB _header
 SET(_src
   block_info.cc
   dof_accessor.cc
+  dof_accessor_get.cc
+  dof_accessor_set.cc
   dof_faces.cc
   dof_handler.cc
   dof_handler_policy.cc
   dof_objects.cc
   dof_renumbering.cc
   dof_tools.cc
+  dof_tools_constraints.cc
+  dof_tools_sparsity.cc
   number_cache.cc
   )
 
 SET(_inst
   block_info.inst.in
   dof_accessor.inst.in
+  dof_accessor_get.inst.in
+  dof_accessor_set.inst.in
   dof_handler.inst.in
   dof_handler_policy.inst.in
   dof_objects.inst.in
   dof_renumbering.inst.in
   dof_tools.inst.in
+  dof_tools_constraints.inst.in
+  dof_tools_sparsity.inst.in
   )
 
 DEAL_II_ADD_LIBRARY(obj_dofs OBJECT ${_src} ${_header} ${_inst})
index 53b67ac4d1997cb95e09b88cd505ee9f63f7434e..34dbb349064bb5dfb18fe57ecb8d7bd0e14633e4 100644 (file)
 //
 // ---------------------------------------------------------------------
 
-#include <deal.II/lac/vector.h>
-#include <deal.II/lac/block_vector.h>
-#include <deal.II/lac/parallel_vector.h>
-#include <deal.II/lac/parallel_block_vector.h>
-#include <deal.II/lac/petsc_vector.h>
-#include <deal.II/lac/petsc_block_vector.h>
-#include <deal.II/lac/trilinos_vector.h>
-#include <deal.II/lac/trilinos_block_vector.h>
-#include <deal.II/lac/sparse_matrix.h>
-
 #include <deal.II/dofs/dof_accessor.h>
 #include <deal.II/dofs/dof_handler.h>
 #include <deal.II/dofs/dof_levels.h>
@@ -97,134 +87,6 @@ DoFCellAccessor<DH,lda>::neighbor_child_on_subface (const unsigned int face,
 
 
 
-template <class DH, bool lda>
-template <class InputVector, typename number>
-void
-DoFCellAccessor<DH,lda>::
-get_interpolated_dof_values (const InputVector &values,
-                             Vector<number>    &interpolated_values) const
-{
-  const FiniteElement<dim,spacedim> &fe            = this->get_fe();
-  const unsigned int        dofs_per_cell = fe.dofs_per_cell;
-
-  Assert (this->dof_handler != 0,
-          typename BaseClass::ExcInvalidObject());
-  Assert (&fe != 0,
-          typename BaseClass::ExcInvalidObject());
-  Assert (interpolated_values.size() == dofs_per_cell,
-          typename BaseClass::ExcVectorDoesNotMatch());
-  Assert (values.size() == this->dof_handler->n_dofs(),
-          typename BaseClass::ExcVectorDoesNotMatch());
-
-  if (!this->has_children())
-    // if this cell has no children: simply return the exact values on this
-    // cell
-    this->get_dof_values (values, interpolated_values);
-  else
-    // otherwise clobber them from the children
-    {
-      Vector<number> tmp1(dofs_per_cell);
-      Vector<number> tmp2(dofs_per_cell);
-
-      interpolated_values = 0;
-
-      // later on we will have to push the values interpolated from the child
-      // to the mother cell into the output vector. unfortunately, there are
-      // two types of elements: ones where you add up the contributions from
-      // the different child cells, and ones where you overwrite.
-      //
-      // an example for the first is piecewise constant (and discontinuous)
-      // elements, where we build the value on the coarse cell by averaging
-      // the values from the cell (i.e. by adding up a fraction of the values
-      // of their values)
-      //
-      // an example for the latter are the usual continuous elements. the
-      // value on a vertex of a coarse cell must there be the same,
-      // irrespective of the adjacent cell we are presently on. so we always
-      // overwrite. in fact, we must, since we cannot know in advance how many
-      // neighbors there will be, so there is no way to compute the average
-      // with fixed factors
-      //
-      // so we have to find out to which type this element belongs. the
-      // difficulty is: the finite element may be a composed one, so we can
-      // only hope to do this for each shape function individually. in fact,
-      // there are even weird finite elements (for example the Raviart-Thomas
-      // element) which have shape functions that are additive (interior ones)
-      // and others that are overwriting (face degrees of freedom that need to
-      // be continuous across the face). to avoid checking this over and over
-      // again, we do this once now and cache the results
-      std::vector<bool> restriction_is_additive (dofs_per_cell);
-      for (unsigned int i=0; i<dofs_per_cell; ++i)
-        restriction_is_additive[i] = fe.restriction_is_additive(i);
-
-      for (unsigned int child=0; child<this->n_children(); ++child)
-        {
-          // get the values from the present child, if necessary by
-          // interpolation itself
-          this->child(child)->get_interpolated_dof_values (values,
-                                                           tmp1);
-          // interpolate these to the mother cell
-          fe.get_restriction_matrix(child, this->refinement_case()).vmult (tmp2, tmp1);
-
-          // and add up or set them in the output vector
-          for (unsigned int i=0; i<dofs_per_cell; ++i)
-            if (restriction_is_additive[i])
-              interpolated_values(i) += tmp2(i);
-            else if (tmp2(i) != number())
-              interpolated_values(i) = tmp2(i);
-        }
-    }
-}
-
-
-
-template <class DH, bool lda>
-template <class OutputVector, typename number>
-void
-DoFCellAccessor<DH,lda>::
-set_dof_values_by_interpolation (const Vector<number> &local_values,
-                                 OutputVector         &values) const
-{
-  const unsigned int dofs_per_cell = this->get_fe().dofs_per_cell;
-
-  Assert (this->dof_handler != 0,
-          typename BaseClass::ExcInvalidObject());
-  Assert (&this->get_fe() != 0,
-          typename BaseClass::ExcInvalidObject());
-  Assert (local_values.size() == dofs_per_cell,
-          typename BaseClass::ExcVectorDoesNotMatch());
-  Assert (values.size() == this->dof_handler->n_dofs(),
-          typename BaseClass::ExcVectorDoesNotMatch());
-
-  if (!this->has_children())
-    // if this cell has no children: simply set the values on this cell
-    this->set_dof_values (local_values, values);
-  else
-    // otherwise distribute them to the children
-    {
-      Vector<number> tmp(dofs_per_cell);
-
-      for (unsigned int child=0; child<this->n_children(); ++child)
-        {
-          Assert (this->child(child)->get_fe().dofs_per_cell == dofs_per_cell,
-                  ExcNotImplemented());
-
-          // prolong the given data to the present cell. FullMatrix only wants
-          // us to call vmult if the matrix size is actually non-zero, so
-          // check that case
-          if (tmp.size() > 0)
-            {
-              this->get_fe().get_prolongation_matrix(child, this->refinement_case())
-              .vmult (tmp, local_values);
-
-              this->child(child)->set_dof_values_by_interpolation (tmp, values);
-            }
-        }
-    }
-}
-
-
-
 // --------------------------------------------------------------------------
 // explicit instantiations
 #include "dof_accessor.inst"
index 103290a71178172230acd97d6aa97a1ad9a82169..297e98c82910e37775671bbf62d974f571401001 100644 (file)
@@ -165,82 +165,3 @@ for (deal_II_dimension : DIMENSIONS; lda : BOOL)
 #endif
   }
 
-
-for (VEC : SERIAL_VECTORS; SCALAR : REAL_SCALARS; deal_II_dimension : DIMENSIONS; lda : BOOL)
-  {
-    template
-      void
-      DoFCellAccessor<DoFHandler<deal_II_dimension>, lda>::get_interpolated_dof_values
-      (const VEC&, Vector<SCALAR>&) const;
-    template
-      void
-      DoFCellAccessor<DoFHandler<deal_II_dimension>, lda>::set_dof_values_by_interpolation
-      (const Vector<SCALAR>&, VEC&) const;
-
-#if deal_II_dimension != 3
-
-    template
-      void
-      DoFCellAccessor<DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::get_interpolated_dof_values
-      (const VEC&, Vector<SCALAR>&) const;
-    template
-      void
-      DoFCellAccessor<DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::set_dof_values_by_interpolation
-      (const Vector<SCALAR>&, VEC&) const;
-
-#endif
-
-#if deal_II_dimension == 3
-
-    template
-      void
-      DoFCellAccessor<DoFHandler<1,3>, lda>::get_interpolated_dof_values
-      (const VEC&, Vector<SCALAR>&) const;
-    template
-      void
-      DoFCellAccessor<DoFHandler<1,3>, lda>::set_dof_values_by_interpolation
-      (const Vector<SCALAR>&, VEC&) const;
-
-#endif
-
-  }
-
-
-for (VEC : SERIAL_VECTORS; SCALAR : REAL_SCALARS; deal_II_dimension : DIMENSIONS; lda : BOOL)
-  {
-    template
-      void
-      DoFCellAccessor<hp::DoFHandler<deal_II_dimension>, lda>::get_interpolated_dof_values
-      (const VEC&, Vector<SCALAR>&) const;
-    template
-      void
-      DoFCellAccessor<hp::DoFHandler<deal_II_dimension>, lda>::set_dof_values_by_interpolation
-      (const Vector<SCALAR>&, VEC&) const;
-
-#if deal_II_dimension != 3
-
-    template
-      void
-      DoFCellAccessor<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::get_interpolated_dof_values
-      (const VEC&, Vector<SCALAR>&) const;
-    template
-      void
-      DoFCellAccessor<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::set_dof_values_by_interpolation
-      (const Vector<SCALAR>&, VEC&) const;
-
-#endif
-
-#if deal_II_dimension == 3
-
-    template
-      void
-      DoFCellAccessor<hp::DoFHandler<1,3>, lda>::get_interpolated_dof_values
-      (const VEC&, Vector<SCALAR>&) const;
-    template
-      void
-      DoFCellAccessor<hp::DoFHandler<1,3>, lda>::set_dof_values_by_interpolation
-      (const Vector<SCALAR>&, VEC&) const;
-
-#endif
-  }
-
diff --git a/deal.II/source/dofs/dof_accessor_get.cc b/deal.II/source/dofs/dof_accessor_get.cc
new file mode 100644 (file)
index 0000000..9b9ca8b
--- /dev/null
@@ -0,0 +1,125 @@
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/lac/parallel_vector.h>
+#include <deal.II/lac/parallel_block_vector.h>
+#include <deal.II/lac/petsc_vector.h>
+#include <deal.II/lac/petsc_block_vector.h>
+#include <deal.II/lac/trilinos_vector.h>
+#include <deal.II/lac/trilinos_block_vector.h>
+#include <deal.II/lac/sparse_matrix.h>
+
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_levels.h>
+#include <deal.II/hp/dof_handler.h>
+#include <deal.II/grid/tria_boundary.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/tria_iterator.templates.h>
+#include <deal.II/fe/fe.h>
+
+#include <vector>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+template <class DH, bool lda>
+template <class InputVector, typename number>
+void
+DoFCellAccessor<DH,lda>::
+get_interpolated_dof_values (const InputVector &values,
+                             Vector<number>    &interpolated_values) const
+{
+  const FiniteElement<dim,spacedim> &fe            = this->get_fe();
+  const unsigned int        dofs_per_cell = fe.dofs_per_cell;
+
+  Assert (this->dof_handler != 0,
+          typename BaseClass::ExcInvalidObject());
+  Assert (&fe != 0,
+          typename BaseClass::ExcInvalidObject());
+  Assert (interpolated_values.size() == dofs_per_cell,
+          typename BaseClass::ExcVectorDoesNotMatch());
+  Assert (values.size() == this->dof_handler->n_dofs(),
+          typename BaseClass::ExcVectorDoesNotMatch());
+
+  if (!this->has_children())
+    // if this cell has no children: simply return the exact values on this
+    // cell
+    this->get_dof_values (values, interpolated_values);
+  else
+    // otherwise clobber them from the children
+    {
+      Vector<number> tmp1(dofs_per_cell);
+      Vector<number> tmp2(dofs_per_cell);
+
+      interpolated_values = 0;
+
+      // later on we will have to push the values interpolated from the child
+      // to the mother cell into the output vector. unfortunately, there are
+      // two types of elements: ones where you add up the contributions from
+      // the different child cells, and ones where you overwrite.
+      //
+      // an example for the first is piecewise constant (and discontinuous)
+      // elements, where we build the value on the coarse cell by averaging
+      // the values from the cell (i.e. by adding up a fraction of the values
+      // of their values)
+      //
+      // an example for the latter are the usual continuous elements. the
+      // value on a vertex of a coarse cell must there be the same,
+      // irrespective of the adjacent cell we are presently on. so we always
+      // overwrite. in fact, we must, since we cannot know in advance how many
+      // neighbors there will be, so there is no way to compute the average
+      // with fixed factors
+      //
+      // so we have to find out to which type this element belongs. the
+      // difficulty is: the finite element may be a composed one, so we can
+      // only hope to do this for each shape function individually. in fact,
+      // there are even weird finite elements (for example the Raviart-Thomas
+      // element) which have shape functions that are additive (interior ones)
+      // and others that are overwriting (face degrees of freedom that need to
+      // be continuous across the face). to avoid checking this over and over
+      // again, we do this once now and cache the results
+      std::vector<bool> restriction_is_additive (dofs_per_cell);
+      for (unsigned int i=0; i<dofs_per_cell; ++i)
+        restriction_is_additive[i] = fe.restriction_is_additive(i);
+
+      for (unsigned int child=0; child<this->n_children(); ++child)
+        {
+          // get the values from the present child, if necessary by
+          // interpolation itself
+          this->child(child)->get_interpolated_dof_values (values,
+                                                           tmp1);
+          // interpolate these to the mother cell
+          fe.get_restriction_matrix(child, this->refinement_case()).vmult (tmp2, tmp1);
+
+          // and add up or set them in the output vector
+          for (unsigned int i=0; i<dofs_per_cell; ++i)
+            if (restriction_is_additive[i])
+              interpolated_values(i) += tmp2(i);
+            else if (tmp2(i) != number())
+              interpolated_values(i) = tmp2(i);
+        }
+    }
+}
+
+
+// --------------------------------------------------------------------------
+// explicit instantiations
+#include "dof_accessor_get.inst"
+
+DEAL_II_NAMESPACE_CLOSE
diff --git a/deal.II/source/dofs/dof_accessor_get.inst.in b/deal.II/source/dofs/dof_accessor_get.inst.in
new file mode 100644 (file)
index 0000000..75d1009
--- /dev/null
@@ -0,0 +1,72 @@
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+for (VEC : SERIAL_VECTORS; SCALAR : REAL_SCALARS; deal_II_dimension : DIMENSIONS; lda : BOOL)
+  {
+    template
+      void
+      DoFCellAccessor<DoFHandler<deal_II_dimension>, lda>::get_interpolated_dof_values
+      (const VEC&, Vector<SCALAR>&) const;
+
+#if deal_II_dimension != 3
+
+    template
+      void
+      DoFCellAccessor<DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::get_interpolated_dof_values
+      (const VEC&, Vector<SCALAR>&) const;
+
+#endif
+
+#if deal_II_dimension == 3
+
+    template
+      void
+      DoFCellAccessor<DoFHandler<1,3>, lda>::get_interpolated_dof_values
+      (const VEC&, Vector<SCALAR>&) const;
+
+#endif
+
+  }
+
+
+for (VEC : SERIAL_VECTORS; SCALAR : REAL_SCALARS; deal_II_dimension : DIMENSIONS; lda : BOOL)
+  {
+    template
+      void
+      DoFCellAccessor<hp::DoFHandler<deal_II_dimension>, lda>::get_interpolated_dof_values
+      (const VEC&, Vector<SCALAR>&) const;
+
+#if deal_II_dimension != 3
+
+    template
+      void
+      DoFCellAccessor<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::get_interpolated_dof_values
+      (const VEC&, Vector<SCALAR>&) const;
+
+#endif
+
+#if deal_II_dimension == 3
+
+    template
+      void
+      DoFCellAccessor<hp::DoFHandler<1,3>, lda>::get_interpolated_dof_values
+      (const VEC&, Vector<SCALAR>&) const;
+
+#endif
+  }
+
diff --git a/deal.II/source/dofs/dof_accessor_set.cc b/deal.II/source/dofs/dof_accessor_set.cc
new file mode 100644 (file)
index 0000000..f11fc84
--- /dev/null
@@ -0,0 +1,93 @@
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/lac/parallel_vector.h>
+#include <deal.II/lac/parallel_block_vector.h>
+#include <deal.II/lac/petsc_vector.h>
+#include <deal.II/lac/petsc_block_vector.h>
+#include <deal.II/lac/trilinos_vector.h>
+#include <deal.II/lac/trilinos_block_vector.h>
+#include <deal.II/lac/sparse_matrix.h>
+
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_levels.h>
+#include <deal.II/hp/dof_handler.h>
+#include <deal.II/grid/tria_boundary.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/tria_iterator.templates.h>
+#include <deal.II/fe/fe.h>
+
+#include <vector>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+
+template <class DH, bool lda>
+template <class OutputVector, typename number>
+void
+DoFCellAccessor<DH,lda>::
+set_dof_values_by_interpolation (const Vector<number> &local_values,
+                                 OutputVector         &values) const
+{
+  const unsigned int dofs_per_cell = this->get_fe().dofs_per_cell;
+
+  Assert (this->dof_handler != 0,
+          typename BaseClass::ExcInvalidObject());
+  Assert (&this->get_fe() != 0,
+          typename BaseClass::ExcInvalidObject());
+  Assert (local_values.size() == dofs_per_cell,
+          typename BaseClass::ExcVectorDoesNotMatch());
+  Assert (values.size() == this->dof_handler->n_dofs(),
+          typename BaseClass::ExcVectorDoesNotMatch());
+
+  if (!this->has_children())
+    // if this cell has no children: simply set the values on this cell
+    this->set_dof_values (local_values, values);
+  else
+    // otherwise distribute them to the children
+    {
+      Vector<number> tmp(dofs_per_cell);
+
+      for (unsigned int child=0; child<this->n_children(); ++child)
+        {
+          Assert (this->child(child)->get_fe().dofs_per_cell == dofs_per_cell,
+                  ExcNotImplemented());
+
+          // prolong the given data to the present cell. FullMatrix only wants
+          // us to call vmult if the matrix size is actually non-zero, so
+          // check that case
+          if (tmp.size() > 0)
+            {
+              this->get_fe().get_prolongation_matrix(child, this->refinement_case())
+              .vmult (tmp, local_values);
+
+              this->child(child)->set_dof_values_by_interpolation (tmp, values);
+            }
+        }
+    }
+}
+
+
+
+// --------------------------------------------------------------------------
+// explicit instantiations
+#include "dof_accessor_set.inst"
+
+DEAL_II_NAMESPACE_CLOSE
diff --git a/deal.II/source/dofs/dof_accessor_set.inst.in b/deal.II/source/dofs/dof_accessor_set.inst.in
new file mode 100644 (file)
index 0000000..7494831
--- /dev/null
@@ -0,0 +1,72 @@
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1998 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+for (VEC : SERIAL_VECTORS; SCALAR : REAL_SCALARS; deal_II_dimension : DIMENSIONS; lda : BOOL)
+  {
+    template
+      void
+      DoFCellAccessor<DoFHandler<deal_II_dimension>, lda>::set_dof_values_by_interpolation
+      (const Vector<SCALAR>&, VEC&) const;
+
+#if deal_II_dimension != 3
+
+    template
+      void
+      DoFCellAccessor<DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::set_dof_values_by_interpolation
+      (const Vector<SCALAR>&, VEC&) const;
+
+#endif
+
+#if deal_II_dimension == 3
+
+    template
+      void
+      DoFCellAccessor<DoFHandler<1,3>, lda>::set_dof_values_by_interpolation
+      (const Vector<SCALAR>&, VEC&) const;
+
+#endif
+
+  }
+
+
+for (VEC : SERIAL_VECTORS; SCALAR : REAL_SCALARS; deal_II_dimension : DIMENSIONS; lda : BOOL)
+  {
+    template
+      void
+      DoFCellAccessor<hp::DoFHandler<deal_II_dimension>, lda>::set_dof_values_by_interpolation
+      (const Vector<SCALAR>&, VEC&) const;
+
+#if deal_II_dimension != 3
+
+    template
+      void
+      DoFCellAccessor<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, lda>::set_dof_values_by_interpolation
+      (const Vector<SCALAR>&, VEC&) const;
+
+#endif
+
+#if deal_II_dimension == 3
+
+    template
+      void
+      DoFCellAccessor<hp::DoFHandler<1,3>, lda>::set_dof_values_by_interpolation
+      (const Vector<SCALAR>&, VEC&) const;
+
+#endif
+  }
+
index ad41b28892b8cbe4b89e6dfd75744a96bd03dee0..51b5f2ec559e360eb7c6fe395c5b0434e234a4a0 100644 (file)
@@ -41,7 +41,6 @@
 #include <deal.II/hp/q_collection.h>
 #include <deal.II/hp/fe_values.h>
 #include <deal.II/dofs/dof_tools.h>
-#include <deal.II/numerics/vector_tools.h>
 
 #include <deal.II/multigrid/mg_dof_handler.h>
 
@@ -54,3212 +53,6 @@ DEAL_II_NAMESPACE_OPEN
 
 namespace DoFTools
 {
-
-  template <class DH, class SparsityPattern>
-  void
-  make_sparsity_pattern (const DH               &dof,
-                         SparsityPattern        &sparsity,
-                         const ConstraintMatrix &constraints,
-                         const bool              keep_constrained_dofs,
-                         const types::subdomain_id subdomain_id)
-  {
-    const types::global_dof_index n_dofs = dof.n_dofs();
-
-    Assert (sparsity.n_rows() == n_dofs,
-            ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
-    Assert (sparsity.n_cols() == n_dofs,
-            ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
-
-    // If we have a distributed::Triangulation only allow locally_owned
-    // subdomain. Not setting a subdomain is also okay, because we skip
-    // ghost cells in the loop below.
-    Assert (
-      (dof.get_tria().locally_owned_subdomain() == numbers::invalid_subdomain_id)
-      ||
-      (subdomain_id == numbers::invalid_subdomain_id)
-      ||
-      (subdomain_id == dof.get_tria().locally_owned_subdomain()),
-      ExcMessage ("For parallel::distributed::Triangulation objects and "
-                  "associated DoF handler objects, asking for any subdomain other "
-                  "than the locally owned one does not make sense."));
-
-    std::vector<types::global_dof_index> dofs_on_this_cell;
-    dofs_on_this_cell.reserve (max_dofs_per_cell(dof));
-    typename DH::active_cell_iterator cell = dof.begin_active(),
-                                      endc = dof.end();
-
-    // In case we work with a distributed sparsity pattern of Trilinos
-    // type, we only have to do the work if the current cell is owned by
-    // the calling processor. Otherwise, just continue.
-    for (; cell!=endc; ++cell)
-      if (((subdomain_id == numbers::invalid_subdomain_id)
-           ||
-           (subdomain_id == cell->subdomain_id()))
-          &&
-          cell->is_locally_owned())
-        {
-          const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
-          dofs_on_this_cell.resize (dofs_per_cell);
-          cell->get_dof_indices (dofs_on_this_cell);
-
-          // make sparsity pattern for this cell. if no constraints pattern
-          // was given, then the following call acts as if simply no
-          // constraints existed
-          constraints.add_entries_local_to_global (dofs_on_this_cell,
-                                                   sparsity,
-                                                   keep_constrained_dofs);
-        }
-  }
-
-
-
-  template <class DH, class SparsityPattern>
-  void
-  make_sparsity_pattern (const DH                &dof,
-                         const Table<2,Coupling> &couplings,
-                         SparsityPattern         &sparsity,
-                         const ConstraintMatrix  &constraints,
-                         const bool               keep_constrained_dofs,
-                         const types::subdomain_id subdomain_id)
-  {
-    const types::global_dof_index n_dofs = dof.n_dofs();
-
-    Assert (sparsity.n_rows() == n_dofs,
-            ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
-    Assert (sparsity.n_cols() == n_dofs,
-            ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
-    Assert (couplings.n_rows() == dof.get_fe().n_components(),
-            ExcDimensionMismatch(couplings.n_rows(), dof.get_fe().n_components()));
-    Assert (couplings.n_cols() == dof.get_fe().n_components(),
-            ExcDimensionMismatch(couplings.n_cols(), dof.get_fe().n_components()));
-
-    // If we have a distributed::Triangulation only allow locally_owned
-    // subdomain. Not setting a subdomain is also okay, because we skip
-    // ghost cells in the loop below.
-    Assert (
-      (dof.get_tria().locally_owned_subdomain() == numbers::invalid_subdomain_id)
-      ||
-      (subdomain_id == numbers::invalid_subdomain_id)
-      ||
-      (subdomain_id == dof.get_tria().locally_owned_subdomain()),
-      ExcMessage ("For parallel::distributed::Triangulation objects and "
-                  "associated DoF handler objects, asking for any subdomain other "
-                  "than the locally owned one does not make sense."));
-
-    const hp::FECollection<DH::dimension,DH::space_dimension> fe_collection (dof.get_fe());
-
-    // first, for each finite element, build a mask for each dof, not like
-    // the one given which represents components. make sure we do the right
-    // thing also with respect to non-primitive shape functions, which
-    // takes some additional thought
-    std::vector<Table<2,bool> > dof_mask(fe_collection.size());
-
-    // check whether the table of couplings contains only true arguments,
-    // i.e., we do not exclude any index. that is the easy case, since we
-    // don't have to set up the tables
-    bool need_dof_mask = false;
-    for (unsigned int i=0; i<couplings.n_rows(); ++i)
-      for (unsigned int j=0; j<couplings.n_cols(); ++j)
-        if (couplings(i,j) == none)
-          need_dof_mask = true;
-
-    if (need_dof_mask == true)
-      for (unsigned int f=0; f<fe_collection.size(); ++f)
-        {
-          const unsigned int dofs_per_cell = fe_collection[f].dofs_per_cell;
-
-          dof_mask[f].reinit (dofs_per_cell, dofs_per_cell);
-
-          for (unsigned int i=0; i<dofs_per_cell; ++i)
-            for (unsigned int j=0; j<dofs_per_cell; ++j)
-              if (fe_collection[f].is_primitive(i) &&
-                  fe_collection[f].is_primitive(j))
-                dof_mask[f](i,j)
-                  = (couplings(fe_collection[f].system_to_component_index(i).first,
-                               fe_collection[f].system_to_component_index(j).first) != none);
-              else
-                {
-                  const unsigned int first_nonzero_comp_i
-                    = fe_collection[f].get_nonzero_components(i).first_selected_component();
-                  const unsigned int first_nonzero_comp_j
-                    = fe_collection[f].get_nonzero_components(j).first_selected_component();
-                  Assert (first_nonzero_comp_i < fe_collection[f].n_components(),
-                          ExcInternalError());
-                  Assert (first_nonzero_comp_j < fe_collection[f].n_components(),
-                          ExcInternalError());
-
-                  dof_mask[f](i,j)
-                    = (couplings(first_nonzero_comp_i,first_nonzero_comp_j) != none);
-                }
-        }
-
-
-    std::vector<types::global_dof_index> dofs_on_this_cell(fe_collection.max_dofs_per_cell());
-    typename DH::active_cell_iterator cell = dof.begin_active(),
-                                      endc = dof.end();
-
-    // In case we work with a distributed sparsity pattern of Trilinos
-    // type, we only have to do the work if the current cell is owned by
-    // the calling processor. Otherwise, just continue.
-    for (; cell!=endc; ++cell)
-      if (((subdomain_id == numbers::invalid_subdomain_id)
-           ||
-           (subdomain_id == cell->subdomain_id()))
-          &&
-          cell->is_locally_owned())
-        {
-          const unsigned int fe_index = cell->active_fe_index();
-          const unsigned int dofs_per_cell =fe_collection[fe_index].dofs_per_cell;
-
-          dofs_on_this_cell.resize (dofs_per_cell);
-          cell->get_dof_indices (dofs_on_this_cell);
-
-
-          // make sparsity pattern for this cell. if no constraints pattern
-          // was given, then the following call acts as if simply no
-          // constraints existed
-          constraints.add_entries_local_to_global (dofs_on_this_cell,
-                                                   sparsity,
-                                                   keep_constrained_dofs,
-                                                   dof_mask[fe_index]);
-        }
-  }
-
-
-
-  template <class DH, class SparsityPattern>
-  void
-  make_sparsity_pattern (
-    const DH        &dof_row,
-    const DH        &dof_col,
-    SparsityPattern &sparsity)
-  {
-    const types::global_dof_index n_dofs_row = dof_row.n_dofs();
-    const types::global_dof_index n_dofs_col = dof_col.n_dofs();
-
-    Assert (sparsity.n_rows() == n_dofs_row,
-            ExcDimensionMismatch (sparsity.n_rows(), n_dofs_row));
-    Assert (sparsity.n_cols() == n_dofs_col,
-            ExcDimensionMismatch (sparsity.n_cols(), n_dofs_col));
-
-//TODO: Looks like wasteful memory management here
-
-    const std::list<std::pair<typename DH::cell_iterator,
-          typename DH::cell_iterator> >
-          cell_list
-          = GridTools::get_finest_common_cells (dof_row, dof_col);
-
-
-    typename std::list<std::pair<typename DH::cell_iterator,
-             typename DH::cell_iterator> >::const_iterator
-             cell_iter = cell_list.begin();
-
-    for (; cell_iter!=cell_list.end(); ++cell_iter)
-      {
-        const typename DH::cell_iterator cell_row = cell_iter->first;
-        const typename DH::cell_iterator cell_col = cell_iter->second;
-
-        if (!cell_row->has_children() && !cell_col->has_children())
-          {
-            const unsigned int dofs_per_cell_row =
-              cell_row->get_fe().dofs_per_cell;
-            const unsigned int dofs_per_cell_col =
-              cell_col->get_fe().dofs_per_cell;
-            std::vector<types::global_dof_index>
-            local_dof_indices_row(dofs_per_cell_row);
-            std::vector<types::global_dof_index>
-            local_dof_indices_col(dofs_per_cell_col);
-            cell_row->get_dof_indices (local_dof_indices_row);
-            cell_col->get_dof_indices (local_dof_indices_col);
-            for (unsigned int i=0; i<dofs_per_cell_row; ++i)
-              sparsity.add_entries (local_dof_indices_row[i],
-                                    local_dof_indices_col.begin(),
-                                    local_dof_indices_col.end());
-          }
-        else if (cell_row->has_children())
-          {
-            const std::vector<typename DH::active_cell_iterator >
-            child_cells = GridTools::get_active_child_cells<DH> (cell_row);
-            for (unsigned int i=0; i<child_cells.size(); i++)
-              {
-                const typename DH::cell_iterator
-                cell_row_child = child_cells[i];
-                const unsigned int dofs_per_cell_row =
-                  cell_row_child->get_fe().dofs_per_cell;
-                const unsigned int dofs_per_cell_col =
-                  cell_col->get_fe().dofs_per_cell;
-                std::vector<types::global_dof_index>
-                local_dof_indices_row(dofs_per_cell_row);
-                std::vector<types::global_dof_index>
-                local_dof_indices_col(dofs_per_cell_col);
-                cell_row_child->get_dof_indices (local_dof_indices_row);
-                cell_col->get_dof_indices (local_dof_indices_col);
-                for (unsigned int i=0; i<dofs_per_cell_row; ++i)
-                  sparsity.add_entries (local_dof_indices_row[i],
-                                        local_dof_indices_col.begin(),
-                                        local_dof_indices_col.end());
-              }
-          }
-        else
-          {
-            std::vector<typename DH::active_cell_iterator>
-            child_cells = GridTools::get_active_child_cells<DH> (cell_col);
-            for (unsigned int i=0; i<child_cells.size(); i++)
-              {
-                const typename DH::active_cell_iterator
-                cell_col_child = child_cells[i];
-                const unsigned int dofs_per_cell_row =
-                  cell_row->get_fe().dofs_per_cell;
-                const unsigned int dofs_per_cell_col =
-                  cell_col_child->get_fe().dofs_per_cell;
-                std::vector<types::global_dof_index>
-                local_dof_indices_row(dofs_per_cell_row);
-                std::vector<types::global_dof_index>
-                local_dof_indices_col(dofs_per_cell_col);
-                cell_row->get_dof_indices (local_dof_indices_row);
-                cell_col_child->get_dof_indices (local_dof_indices_col);
-                for (unsigned int i=0; i<dofs_per_cell_row; ++i)
-                  sparsity.add_entries (local_dof_indices_row[i],
-                                        local_dof_indices_col.begin(),
-                                        local_dof_indices_col.end());
-              }
-          }
-      }
-  }
-
-
-
-  template <class DH, class SparsityPattern>
-  void
-  make_boundary_sparsity_pattern (
-    const DH                        &dof,
-    const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
-    SparsityPattern                 &sparsity)
-  {
-    if (DH::dimension == 1)
-      {
-        // there are only 2 boundary indicators in 1d, so it is no
-        // performance problem to call the other function
-        typename DH::FunctionMap boundary_indicators;
-        boundary_indicators[0] = 0;
-        boundary_indicators[1] = 0;
-        make_boundary_sparsity_pattern<DH, SparsityPattern> (dof,
-                                                             boundary_indicators,
-                                                             dof_to_boundary_mapping,
-                                                             sparsity);
-        return;
-      }
-
-    const types::global_dof_index n_dofs = dof.n_dofs();
-
-    AssertDimension (dof_to_boundary_mapping.size(), n_dofs);
-    AssertDimension (sparsity.n_rows(), dof.n_boundary_dofs());
-    AssertDimension (sparsity.n_cols(), dof.n_boundary_dofs());
-#ifdef DEBUG
-    if (sparsity.n_rows() != 0)
-      {
-        types::global_dof_index max_element = 0;
-        for (std::vector<types::global_dof_index>::const_iterator i=dof_to_boundary_mapping.begin();
-             i!=dof_to_boundary_mapping.end(); ++i)
-          if ((*i != DH::invalid_dof_index) &&
-              (*i > max_element))
-            max_element = *i;
-        AssertDimension (max_element, sparsity.n_rows()-1);
-      };
-#endif
-
-    std::vector<types::global_dof_index> dofs_on_this_face;
-    dofs_on_this_face.reserve (max_dofs_per_face(dof));
-
-    // loop over all faces to check whether they are at a boundary. note
-    // that we need not take special care of single lines (using
-    // @p{cell->has_boundary_lines}), since we do not support boundaries of
-    // dimension dim-2, and so every boundary line is also part of a
-    // boundary face.
-    typename DH::active_cell_iterator cell = dof.begin_active(),
-                                      endc = dof.end();
-    for (; cell!=endc; ++cell)
-      for (unsigned int f=0; f<GeometryInfo<DH::dimension>::faces_per_cell; ++f)
-        if (cell->at_boundary(f))
-          {
-            const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
-            dofs_on_this_face.resize (dofs_per_face);
-            cell->face(f)->get_dof_indices (dofs_on_this_face,
-                                            cell->active_fe_index());
-
-            // make sparsity pattern for this cell
-            for (unsigned int i=0; i<dofs_per_face; ++i)
-              for (unsigned int j=0; j<dofs_per_face; ++j)
-                sparsity.add (dof_to_boundary_mapping[dofs_on_this_face[i]],
-                              dof_to_boundary_mapping[dofs_on_this_face[j]]);
-          }
-  }
-
-
-
-  template <class DH, class SparsityPattern>
-  void make_boundary_sparsity_pattern (
-    const DH                                        &dof,
-    const typename FunctionMap<DH::space_dimension>::type &boundary_indicators,
-    const std::vector<types::global_dof_index>                 &dof_to_boundary_mapping,
-    SparsityPattern                                 &sparsity)
-  {
-    if (DH::dimension == 1)
-      {
-        // first check left, then right boundary point
-        for (unsigned int direction=0; direction<2; ++direction)
-          {
-            // if this boundary is not requested, then go on with next one
-            if (boundary_indicators.find(direction) ==
-                boundary_indicators.end())
-              continue;
-
-            // find active cell at that boundary: first go to left/right,
-            // then to children
-            typename DH::level_cell_iterator cell = dof.begin(0);
-            while (!cell->at_boundary(direction))
-              cell = cell->neighbor(direction);
-            while (!cell->active())
-              cell = cell->child(direction);
-
-            const unsigned int dofs_per_vertex = cell->get_fe().dofs_per_vertex;
-            std::vector<types::global_dof_index> boundary_dof_boundary_indices (dofs_per_vertex);
-
-            // next get boundary mapped dof indices of boundary dofs
-            for (unsigned int i=0; i<dofs_per_vertex; ++i)
-              boundary_dof_boundary_indices[i]
-                = dof_to_boundary_mapping[cell->vertex_dof_index(direction,i)];
-
-            for (unsigned int i=0; i<dofs_per_vertex; ++i)
-              sparsity.add_entries (boundary_dof_boundary_indices[i],
-                                    boundary_dof_boundary_indices.begin(),
-                                    boundary_dof_boundary_indices.end());
-          };
-        return;
-      }
-
-    const types::global_dof_index n_dofs = dof.n_dofs();
-
-    AssertDimension (dof_to_boundary_mapping.size(), n_dofs);
-    Assert (boundary_indicators.find(numbers::internal_face_boundary_id) == boundary_indicators.end(),
-            typename DH::ExcInvalidBoundaryIndicator());
-    Assert (sparsity.n_rows() == dof.n_boundary_dofs (boundary_indicators),
-            ExcDimensionMismatch (sparsity.n_rows(), dof.n_boundary_dofs (boundary_indicators)));
-    Assert (sparsity.n_cols() == dof.n_boundary_dofs (boundary_indicators),
-            ExcDimensionMismatch (sparsity.n_cols(), dof.n_boundary_dofs (boundary_indicators)));
-#ifdef DEBUG
-    if (sparsity.n_rows() != 0)
-      {
-        types::global_dof_index max_element = 0;
-        for (std::vector<types::global_dof_index>::const_iterator i=dof_to_boundary_mapping.begin();
-             i!=dof_to_boundary_mapping.end(); ++i)
-          if ((*i != DH::invalid_dof_index) &&
-              (*i > max_element))
-            max_element = *i;
-        AssertDimension (max_element, sparsity.n_rows()-1);
-      };
-#endif
-
-    std::vector<types::global_dof_index> dofs_on_this_face;
-    dofs_on_this_face.reserve (max_dofs_per_face(dof));
-    typename DH::active_cell_iterator cell = dof.begin_active(),
-                                      endc = dof.end();
-    for (; cell!=endc; ++cell)
-      for (unsigned int f=0; f<GeometryInfo<DH::dimension>::faces_per_cell; ++f)
-        if (boundary_indicators.find(cell->face(f)->boundary_indicator()) !=
-            boundary_indicators.end())
-          {
-            const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
-            dofs_on_this_face.resize (dofs_per_face);
-            cell->face(f)->get_dof_indices (dofs_on_this_face,
-                                            cell->active_fe_index());
-
-            // make sparsity pattern for this cell
-            for (unsigned int i=0; i<dofs_per_face; ++i)
-              for (unsigned int j=0; j<dofs_per_face; ++j)
-                sparsity.add (dof_to_boundary_mapping[dofs_on_this_face[i]],
-                              dof_to_boundary_mapping[dofs_on_this_face[j]]);
-          }
-  }
-
-
-
-  template <class DH, class SparsityPattern>
-  void
-  make_flux_sparsity_pattern (const DH                  &dof,
-                              SparsityPattern           &sparsity,
-                              const ConstraintMatrix    &constraints,
-                              const bool                keep_constrained_dofs,
-                              const types::subdomain_id subdomain_id)
-
-  // TODO: QA: reduce the indentation level of this method..., Maier 2012
-
-  {
-    const types::global_dof_index n_dofs = dof.n_dofs();
-
-    AssertDimension (sparsity.n_rows(), n_dofs);
-    AssertDimension (sparsity.n_cols(), n_dofs);
-
-    // If we have a distributed::Triangulation only allow locally_owned
-    // subdomain. Not setting a subdomain is also okay, because we skip
-    // ghost cells in the loop below.
-    Assert (
-      (dof.get_tria().locally_owned_subdomain() == numbers::invalid_subdomain_id)
-      ||
-      (subdomain_id == numbers::invalid_subdomain_id)
-      ||
-      (subdomain_id == dof.get_tria().locally_owned_subdomain()),
-      ExcMessage ("For parallel::distributed::Triangulation objects and "
-                  "associated DoF handler objects, asking for any subdomain other "
-                  "than the locally owned one does not make sense."));
-
-    std::vector<types::global_dof_index> dofs_on_this_cell;
-    std::vector<types::global_dof_index> dofs_on_other_cell;
-    dofs_on_this_cell.reserve (max_dofs_per_cell(dof));
-    dofs_on_other_cell.reserve (max_dofs_per_cell(dof));
-    typename DH::active_cell_iterator cell = dof.begin_active(),
-                                      endc = dof.end();
-
-    // TODO: in an old implementation, we used user flags before to tag
-    // faces that were already touched. this way, we could reduce the work
-    // a little bit. now, we instead add only data from one side. this
-    // should be OK, but we need to actually verify it.
-
-    // In case we work with a distributed sparsity pattern of Trilinos
-    // type, we only have to do the work if the current cell is owned by
-    // the calling processor. Otherwise, just continue.
-    for (; cell!=endc; ++cell)
-      if (((subdomain_id == numbers::invalid_subdomain_id)
-           ||
-           (subdomain_id == cell->subdomain_id()))
-          &&
-          cell->is_locally_owned())
-        {
-          const unsigned int n_dofs_on_this_cell = cell->get_fe().dofs_per_cell;
-          dofs_on_this_cell.resize (n_dofs_on_this_cell);
-          cell->get_dof_indices (dofs_on_this_cell);
-
-          // make sparsity pattern for this cell. if no constraints pattern
-          // was given, then the following call acts as if simply no
-          // constraints existed
-          constraints.add_entries_local_to_global (dofs_on_this_cell,
-                                                   sparsity,
-                                                   keep_constrained_dofs);
-
-          for (unsigned int face = 0;
-               face < GeometryInfo<DH::dimension>::faces_per_cell;
-               ++face)
-            {
-              typename DH::face_iterator cell_face = cell->face(face);
-              if (! cell->at_boundary(face) )
-                {
-                  typename DH::level_cell_iterator neighbor = cell->neighbor(face);
-
-                  // in 1d, we do not need to worry whether the neighbor
-                  // might have children and then loop over those children.
-                  // rather, we may as well go straight to to cell behind
-                  // this particular cell's most terminal child
-                  if (DH::dimension==1)
-                    while (neighbor->has_children())
-                      neighbor = neighbor->child(face==0 ? 1 : 0);
-
-                  if (neighbor->has_children())
-                    {
-                      for (unsigned int sub_nr = 0;
-                           sub_nr != cell_face->number_of_children();
-                           ++sub_nr)
-                        {
-                          const typename DH::level_cell_iterator
-                          sub_neighbor
-                            = cell->neighbor_child_on_subface (face, sub_nr);
-
-                          const unsigned int n_dofs_on_neighbor
-                            = sub_neighbor->get_fe().dofs_per_cell;
-                          dofs_on_other_cell.resize (n_dofs_on_neighbor);
-                          sub_neighbor->get_dof_indices (dofs_on_other_cell);
-
-                          constraints.add_entries_local_to_global
-                          (dofs_on_this_cell, dofs_on_other_cell,
-                           sparsity, keep_constrained_dofs);
-                          constraints.add_entries_local_to_global
-                          (dofs_on_other_cell, dofs_on_this_cell,
-                           sparsity, keep_constrained_dofs);
-                        }
-                    }
-                  else
-                    {
-                      // Refinement edges are taken care of by coarser
-                      // cells
-
-                      // TODO: in the distributed case, we miss out the
-                      // constraints when the neighbor cell is coarser, but
-                      // only the current cell is owned locally!
-                      if (cell->neighbor_is_coarser(face))
-                        continue;
-
-                      const unsigned int n_dofs_on_neighbor
-                        = neighbor->get_fe().dofs_per_cell;
-                      dofs_on_other_cell.resize (n_dofs_on_neighbor);
-
-                      neighbor->get_dof_indices (dofs_on_other_cell);
-
-                      constraints.add_entries_local_to_global
-                      (dofs_on_this_cell, dofs_on_other_cell,
-                       sparsity, keep_constrained_dofs);
-
-                      // only need to add these in case the neighbor cell
-                      // is not locally owned - otherwise, we touch each
-                      // face twice and hence put the indices the other way
-                      // around
-                      if (!cell->neighbor(face)->active()
-                          ||
-                          (cell->neighbor(face)->subdomain_id() !=
-                           cell->subdomain_id()))
-                        constraints.add_entries_local_to_global
-                        (dofs_on_other_cell, dofs_on_this_cell,
-                         sparsity, keep_constrained_dofs);
-                    }
-                }
-            }
-        }
-  }
-
-
-
-  template <class DH, class SparsityPattern>
-  void
-  make_flux_sparsity_pattern (const DH        &dof,
-                              SparsityPattern &sparsity)
-  {
-    ConstraintMatrix constraints;
-    make_flux_sparsity_pattern (dof, sparsity, constraints);
-  }
-
-
-
-  template <int dim, int spacedim>
-  Table<2,Coupling>
-  dof_couplings_from_component_couplings (const FiniteElement<dim,spacedim> &fe,
-                                          const Table<2,Coupling> &component_couplings)
-  {
-    Assert(component_couplings.n_rows() == fe.n_components(),
-           ExcDimensionMismatch(component_couplings.n_rows(),
-                                fe.n_components()));
-    Assert(component_couplings.n_cols() == fe.n_components(),
-           ExcDimensionMismatch(component_couplings.n_cols(),
-                                fe.n_components()));
-
-    const unsigned int n_dofs = fe.dofs_per_cell;
-
-    Table<2,Coupling> dof_couplings (n_dofs, n_dofs);
-
-    for (unsigned int i=0; i<n_dofs; ++i)
-      {
-        const unsigned int ii
-          = (fe.is_primitive(i) ?
-             fe.system_to_component_index(i).first
-             :
-             fe.get_nonzero_components(i).first_selected_component()
-            );
-        Assert (ii < fe.n_components(), ExcInternalError());
-
-        for (unsigned int j=0; j<n_dofs; ++j)
-          {
-            const unsigned int jj
-              = (fe.is_primitive(j) ?
-                 fe.system_to_component_index(j).first
-                 :
-                 fe.get_nonzero_components(j).first_selected_component()
-                );
-            Assert (jj < fe.n_components(), ExcInternalError());
-
-            dof_couplings(i,j) = component_couplings(ii,jj);
-          }
-      }
-    return dof_couplings;
-  }
-
-
-
-  template <int dim, int spacedim>
-  std::vector<Table<2,Coupling> >
-  dof_couplings_from_component_couplings
-  (const hp::FECollection<dim,spacedim> &fe,
-   const Table<2,Coupling> &component_couplings)
-  {
-    std::vector<Table<2,Coupling> > return_value (fe.size());
-    for (unsigned int i=0; i<fe.size(); ++i)
-      return_value[i]
-        = dof_couplings_from_component_couplings(fe[i], component_couplings);
-
-    return return_value;
-  }
-
-
-
-  namespace internal
-  {
-    namespace
-    {
-
-      // implementation of the same function in namespace DoFTools for
-      // non-hp DoFHandlers
-      template <class DH, class SparsityPattern>
-      void
-      make_flux_sparsity_pattern (const DH                &dof,
-                                  SparsityPattern         &sparsity,
-                                  const Table<2,Coupling> &int_mask,
-                                  const Table<2,Coupling> &flux_mask)
-      {
-        const FiniteElement<DH::dimension,DH::space_dimension> &fe = dof.get_fe();
-
-        std::vector<types::global_dof_index> dofs_on_this_cell(fe.dofs_per_cell);
-        std::vector<types::global_dof_index> dofs_on_other_cell(fe.dofs_per_cell);
-
-        const Table<2,Coupling>
-        int_dof_mask  = dof_couplings_from_component_couplings(fe, int_mask),
-        flux_dof_mask = dof_couplings_from_component_couplings(fe, flux_mask);
-
-        Table<2,bool> support_on_face(fe.dofs_per_cell,
-                                      GeometryInfo<DH::dimension>::faces_per_cell);
-        for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
-          for (unsigned int f=0; f<GeometryInfo<DH::dimension>::faces_per_cell; ++f)
-            support_on_face(i,f) = fe.has_support_on_face(i,f);
-
-        typename DH::active_cell_iterator cell = dof.begin_active(),
-                                          endc = dof.end();
-        for (; cell!=endc; ++cell)
-          if (cell->is_locally_owned())
-            {
-              cell->get_dof_indices (dofs_on_this_cell);
-              // make sparsity pattern for this cell
-              for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
-                for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
-                  if (int_dof_mask(i,j) != none)
-                    sparsity.add (dofs_on_this_cell[i],
-                                  dofs_on_this_cell[j]);
-
-              // Loop over all interior neighbors
-              for (unsigned int face = 0;
-                   face < GeometryInfo<DH::dimension>::faces_per_cell;
-                   ++face)
-                {
-                  const typename DH::face_iterator
-                  cell_face = cell->face(face);
-                  if (cell_face->user_flag_set ())
-                    continue;
-
-                  if (cell->at_boundary (face) )
-                    {
-                      for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
-                        {
-                          const bool i_non_zero_i = support_on_face (i, face);
-                          for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
-                            {
-                              const bool j_non_zero_i = support_on_face (j, face);
-
-                              if ((flux_dof_mask(i,j) == always)
-                                  ||
-                                  (flux_dof_mask(i,j) == nonzero
-                                   &&
-                                   i_non_zero_i
-                                   &&
-                                   j_non_zero_i))
-                                sparsity.add (dofs_on_this_cell[i],
-                                              dofs_on_this_cell[j]);
-                            }
-                        }
-                    }
-                  else
-                    {
-                      typename DH::level_cell_iterator
-                      neighbor = cell->neighbor(face);
-                      // Refinement edges are taken care of by coarser
-                      // cells
-                      if (cell->neighbor_is_coarser(face))
-                        continue;
-
-                      typename DH::face_iterator cell_face = cell->face(face);
-                      const unsigned int
-                      neighbor_face = cell->neighbor_of_neighbor(face);
-
-                      if (cell_face->has_children())
-                        {
-                          for (unsigned int sub_nr = 0;
-                               sub_nr != cell_face->n_children();
-                               ++sub_nr)
-                            {
-                              const typename DH::level_cell_iterator
-                              sub_neighbor
-                                = cell->neighbor_child_on_subface (face, sub_nr);
-
-                              sub_neighbor->get_dof_indices (dofs_on_other_cell);
-                              for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
-                                {
-                                  const bool i_non_zero_i = support_on_face (i, face);
-                                  const bool i_non_zero_e = support_on_face (i, neighbor_face);
-                                  for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
-                                    {
-                                      const bool j_non_zero_i = support_on_face (j, face);
-                                      const bool j_non_zero_e = support_on_face (j, neighbor_face);
-
-                                      if (flux_dof_mask(i,j) == always)
-                                        {
-                                          sparsity.add (dofs_on_this_cell[i],
-                                                        dofs_on_other_cell[j]);
-                                          sparsity.add (dofs_on_other_cell[i],
-                                                        dofs_on_this_cell[j]);
-                                          sparsity.add (dofs_on_this_cell[i],
-                                                        dofs_on_this_cell[j]);
-                                          sparsity.add (dofs_on_other_cell[i],
-                                                        dofs_on_other_cell[j]);
-                                        }
-                                      else if (flux_dof_mask(i,j) == nonzero)
-                                        {
-                                          if (i_non_zero_i && j_non_zero_e)
-                                            sparsity.add (dofs_on_this_cell[i],
-                                                          dofs_on_other_cell[j]);
-                                          if (i_non_zero_e && j_non_zero_i)
-                                            sparsity.add (dofs_on_other_cell[i],
-                                                          dofs_on_this_cell[j]);
-                                          if (i_non_zero_i && j_non_zero_i)
-                                            sparsity.add (dofs_on_this_cell[i],
-                                                          dofs_on_this_cell[j]);
-                                          if (i_non_zero_e && j_non_zero_e)
-                                            sparsity.add (dofs_on_other_cell[i],
-                                                          dofs_on_other_cell[j]);
-                                        }
-
-                                      if (flux_dof_mask(j,i) == always)
-                                        {
-                                          sparsity.add (dofs_on_this_cell[j],
-                                                        dofs_on_other_cell[i]);
-                                          sparsity.add (dofs_on_other_cell[j],
-                                                        dofs_on_this_cell[i]);
-                                          sparsity.add (dofs_on_this_cell[j],
-                                                        dofs_on_this_cell[i]);
-                                          sparsity.add (dofs_on_other_cell[j],
-                                                        dofs_on_other_cell[i]);
-                                        }
-                                      else if (flux_dof_mask(j,i) == nonzero)
-                                        {
-                                          if (j_non_zero_i && i_non_zero_e)
-                                            sparsity.add (dofs_on_this_cell[j],
-                                                          dofs_on_other_cell[i]);
-                                          if (j_non_zero_e && i_non_zero_i)
-                                            sparsity.add (dofs_on_other_cell[j],
-                                                          dofs_on_this_cell[i]);
-                                          if (j_non_zero_i && i_non_zero_i)
-                                            sparsity.add (dofs_on_this_cell[j],
-                                                          dofs_on_this_cell[i]);
-                                          if (j_non_zero_e && i_non_zero_e)
-                                            sparsity.add (dofs_on_other_cell[j],
-                                                          dofs_on_other_cell[i]);
-                                        }
-                                    }
-                                }
-                              sub_neighbor->face(neighbor_face)->set_user_flag ();
-                            }
-                        }
-                      else
-                        {
-                          neighbor->get_dof_indices (dofs_on_other_cell);
-                          for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
-                            {
-                              const bool i_non_zero_i = support_on_face (i, face);
-                              const bool i_non_zero_e = support_on_face (i, neighbor_face);
-                              for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
-                                {
-                                  const bool j_non_zero_i = support_on_face (j, face);
-                                  const bool j_non_zero_e = support_on_face (j, neighbor_face);
-                                  if (flux_dof_mask(i,j) == always)
-                                    {
-                                      sparsity.add (dofs_on_this_cell[i],
-                                                    dofs_on_other_cell[j]);
-                                      sparsity.add (dofs_on_other_cell[i],
-                                                    dofs_on_this_cell[j]);
-                                      sparsity.add (dofs_on_this_cell[i],
-                                                    dofs_on_this_cell[j]);
-                                      sparsity.add (dofs_on_other_cell[i],
-                                                    dofs_on_other_cell[j]);
-                                    }
-                                  if (flux_dof_mask(i,j) == nonzero)
-                                    {
-                                      if (i_non_zero_i && j_non_zero_e)
-                                        sparsity.add (dofs_on_this_cell[i],
-                                                      dofs_on_other_cell[j]);
-                                      if (i_non_zero_e && j_non_zero_i)
-                                        sparsity.add (dofs_on_other_cell[i],
-                                                      dofs_on_this_cell[j]);
-                                      if (i_non_zero_i && j_non_zero_i)
-                                        sparsity.add (dofs_on_this_cell[i],
-                                                      dofs_on_this_cell[j]);
-                                      if (i_non_zero_e && j_non_zero_e)
-                                        sparsity.add (dofs_on_other_cell[i],
-                                                      dofs_on_other_cell[j]);
-                                    }
-
-                                  if (flux_dof_mask(j,i) == always)
-                                    {
-                                      sparsity.add (dofs_on_this_cell[j],
-                                                    dofs_on_other_cell[i]);
-                                      sparsity.add (dofs_on_other_cell[j],
-                                                    dofs_on_this_cell[i]);
-                                      sparsity.add (dofs_on_this_cell[j],
-                                                    dofs_on_this_cell[i]);
-                                      sparsity.add (dofs_on_other_cell[j],
-                                                    dofs_on_other_cell[i]);
-                                    }
-                                  if (flux_dof_mask(j,i) == nonzero)
-                                    {
-                                      if (j_non_zero_i && i_non_zero_e)
-                                        sparsity.add (dofs_on_this_cell[j],
-                                                      dofs_on_other_cell[i]);
-                                      if (j_non_zero_e && i_non_zero_i)
-                                        sparsity.add (dofs_on_other_cell[j],
-                                                      dofs_on_this_cell[i]);
-                                      if (j_non_zero_i && i_non_zero_i)
-                                        sparsity.add (dofs_on_this_cell[j],
-                                                      dofs_on_this_cell[i]);
-                                      if (j_non_zero_e && i_non_zero_e)
-                                        sparsity.add (dofs_on_other_cell[j],
-                                                      dofs_on_other_cell[i]);
-                                    }
-                                }
-                            }
-                          neighbor->face(neighbor_face)->set_user_flag ();
-                        }
-                    }
-                }
-            }
-      }
-
-
-      // implementation of the same function in namespace DoFTools for
-      // non-hp DoFHandlers
-      template <int dim, int spacedim, class SparsityPattern>
-      void
-      make_flux_sparsity_pattern (const dealii::hp::DoFHandler<dim,spacedim> &dof,
-                                  SparsityPattern                           &sparsity,
-                                  const Table<2,Coupling> &int_mask,
-                                  const Table<2,Coupling> &flux_mask)
-      {
-        // while the implementation above is quite optimized and caches a
-        // lot of data (see e.g. the int/flux_dof_mask tables), this is no
-        // longer practical for the hp version since we would have to have
-        // it for all combinations of elements in the hp::FECollection.
-        // consequently, the implementation here is simpler and probably
-        // less efficient but at least readable...
-
-        const dealii::hp::FECollection<dim,spacedim> &fe = dof.get_fe();
-
-        std::vector<types::global_dof_index> dofs_on_this_cell(DoFTools::max_dofs_per_cell(dof));
-        std::vector<types::global_dof_index> dofs_on_other_cell(DoFTools::max_dofs_per_cell(dof));
-
-        const std::vector<Table<2,Coupling> >
-        int_dof_mask
-          = dof_couplings_from_component_couplings(fe, int_mask);
-
-        typename dealii::hp::DoFHandler<dim,spacedim>::active_cell_iterator
-        cell = dof.begin_active(),
-        endc = dof.end();
-        for (; cell!=endc; ++cell)
-          {
-            dofs_on_this_cell.resize (cell->get_fe().dofs_per_cell);
-            cell->get_dof_indices (dofs_on_this_cell);
-
-            // make sparsity pattern for this cell
-            for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
-              for (unsigned int j=0; j<cell->get_fe().dofs_per_cell; ++j)
-                if (int_dof_mask[cell->active_fe_index()](i,j) != none)
-                  sparsity.add (dofs_on_this_cell[i],
-                                dofs_on_this_cell[j]);
-
-            // Loop over all interior neighbors
-            for (unsigned int face = 0;
-                 face < GeometryInfo<dim>::faces_per_cell;
-                 ++face)
-              {
-                const typename dealii::hp::DoFHandler<dim,spacedim>::face_iterator
-                cell_face = cell->face(face);
-                if (cell_face->user_flag_set ())
-                  continue;
-
-                if (cell->at_boundary (face) )
-                  {
-                    for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
-                      for (unsigned int j=0; j<cell->get_fe().dofs_per_cell; ++j)
-                        if ((flux_mask(cell->get_fe().system_to_component_index(i).first,
-                                       cell->get_fe().system_to_component_index(j).first)
-                             == always)
-                            ||
-                            (flux_mask(cell->get_fe().system_to_component_index(i).first,
-                                       cell->get_fe().system_to_component_index(j).first)
-                             == nonzero))
-                          sparsity.add (dofs_on_this_cell[i],
-                                        dofs_on_this_cell[j]);
-                  }
-                else
-                  {
-                    typename dealii::hp::DoFHandler<dim,spacedim>::level_cell_iterator
-                    neighbor = cell->neighbor(face);
-
-                    // Refinement edges are taken care of by coarser cells
-                    if (cell->neighbor_is_coarser(face))
-                      continue;
-
-                    typename dealii::hp::DoFHandler<dim,spacedim>::face_iterator
-                    cell_face = cell->face(face);
-                    const unsigned int
-                    neighbor_face = cell->neighbor_of_neighbor(face);
-
-                    if (cell_face->has_children())
-                      {
-                        for (unsigned int sub_nr = 0;
-                             sub_nr != cell_face->n_children();
-                             ++sub_nr)
-                          {
-                            const typename dealii::hp::DoFHandler<dim,spacedim>::level_cell_iterator
-                            sub_neighbor
-                              = cell->neighbor_child_on_subface (face, sub_nr);
-
-                            dofs_on_other_cell.resize (sub_neighbor->get_fe().dofs_per_cell);
-                            sub_neighbor->get_dof_indices (dofs_on_other_cell);
-                            for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
-                              {
-                                for (unsigned int j=0; j<sub_neighbor->get_fe().dofs_per_cell;
-                                     ++j)
-                                  {
-                                    if ((flux_mask(cell->get_fe().system_to_component_index(i).first,
-                                                   sub_neighbor->get_fe().system_to_component_index(j).first)
-                                         == always)
-                                        ||
-                                        (flux_mask(cell->get_fe().system_to_component_index(i).first,
-                                                   sub_neighbor->get_fe().system_to_component_index(j).first)
-                                         == nonzero))
-                                      {
-                                        sparsity.add (dofs_on_this_cell[i],
-                                                      dofs_on_other_cell[j]);
-                                        sparsity.add (dofs_on_other_cell[i],
-                                                      dofs_on_this_cell[j]);
-                                        sparsity.add (dofs_on_this_cell[i],
-                                                      dofs_on_this_cell[j]);
-                                        sparsity.add (dofs_on_other_cell[i],
-                                                      dofs_on_other_cell[j]);
-                                      }
-
-                                    if ((flux_mask(sub_neighbor->get_fe().system_to_component_index(j).first,
-                                                   cell->get_fe().system_to_component_index(i).first)
-                                         == always)
-                                        ||
-                                        (flux_mask(sub_neighbor->get_fe().system_to_component_index(j).first,
-                                                   cell->get_fe().system_to_component_index(i).first)
-                                         == nonzero))
-                                      {
-                                        sparsity.add (dofs_on_this_cell[j],
-                                                      dofs_on_other_cell[i]);
-                                        sparsity.add (dofs_on_other_cell[j],
-                                                      dofs_on_this_cell[i]);
-                                        sparsity.add (dofs_on_this_cell[j],
-                                                      dofs_on_this_cell[i]);
-                                        sparsity.add (dofs_on_other_cell[j],
-                                                      dofs_on_other_cell[i]);
-                                      }
-                                  }
-                              }
-                            sub_neighbor->face(neighbor_face)->set_user_flag ();
-                          }
-                      }
-                    else
-                      {
-                        dofs_on_other_cell.resize (neighbor->get_fe().dofs_per_cell);
-                        neighbor->get_dof_indices (dofs_on_other_cell);
-                        for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
-                          {
-                            for (unsigned int j=0; j<neighbor->get_fe().dofs_per_cell; ++j)
-                              {
-                                if ((flux_mask(cell->get_fe().system_to_component_index(i).first,
-                                               neighbor->get_fe().system_to_component_index(j).first)
-                                     == always)
-                                    ||
-                                    (flux_mask(cell->get_fe().system_to_component_index(i).first,
-                                               neighbor->get_fe().system_to_component_index(j).first)
-                                     == nonzero))
-                                  {
-                                    sparsity.add (dofs_on_this_cell[i],
-                                                  dofs_on_other_cell[j]);
-                                    sparsity.add (dofs_on_other_cell[i],
-                                                  dofs_on_this_cell[j]);
-                                    sparsity.add (dofs_on_this_cell[i],
-                                                  dofs_on_this_cell[j]);
-                                    sparsity.add (dofs_on_other_cell[i],
-                                                  dofs_on_other_cell[j]);
-                                  }
-
-                                if ((flux_mask(neighbor->get_fe().system_to_component_index(j).first,
-                                               cell->get_fe().system_to_component_index(i).first)
-                                     == always)
-                                    ||
-                                    (flux_mask(neighbor->get_fe().system_to_component_index(j).first,
-                                               cell->get_fe().system_to_component_index(i).first)
-                                     == nonzero))
-                                  {
-                                    sparsity.add (dofs_on_this_cell[j],
-                                                  dofs_on_other_cell[i]);
-                                    sparsity.add (dofs_on_other_cell[j],
-                                                  dofs_on_this_cell[i]);
-                                    sparsity.add (dofs_on_this_cell[j],
-                                                  dofs_on_this_cell[i]);
-                                    sparsity.add (dofs_on_other_cell[j],
-                                                  dofs_on_other_cell[i]);
-                                  }
-                              }
-                          }
-                        neighbor->face(neighbor_face)->set_user_flag ();
-                      }
-                  }
-              }
-          }
-      }
-    }
-
-  }
-
-
-
-
-  template <class DH, class SparsityPattern>
-  void
-  make_flux_sparsity_pattern (const DH                &dof,
-                              SparsityPattern         &sparsity,
-                              const Table<2,Coupling> &int_mask,
-                              const Table<2,Coupling> &flux_mask)
-  {
-    // do the error checking and frame code here, and then pass on to more
-    // specialized functions in the internal namespace
-    const types::global_dof_index n_dofs = dof.n_dofs();
-    const unsigned int n_comp = dof.get_fe().n_components();
-
-    Assert (sparsity.n_rows() == n_dofs,
-            ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
-    Assert (sparsity.n_cols() == n_dofs,
-            ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
-    Assert (int_mask.n_rows() == n_comp,
-            ExcDimensionMismatch (int_mask.n_rows(), n_comp));
-    Assert (int_mask.n_cols() == n_comp,
-            ExcDimensionMismatch (int_mask.n_cols(), n_comp));
-    Assert (flux_mask.n_rows() == n_comp,
-            ExcDimensionMismatch (flux_mask.n_rows(), n_comp));
-    Assert (flux_mask.n_cols() == n_comp,
-            ExcDimensionMismatch (flux_mask.n_cols(), n_comp));
-
-    // Clear user flags because we will need them. But first we save them
-    // and make sure that we restore them later such that at the end of
-    // this function the Triangulation will be in the same state as it was
-    // at the beginning of this function.
-    std::vector<bool> user_flags;
-    dof.get_tria().save_user_flags(user_flags);
-    const_cast<Triangulation<DH::dimension,DH::space_dimension> &>(dof.get_tria()).clear_user_flags ();
-
-    internal::make_flux_sparsity_pattern (dof, sparsity,
-                                          int_mask, flux_mask);
-
-    // finally restore the user flags
-    const_cast<Triangulation<DH::dimension,DH::space_dimension> &>(dof.get_tria()).load_user_flags(user_flags);
-  }
-
-
-
-
-  namespace internal
-  {
-    namespace
-    {
-      inline bool
-      check_master_dof_list (const FullMatrix<double> &face_interpolation_matrix,
-                             const std::vector<types::global_dof_index> &master_dof_list)
-      {
-        const unsigned int N = master_dof_list.size();
-
-        FullMatrix<double> tmp (N,N);
-        for (unsigned int i=0; i<N; ++i)
-          for (unsigned int j=0; j<N; ++j)
-            tmp(i,j) = face_interpolation_matrix (master_dof_list[i], j);
-
-        // then use the algorithm from FullMatrix::gauss_jordan on this
-        // matrix to find out whether it is singular. the algorithm there
-        // does piviting and at the end swaps rows back into their proper
-        // order -- we omit this step here, since we don't care about the
-        // inverse matrix, all we care about is whether the matrix is
-        // regular or singular
-
-        // first get an estimate of the size of the elements of this
-        // matrix, for later checks whether the pivot element is large
-        // enough, or whether we have to fear that the matrix is not
-        // regular
-        double diagonal_sum = 0;
-        for (unsigned int i=0; i<N; ++i)
-          diagonal_sum += std::fabs(tmp(i,i));
-        const double typical_diagonal_element = diagonal_sum/N;
-
-        // initialize the array that holds the permutations that we find
-        // during pivot search
-        std::vector<unsigned int> p(N);
-        for (unsigned int i=0; i<N; ++i)
-          p[i] = i;
-
-        for (unsigned int j=0; j<N; ++j)
-          {
-            // pivot search: search that part of the line on and right of
-            // the diagonal for the largest element
-            double       max = std::fabs(tmp(j,j));
-            unsigned int r   = j;
-            for (unsigned int i=j+1; i<N; ++i)
-              {
-                if (std::fabs(tmp(i,j)) > max)
-                  {
-                    max = std::fabs(tmp(i,j));
-                    r = i;
-                  }
-              }
-            // check whether the pivot is too small. if that is the case,
-            // then the matrix is singular and we shouldn't use this set of
-            // master dofs
-            if (max < 1.e-12*typical_diagonal_element)
-              return false;
-
-            // row interchange
-            if (r>j)
-              {
-                for (unsigned int k=0; k<N; ++k)
-                  std::swap (tmp(j,k), tmp(r,k));
-
-                std::swap (p[j], p[r]);
-              }
-
-            // transformation
-            const double hr = 1./tmp(j,j);
-            tmp(j,j) = hr;
-            for (unsigned int k=0; k<N; ++k)
-              {
-                if (k==j) continue;
-                for (unsigned int i=0; i<N; ++i)
-                  {
-                    if (i==j) continue;
-                    tmp(i,k) -= tmp(i,j)*tmp(j,k)*hr;
-                  }
-              }
-            for (unsigned int i=0; i<N; ++i)
-              {
-                tmp(i,j) *= hr;
-                tmp(j,i) *= -hr;
-              }
-            tmp(j,j) = hr;
-          }
-
-        // everything went fine, so we can accept this set of master dofs
-        // (at least as far as they have already been collected)
-        return true;
-      }
-
-
-
-      /**
-       * When restricting, on a face, the degrees of freedom of fe1 to the
-       * space described by fe2 (for example for the complex case described
-       * in the @ref hp_paper "hp paper"), we have to select
-       * fe2.dofs_per_face out of the fe1.dofs_per_face face DoFs as the
-       * master DoFs, and the rest become slave dofs. This function selects
-       * which ones will be masters, and which ones will be slaves.
-       *
-       * The function assumes that master_dofs already has size
-       * fe1.dofs_per_face. After the function, exactly fe2.dofs_per_face
-       * entries will be true.
-       *
-       * The function is a bit complicated since it has to figure out a set
-       * a DoFs so that the corresponding rows in the face interpolation
-       * matrix are all linearly independent. we have a good heuristic (see
-       * the function body) for selecting these rows, but there are cases
-       * where this fails and we have to pick them differently. what we do
-       * is to run the heuristic and then go back to determine whether we
-       * have a set of rows with full row rank. if this isn't the case, go
-       * back and select dofs differently
-       */
-      template <int dim, int spacedim>
-      void
-      select_master_dofs_for_face_restriction (const FiniteElement<dim,spacedim> &fe1,
-                                               const FiniteElement<dim,spacedim> &fe2,
-                                               const FullMatrix<double> &face_interpolation_matrix,
-                                               std::vector<bool>        &master_dof_mask)
-      {
-        Assert (fe1.dofs_per_face >= fe2.dofs_per_face,
-                ExcInternalError());
-        AssertDimension (master_dof_mask.size(), fe1.dofs_per_face);
-
-        Assert (fe2.dofs_per_vertex <= fe1.dofs_per_vertex,
-                ExcInternalError());
-        Assert (fe2.dofs_per_line <= fe1.dofs_per_line,
-                ExcInternalError());
-        Assert ((dim < 3)
-                ||
-                (fe2.dofs_per_quad <= fe1.dofs_per_quad),
-                ExcInternalError());
-
-        // the idea here is to designate as many DoFs in fe1 per object
-        // (vertex, line, quad) as master as there are such dofs in fe2
-        // (indices are int, because we want to avoid the 'unsigned int < 0
-        // is always false warning for the cases at the bottom in 1d and
-        // 2d)
-        //
-        // as mentioned in the paper, it is not always easy to find a set
-        // of master dofs that produces an invertible matrix. to this end,
-        // we check in each step whether the matrix is still invertible and
-        // simply discard this dof if the matrix is not invertible anymore.
-        //
-        // the cases where we did have trouble in the past were with adding
-        // more quad dofs when Q3 and Q4 elements meet at a refined face in
-        // 3d (see the hp/crash_12 test that tests that we can do exactly
-        // this, and failed before we had code to compensate for this
-        // case). the other case are system elements: if we have say a Q1Q2
-        // vs a Q2Q3 element, then we can't just take all master dofs on a
-        // line from a single base element, since the shape functions of
-        // that base element are independent of that of the other one. this
-        // latter case shows up when running hp/hp_constraints_q_system_06
-
-        std::vector<types::global_dof_index> master_dof_list;
-        unsigned int index = 0;
-        for (int v=0;
-             v<static_cast<signed int>(GeometryInfo<dim>::vertices_per_face);
-             ++v)
-          {
-            unsigned int dofs_added = 0;
-            unsigned int i          = 0;
-            while (dofs_added < fe2.dofs_per_vertex)
-              {
-                // make sure that we were able to find a set of master dofs
-                // and that the code down below didn't just reject all our
-                // efforts
-                Assert (i < fe1.dofs_per_vertex,
-                        ExcInternalError());
-
-                // tentatively push this vertex dof
-                master_dof_list.push_back (index+i);
-
-                // then see what happens. if it succeeds, fine
-                if (check_master_dof_list (face_interpolation_matrix,
-                                           master_dof_list)
-                    == true)
-                  ++dofs_added;
-                else
-                  // well, it didn't. simply pop that dof from the list
-                  // again and try with the next dof
-                  master_dof_list.pop_back ();
-
-                // forward counter by one
-                ++i;
-              }
-            index += fe1.dofs_per_vertex;
-          }
-
-        for (int l=0;
-             l<static_cast<signed int>(GeometryInfo<dim>::lines_per_face);
-             ++l)
-          {
-            // same algorithm as above
-            unsigned int dofs_added = 0;
-            unsigned int i          = 0;
-            while (dofs_added < fe2.dofs_per_line)
-              {
-                Assert (i < fe1.dofs_per_line,
-                        ExcInternalError());
-
-                master_dof_list.push_back (index+i);
-                if (check_master_dof_list (face_interpolation_matrix,
-                                           master_dof_list)
-                    == true)
-                  ++dofs_added;
-                else
-                  master_dof_list.pop_back ();
-
-                ++i;
-              }
-            index += fe1.dofs_per_line;
-          }
-
-        for (int q=0;
-             q<static_cast<signed int>(GeometryInfo<dim>::quads_per_face);
-             ++q)
-          {
-            // same algorithm as above
-            unsigned int dofs_added = 0;
-            unsigned int i          = 0;
-            while (dofs_added < fe2.dofs_per_quad)
-              {
-                Assert (i < fe1.dofs_per_quad,
-                        ExcInternalError());
-
-                master_dof_list.push_back (index+i);
-                if (check_master_dof_list (face_interpolation_matrix,
-                                           master_dof_list)
-                    == true)
-                  ++dofs_added;
-                else
-                  master_dof_list.pop_back ();
-
-                ++i;
-              }
-            index += fe1.dofs_per_quad;
-          }
-
-        AssertDimension (index, fe1.dofs_per_face);
-        AssertDimension (master_dof_list.size(), fe2.dofs_per_face);
-
-        // finally copy the list into the mask
-        std::fill (master_dof_mask.begin(), master_dof_mask.end(), false);
-        for (std::vector<types::global_dof_index>::const_iterator i=master_dof_list.begin();
-             i!=master_dof_list.end(); ++i)
-          master_dof_mask[*i] = true;
-      }
-
-
-
-      /**
-       * Make sure that the mask exists that determines which dofs will be
-       * the masters on refined faces where an fe1 and a fe2 meet.
-       */
-      template <int dim, int spacedim>
-      void
-      ensure_existence_of_master_dof_mask (const FiniteElement<dim,spacedim> &fe1,
-                                           const FiniteElement<dim,spacedim> &fe2,
-                                           const FullMatrix<double> &face_interpolation_matrix,
-                                           std_cxx1x::shared_ptr<std::vector<bool> > &master_dof_mask)
-      {
-        if (master_dof_mask == std_cxx1x::shared_ptr<std::vector<bool> >())
-          {
-            master_dof_mask = std_cxx1x::shared_ptr<std::vector<bool> >
-                              (new std::vector<bool> (fe1.dofs_per_face));
-            select_master_dofs_for_face_restriction (fe1,
-                                                     fe2,
-                                                     face_interpolation_matrix,
-                                                     *master_dof_mask);
-          }
-      }
-
-
-
-      /**
-       * Make sure that the given @p face_interpolation_matrix pointer
-       * points to a valid matrix. If the pointer is zero beforehand,
-       * create an entry with the correct data. If it is nonzero, don't
-       * touch it.
-       */
-      template <int dim, int spacedim>
-      void
-      ensure_existence_of_face_matrix (const FiniteElement<dim,spacedim> &fe1,
-                                       const FiniteElement<dim,spacedim> &fe2,
-                                       std_cxx1x::shared_ptr<FullMatrix<double> > &matrix)
-      {
-        if (matrix == std_cxx1x::shared_ptr<FullMatrix<double> >())
-          {
-            matrix = std_cxx1x::shared_ptr<FullMatrix<double> >
-                     (new FullMatrix<double> (fe2.dofs_per_face,
-                                              fe1.dofs_per_face));
-            fe1.get_face_interpolation_matrix (fe2,
-                                               *matrix);
-          }
-      }
-
-
-
-      /**
-       * Same, but for subface interpolation matrices.
-       */
-      template <int dim, int spacedim>
-      void
-      ensure_existence_of_subface_matrix (const FiniteElement<dim,spacedim> &fe1,
-                                          const FiniteElement<dim,spacedim> &fe2,
-                                          const unsigned int        subface,
-                                          std_cxx1x::shared_ptr<FullMatrix<double> > &matrix)
-      {
-        if (matrix == std_cxx1x::shared_ptr<FullMatrix<double> >())
-          {
-            matrix = std_cxx1x::shared_ptr<FullMatrix<double> >
-                     (new FullMatrix<double> (fe2.dofs_per_face,
-                                              fe1.dofs_per_face));
-            fe1.get_subface_interpolation_matrix (fe2,
-                                                  subface,
-                                                  *matrix);
-          }
-      }
-
-
-
-      /**
-       * Given the face interpolation matrix between two elements, split it
-       * into its master and slave parts and invert the master part as
-       * explained in the @ref hp_paper "hp paper".
-       */
-      void
-      ensure_existence_of_split_face_matrix (const FullMatrix<double> &face_interpolation_matrix,
-                                             const std::vector<bool> &master_dof_mask,
-                                             std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > > &split_matrix)
-      {
-        AssertDimension (master_dof_mask.size(), face_interpolation_matrix.m());
-        Assert (std::count (master_dof_mask.begin(), master_dof_mask.end(), true) ==
-                static_cast<signed int>(face_interpolation_matrix.n()),
-                ExcInternalError());
-
-        if (split_matrix ==
-            std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > >())
-          {
-            split_matrix
-              = std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > >
-                (new std::pair<FullMatrix<double>,FullMatrix<double> >());
-
-            const unsigned int n_master_dofs = face_interpolation_matrix.n();
-            const unsigned int n_dofs        = face_interpolation_matrix.m();
-
-            Assert (n_master_dofs <= n_dofs, ExcInternalError());
-
-            // copy and invert the master
-            // component, copy the slave
-            // component
-            split_matrix->first.reinit (n_master_dofs, n_master_dofs);
-            split_matrix->second.reinit (n_dofs-n_master_dofs, n_master_dofs);
-
-            unsigned int nth_master_dof = 0,
-                         nth_slave_dof  = 0;
-
-            for (unsigned int i=0; i<n_dofs; ++i)
-              if (master_dof_mask[i] == true)
-                {
-                  for (unsigned int j=0; j<n_master_dofs; ++j)
-                    split_matrix->first(nth_master_dof,j)
-                      = face_interpolation_matrix(i,j);
-                  ++nth_master_dof;
-                }
-              else
-                {
-                  for (unsigned int j=0; j<n_master_dofs; ++j)
-                    split_matrix->second(nth_slave_dof,j)
-                      = face_interpolation_matrix(i,j);
-                  ++nth_slave_dof;
-                }
-
-            AssertDimension (nth_master_dof, n_master_dofs);
-            AssertDimension (nth_slave_dof, n_dofs-n_master_dofs);
-
-            //TODO[WB]: We should make sure very small entries are removed after inversion
-            split_matrix->first.gauss_jordan ();
-          }
-      }
-
-
-      // a template that can determine statically whether a given
-      // DoFHandler class supports different finite element elements
-      template <typename>
-      struct DoFHandlerSupportsDifferentFEs
-      {
-        static const bool value = true;
-      };
-
-
-      template <int dim, int spacedim>
-      struct DoFHandlerSupportsDifferentFEs< dealii::DoFHandler<dim,spacedim> >
-      {
-        static const bool value = false;
-      };
-
-
-      template <int dim, int spacedim>
-      struct DoFHandlerSupportsDifferentFEs< dealii::MGDoFHandler<dim,spacedim> >
-      {
-        static const bool value = false;
-      };
-
-
-      /**
-       * A function that returns how many different finite elements a dof
-       * handler uses. This is one for non-hp DoFHandlers and
-       * dof_handler.get_fe().size() for the hp-versions.
-       */
-      template <int dim, int spacedim>
-      unsigned int
-      n_finite_elements (const dealii::hp::DoFHandler<dim,spacedim> &dof_handler)
-      {
-        return dof_handler.get_fe().size();
-      }
-
-
-      template <class DH>
-      unsigned int
-      n_finite_elements (const DH &)
-      {
-        return 1;
-      }
-
-
-      /**
-       * For a given face belonging to an active cell that borders to a
-       * more refined cell, return the fe_index of the most dominating
-       * finite element used on any of the face's subfaces.
-       */
-      template <typename face_iterator>
-      unsigned int
-      get_most_dominating_subface_fe_index (const face_iterator &face)
-      {
-        const unsigned int dim
-          = face_iterator::AccessorType::dimension;
-        const unsigned int spacedim
-          = face_iterator::AccessorType::space_dimension;
-
-        unsigned int dominating_subface_no = 0;
-        for (; dominating_subface_no<face->n_children();
-             ++dominating_subface_no)
-          {
-            // each of the subfaces can have only a single fe_index
-            // associated with them, since there is no cell on the other
-            // side
-            Assert (face->child(dominating_subface_no)
-                    ->n_active_fe_indices()
-                    == 1,
-                    ExcInternalError());
-
-            const FiniteElement<dim,spacedim> &
-            this_subface_fe = (face->child(dominating_subface_no)
-                               ->get_fe (face->child(dominating_subface_no)
-                                         ->nth_active_fe_index(0)));
-
-            FiniteElementDomination::Domination
-            domination = FiniteElementDomination::either_element_can_dominate;
-            for (unsigned int sf=0; sf<face->n_children(); ++sf)
-              if (sf != dominating_subface_no)
-                {
-                  const FiniteElement<dim,spacedim> &
-                  that_subface_fe = (face->child(sf)
-                                     ->get_fe (face->child(sf)
-                                               ->nth_active_fe_index(0)));
-
-                  domination = domination &
-                               this_subface_fe.compare_for_face_domination(that_subface_fe);
-                }
-
-            // see if the element on this subface is able to dominate the
-            // ones on all other subfaces, and if so take it
-            if ((domination == FiniteElementDomination::this_element_dominates)
-                ||
-                (domination == FiniteElementDomination::either_element_can_dominate))
-              break;
-          }
-
-        // check that we have found one such subface
-        Assert (dominating_subface_no < face->n_children(),
-                ExcNotImplemented());
-
-        // return the finite element index used on it. note that only a
-        // single fe can be active on such subfaces
-        return face->child (dominating_subface_no)->nth_active_fe_index(0);
-      }
-
-
-
-      /**
-       * Copy constraints into a constraint matrix object.
-       *
-       * This function removes zero constraints and those, which constrain
-       * a DoF which was already eliminated in one of the previous steps of
-       * the hp hanging node procedure.
-       *
-       * It also suppresses very small entries in the constraint matrix to
-       * avoid making the sparsity pattern fuller than necessary.
-       */
-      void
-      filter_constraints (const std::vector<types::global_dof_index> &master_dofs,
-                          const std::vector<types::global_dof_index> &slave_dofs,
-                          const FullMatrix<double> &face_constraints,
-                          ConstraintMatrix &constraints)
-      {
-        Assert (face_constraints.n () == master_dofs.size (),
-                ExcDimensionMismatch(master_dofs.size (),
-                                     face_constraints.n()));
-        Assert (face_constraints.m () == slave_dofs.size (),
-                ExcDimensionMismatch(slave_dofs.size (),
-                                     face_constraints.m()));
-
-        const unsigned int n_master_dofs = master_dofs.size ();
-        const unsigned int n_slave_dofs = slave_dofs.size ();
-
-        // check for a couple conditions that happened in parallel
-        // distributed mode
-        for (unsigned int row=0; row!=n_slave_dofs; ++row)
-          Assert (slave_dofs[row] != numbers::invalid_dof_index,
-                  ExcInternalError());
-        for (unsigned int col=0; col!=n_master_dofs; ++col)
-          Assert (master_dofs[col] != numbers::invalid_dof_index,
-                  ExcInternalError());
-
-
-        for (unsigned int row=0; row!=n_slave_dofs; ++row)
-          if (constraints.is_constrained (slave_dofs[row]) == false)
-            {
-              bool constraint_already_satisfied = false;
-
-              // Check if we have an identity constraint, which is already
-              // satisfied by unification of the corresponding global dof
-              // indices
-              for (unsigned int i=0; i<n_master_dofs; ++i)
-                if (face_constraints (row,i) == 1.0)
-                  if (master_dofs[i] == slave_dofs[row])
-                    {
-                      constraint_already_satisfied = true;
-                      break;
-                    }
-
-              if (constraint_already_satisfied == false)
-                {
-                  // add up the absolute values of all constraints in this
-                  // line to get a measure of their absolute size
-                  double abs_sum = 0;
-                  for (unsigned int i=0; i<n_master_dofs; ++i)
-                    abs_sum += std::abs (face_constraints(row,i));
-
-                  // then enter those constraints that are larger than
-                  // 1e-14*abs_sum. everything else probably originated
-                  // from inexact inversion of matrices and similar
-                  // effects. having those constraints in here will only
-                  // lead to problems because it makes sparsity patterns
-                  // fuller than necessary without producing any
-                  // significant effect
-                  constraints.add_line (slave_dofs[row]);
-                  for (unsigned int i=0; i<n_master_dofs; ++i)
-                    if ((face_constraints(row,i) != 0)
-                        &&
-                        (std::fabs(face_constraints(row,i)) >= 1e-14*abs_sum))
-                      constraints.add_entry (slave_dofs[row],
-                                             master_dofs[i],
-                                             face_constraints (row,i));
-                  constraints.set_inhomogeneity (slave_dofs[row], 0.);
-                }
-            }
-      }
-
-    }
-
-
-
-    void
-    make_hp_hanging_node_constraints (const dealii::DoFHandler<1> &,
-                                      ConstraintMatrix &)
-    {
-      // nothing to do for regular dof handlers in 1d
-    }
-
-
-
-    void
-    make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1> &,
-                                            ConstraintMatrix &,
-                                            dealii::internal::int2type<1>)
-    {
-      // nothing to do for regular dof handlers in 1d
-    }
-
-
-    void
-    make_hp_hanging_node_constraints (const dealii::MGDoFHandler<1> &,
-                                      ConstraintMatrix &)
-    {
-      // nothing to do for regular dof handlers in 1d
-    }
-
-
-
-    void
-    make_oldstyle_hanging_node_constraints (const dealii::MGDoFHandler<1> &,
-                                            ConstraintMatrix &,
-                                            dealii::internal::int2type<1>)
-    {
-      // nothing to do for regular dof handlers in 1d
-    }
-
-
-    void
-    make_hp_hanging_node_constraints (const dealii::hp::DoFHandler<1> &/*dof_handler*/,
-                                      ConstraintMatrix        &/*constraints*/)
-    {
-      // we may have to compute constraints for vertices. gotta think about
-      // that a bit more
-
-      //TODO[WB]: think about what to do here...
-    }
-
-
-
-    void
-    make_oldstyle_hanging_node_constraints (const dealii::hp::DoFHandler<1> &/*dof_handler*/,
-                                            ConstraintMatrix        &/*constraints*/,
-                                            dealii::internal::int2type<1>)
-    {
-      // we may have to compute constraints for vertices. gotta think about
-      // that a bit more
-
-      //TODO[WB]: think about what to do here...
-    }
-
-
-    void
-    make_hp_hanging_node_constraints (const dealii::DoFHandler<1,2> &,
-                                      ConstraintMatrix &)
-    {
-      // nothing to do for regular dof handlers in 1d
-    }
-
-
-
-    void
-    make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1,2> &,
-                                            ConstraintMatrix &,
-                                            dealii::internal::int2type<1>)
-    {
-      // nothing to do for regular dof handlers in 1d
-    }
-
-
-    void
-    make_hp_hanging_node_constraints (const dealii::DoFHandler<1,3> &,
-                                      ConstraintMatrix &)
-    {
-      // nothing to do for regular dof handlers in 1d
-    }
-
-    void
-    make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1,3> &,
-                                            ConstraintMatrix &,
-                                            dealii::internal::int2type<1>)
-    {
-      // nothing to do for regular dof handlers in 1d
-    }
-
-
-//   currently not used but may be in the future:
-
-//     void
-//     make_hp_hanging_node_constraints (const dealii::MDoFHandler<1,2> &,
-//                                    ConstraintMatrix    &)
-//     {
-//                                     // nothing to do for regular
-//                                     // dof handlers in 1d
-//     }
-
-
-
-//     void
-//     make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1,2> &,
-//                                          ConstraintMatrix    &,
-//                                          dealii::internal::int2type<1>)
-//     {
-//                                     // nothing to do for regular
-//                                     // dof handlers in 1d
-//     }
-
-
-//     void
-//     make_oldstyle_hanging_node_constraints (const dealii::hp::DoFHandler<1,2> &/*dof_handler*/,
-//                                          ConstraintMatrix        &/*constraints*/,
-//                                          dealii::internal::int2type<1>)
-//     {
-//                                     // we may have to compute
-//                                     // constraints for
-//                                     // vertices. gotta think about
-//                                     // that a bit more
-//
-// //TODO[WB]: think about what to do here...
-//     }
-//#endif
-
-
-
-    template <class DH>
-    void
-    make_oldstyle_hanging_node_constraints (const DH         &dof_handler,
-                                            ConstraintMatrix &constraints,
-                                            dealii::internal::int2type<2>)
-    {
-      const unsigned int dim = 2;
-
-      const unsigned int spacedim = DH::space_dimension;
-
-      std::vector<types::global_dof_index> dofs_on_mother;
-      std::vector<types::global_dof_index> dofs_on_children;
-
-      // loop over all lines; only on lines there can be constraints. We do
-      // so by looping over all active cells and checking whether any of
-      // the faces are refined which can only be from the neighboring cell
-      // because this one is active. In that case, the face is subject to
-      // constraints
-      //
-      // note that even though we may visit a face twice if the neighboring
-      // cells are equally refined, we can only visit each face with
-      // hanging nodes once
-      typename DH::active_cell_iterator cell = dof_handler.begin_active(),
-                                        endc = dof_handler.end();
-      for (; cell!=endc; ++cell)
-        // artificial cells can at best neighbor ghost cells, but we're not
-        // interested in these interfaces
-        if (!cell->is_artificial ())
-          for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
-            if (cell->face(face)->has_children())
-              {
-                // in any case, faces can have at most two active fe
-                // indices, but here the face can have only one (namely the
-                // same as that from the cell we're sitting on), and each
-                // of the children can have only one as well. check this
-                Assert (cell->face(face)->n_active_fe_indices() == 1,
-                        ExcInternalError());
-                Assert (cell->face(face)->fe_index_is_active(cell->active_fe_index())
-                        == true,
-                        ExcInternalError());
-                for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
-                  if (!cell->neighbor_child_on_subface(face,c)->is_artificial())
-                    Assert (cell->face(face)->child(c)->n_active_fe_indices() == 1,
-                            ExcInternalError());
-
-                // right now, all that is implemented is the case that both
-                // sides use the same fe
-                for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
-                  if (!cell->neighbor_child_on_subface(face,c)->is_artificial())
-                    Assert (cell->face(face)->child(c)
-                            ->fe_index_is_active(cell->active_fe_index()) == true,
-                            ExcNotImplemented());
-
-                // ok, start up the work
-                const FiniteElement<dim,spacedim> &fe       = cell->get_fe();
-                const unsigned int        fe_index = cell->active_fe_index();
-
-                const unsigned int
-                n_dofs_on_mother   = 2*fe.dofs_per_vertex + fe.dofs_per_line,
-                n_dofs_on_children = fe.dofs_per_vertex + 2*fe.dofs_per_line;
-
-                dofs_on_mother.resize (n_dofs_on_mother);
-                dofs_on_children.resize (n_dofs_on_children);
-
-                Assert(n_dofs_on_mother == fe.constraints().n(),
-                       ExcDimensionMismatch(n_dofs_on_mother,
-                                            fe.constraints().n()));
-                Assert(n_dofs_on_children == fe.constraints().m(),
-                       ExcDimensionMismatch(n_dofs_on_children,
-                                            fe.constraints().m()));
-
-                const typename DH::line_iterator this_face = cell->face(face);
-
-                // fill the dofs indices. Use same enumeration scheme as in
-                // @p{FiniteElement::constraints()}
-                unsigned int next_index = 0;
-                for (unsigned int vertex=0; vertex<2; ++vertex)
-                  for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
-                    dofs_on_mother[next_index++] = this_face->vertex_dof_index(vertex,dof,
-                                                                               fe_index);
-                for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
-                  dofs_on_mother[next_index++] = this_face->dof_index(dof, fe_index);
-                AssertDimension (next_index, dofs_on_mother.size());
-
-                next_index = 0;
-                for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
-                  dofs_on_children[next_index++]
-                    = this_face->child(0)->vertex_dof_index(1,dof,fe_index);
-                for (unsigned int child=0; child<2; ++child)
-                  for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
-                    dofs_on_children[next_index++]
-                      = this_face->child(child)->dof_index(dof, fe_index);
-                AssertDimension (next_index, dofs_on_children.size());
-
-                // for each row in the constraint matrix for this line:
-                for (unsigned int row=0; row!=dofs_on_children.size(); ++row)
-                  {
-                    constraints.add_line (dofs_on_children[row]);
-                    for (unsigned int i=0; i!=dofs_on_mother.size(); ++i)
-                      constraints.add_entry (dofs_on_children[row],
-                                             dofs_on_mother[i],
-                                             fe.constraints()(row,i));
-
-                    constraints.set_inhomogeneity (dofs_on_children[row], 0.);
-                  }
-              }
-            else
-              {
-                // this face has no children, but it could still be that it
-                // is shared by two cells that use a different fe index.
-                // check a couple of things, but ignore the case that the
-                // neighbor is an artificial cell
-                if (!cell->at_boundary(face) &&
-                    !cell->neighbor(face)->is_artificial())
-                  {
-                    Assert (cell->face(face)->n_active_fe_indices() == 1,
-                            ExcNotImplemented());
-                    Assert (cell->face(face)
-                            ->fe_index_is_active(cell->active_fe_index()) == true,
-                            ExcInternalError());
-                  }
-              }
-    }
-
-
-
-    template <class DH>
-    void
-    make_oldstyle_hanging_node_constraints (const DH         &dof_handler,
-                                            ConstraintMatrix &constraints,
-                                            dealii::internal::int2type<3>)
-    {
-      const unsigned int dim = 3;
-
-      std::vector<types::global_dof_index> dofs_on_mother;
-      std::vector<types::global_dof_index> dofs_on_children;
-
-      // loop over all quads; only on quads there can be constraints. We do
-      // so by looping over all active cells and checking whether any of
-      // the faces are refined which can only be from the neighboring cell
-      // because this one is active. In that case, the face is subject to
-      // constraints
-      //
-      // note that even though we may visit a face twice if the neighboring
-      // cells are equally refined, we can only visit each face with
-      // hanging nodes once
-      typename DH::active_cell_iterator cell = dof_handler.begin_active(),
-                                        endc = dof_handler.end();
-      for (; cell!=endc; ++cell)
-        // artificial cells can at best neighbor ghost cells, but we're not
-        // interested in these interfaces
-        if (!cell->is_artificial ())
-          for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
-            if (cell->face(face)->has_children())
-              {
-                // first of all, make sure that we treat a case which is
-                // possible, i.e. either no dofs on the face at all or no
-                // anisotropic refinement
-                if (cell->get_fe().dofs_per_face == 0)
-                  continue;
-
-                Assert(cell->face(face)->refinement_case()==RefinementCase<dim-1>::isotropic_refinement,
-                       ExcNotImplemented());
-
-                // in any case, faces can have at most two active fe
-                // indices, but here the face can have only one (namely the
-                // same as that from the cell we're sitting on), and each
-                // of the children can have only one as well. check this
-                AssertDimension (cell->face(face)->n_active_fe_indices(), 1);
-                Assert (cell->face(face)->fe_index_is_active(cell->active_fe_index())
-                        == true,
-                        ExcInternalError());
-                for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
-                  AssertDimension (cell->face(face)->child(c)->n_active_fe_indices(), 1);
-
-                // right now, all that is implemented is the case that both
-                // sides use the same fe, and not only that but also that
-                // all lines bounding this face and the children have the
-                // same fe
-                for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
-                  if (!cell->neighbor_child_on_subface(face,c)->is_artificial())
-                    {
-                      Assert (cell->face(face)->child(c)
-                              ->fe_index_is_active(cell->active_fe_index()) == true,
-                              ExcNotImplemented());
-                      for (unsigned int e=0; e<4; ++e)
-                        {
-                          Assert (cell->face(face)->child(c)->line(e)
-                                  ->n_active_fe_indices() == 1,
-                                  ExcNotImplemented());
-                          Assert (cell->face(face)->child(c)->line(e)
-                                  ->fe_index_is_active(cell->active_fe_index()) == true,
-                                  ExcNotImplemented());
-                        }
-                    }
-                for (unsigned int e=0; e<4; ++e)
-                  {
-                    Assert (cell->face(face)->line(e)
-                            ->n_active_fe_indices() == 1,
-                            ExcNotImplemented());
-                    Assert (cell->face(face)->line(e)
-                            ->fe_index_is_active(cell->active_fe_index()) == true,
-                            ExcNotImplemented());
-                  }
-
-                // ok, start up the work
-                const FiniteElement<dim> &fe       = cell->get_fe();
-                const unsigned int        fe_index = cell->active_fe_index();
-
-                const unsigned int n_dofs_on_mother = fe.dofs_per_face;
-                const unsigned int n_dofs_on_children = (5*fe.dofs_per_vertex+
-                                                         12*fe.dofs_per_line+
-                                                         4*fe.dofs_per_quad);
-
-                //TODO[TL]: think about this and the following in case of anisotropic refinement
-
-                dofs_on_mother.resize (n_dofs_on_mother);
-                dofs_on_children.resize (n_dofs_on_children);
-
-                Assert(n_dofs_on_mother == fe.constraints().n(),
-                       ExcDimensionMismatch(n_dofs_on_mother,
-                                            fe.constraints().n()));
-                Assert(n_dofs_on_children == fe.constraints().m(),
-                       ExcDimensionMismatch(n_dofs_on_children,
-                                            fe.constraints().m()));
-
-                const typename DH::face_iterator this_face = cell->face(face);
-
-                // fill the dofs indices. Use same enumeration scheme as in
-                // @p{FiniteElement::constraints()}
-                unsigned int next_index = 0;
-                for (unsigned int vertex=0; vertex<4; ++vertex)
-                  for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
-                    dofs_on_mother[next_index++] = this_face->vertex_dof_index(vertex,dof,
-                                                                               fe_index);
-                for (unsigned int line=0; line<4; ++line)
-                  for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
-                    dofs_on_mother[next_index++]
-                      = this_face->line(line)->dof_index(dof, fe_index);
-                for (unsigned int dof=0; dof!=fe.dofs_per_quad; ++dof)
-                  dofs_on_mother[next_index++] = this_face->dof_index(dof, fe_index);
-                AssertDimension (next_index, dofs_on_mother.size());
-
-                next_index = 0;
-
-                // assert some consistency assumptions
-
-                //TODO[TL]: think about this in case of anisotropic
-                //refinement
-
-                Assert (dof_handler.get_tria().get_anisotropic_refinement_flag() ||
-                        ((this_face->child(0)->vertex_index(3) ==
-                          this_face->child(1)->vertex_index(2)) &&
-                         (this_face->child(0)->vertex_index(3) ==
-                          this_face->child(2)->vertex_index(1)) &&
-                         (this_face->child(0)->vertex_index(3) ==
-                          this_face->child(3)->vertex_index(0))),
-                        ExcInternalError());
-                for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
-                  dofs_on_children[next_index++]
-                    = this_face->child(0)->vertex_dof_index(3,dof);
-
-                // dof numbers on the centers of the lines bounding this
-                // face
-                for (unsigned int line=0; line<4; ++line)
-                  for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
-                    dofs_on_children[next_index++]
-                      = this_face->line(line)->child(0)->vertex_dof_index(1,dof, fe_index);
-
-                // next the dofs on the lines interior to the face; the
-                // order of these lines is laid down in the FiniteElement
-                // class documentation
-                for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
-                  dofs_on_children[next_index++]
-                    = this_face->child(0)->line(1)->dof_index(dof, fe_index);
-                for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
-                  dofs_on_children[next_index++]
-                    = this_face->child(2)->line(1)->dof_index(dof, fe_index);
-                for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
-                  dofs_on_children[next_index++]
-                    = this_face->child(0)->line(3)->dof_index(dof, fe_index);
-                for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
-                  dofs_on_children[next_index++]
-                    = this_face->child(1)->line(3)->dof_index(dof, fe_index);
-
-                // dofs on the bordering lines
-                for (unsigned int line=0; line<4; ++line)
-                  for (unsigned int child=0; child<2; ++child)
-                    for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
-                      dofs_on_children[next_index++]
-                        = this_face->line(line)->child(child)->dof_index(dof, fe_index);
-
-                // finally, for the dofs interior to the four child faces
-                for (unsigned int child=0; child<4; ++child)
-                  for (unsigned int dof=0; dof!=fe.dofs_per_quad; ++dof)
-                    dofs_on_children[next_index++]
-                      = this_face->child(child)->dof_index(dof, fe_index);
-                AssertDimension (next_index, dofs_on_children.size());
-
-                // for each row in the constraint matrix for this line:
-                for (unsigned int row=0; row!=dofs_on_children.size(); ++row)
-                  {
-                    constraints.add_line (dofs_on_children[row]);
-                    for (unsigned int i=0; i!=dofs_on_mother.size(); ++i)
-                      constraints.add_entry (dofs_on_children[row],
-                                             dofs_on_mother[i],
-                                             fe.constraints()(row,i));
-
-                    constraints.set_inhomogeneity(dofs_on_children[row], 0.);
-                  }
-              }
-            else
-              {
-                // this face has no children, but it could still be that it
-                // is shared by two cells that use a different fe index.
-                // check a couple of things, but ignore the case that the
-                // neighbor is an artificial cell
-                if (!cell->at_boundary(face) &&
-                    !cell->neighbor(face)->is_artificial())
-                  {
-                    Assert (cell->face(face)->n_active_fe_indices() == 1,
-                            ExcNotImplemented());
-                    Assert (cell->face(face)
-                            ->fe_index_is_active(cell->active_fe_index()) == true,
-                            ExcInternalError());
-                  }
-              }
-    }
-
-
-    template <class DH>
-    void
-    make_hp_hanging_node_constraints (const DH         &dof_handler,
-                                      ConstraintMatrix &constraints)
-    {
-      // note: this function is going to be hard to understand if you
-      // haven't read the hp paper. however, we try to follow the notation
-      // laid out there, so go read the paper before you try to understand
-      // what is going on here
-
-      const unsigned int dim = DH::dimension;
-
-      const unsigned int spacedim = DH::space_dimension;
-
-
-      // a matrix to be used for constraints below. declared here and
-      // simply resized down below to avoid permanent re-allocation of
-      // memory
-      FullMatrix<double> constraint_matrix;
-
-      // similarly have arrays that will hold master and slave dof numbers,
-      // as well as a scratch array needed for the complicated case below
-      std::vector<types::global_dof_index> master_dofs;
-      std::vector<types::global_dof_index> slave_dofs;
-      std::vector<types::global_dof_index> scratch_dofs;
-
-      // caches for the face and subface interpolation matrices between
-      // different (or the same) finite elements. we compute them only
-      // once, namely the first time they are needed, and then just reuse
-      // them
-      Table<2,std_cxx1x::shared_ptr<FullMatrix<double> > >
-      face_interpolation_matrices (n_finite_elements (dof_handler),
-                                   n_finite_elements (dof_handler));
-      Table<3,std_cxx1x::shared_ptr<FullMatrix<double> > >
-      subface_interpolation_matrices (n_finite_elements (dof_handler),
-                                      n_finite_elements (dof_handler),
-                                      GeometryInfo<dim>::max_children_per_face);
-
-      // similarly have a cache for the matrices that are split into their
-      // master and slave parts, and for which the master part is inverted.
-      // these two matrices are derived from the face interpolation matrix
-      // as described in the @ref hp_paper "hp paper"
-      Table<2,std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > > >
-      split_face_interpolation_matrices (n_finite_elements (dof_handler),
-                                         n_finite_elements (dof_handler));
-
-      // finally, for each pair of finite elements, have a mask that states
-      // which of the degrees of freedom on the coarse side of a refined
-      // face will act as master dofs.
-      Table<2,std_cxx1x::shared_ptr<std::vector<bool> > >
-      master_dof_masks (n_finite_elements (dof_handler),
-                        n_finite_elements (dof_handler));
-
-      // loop over all faces
-      //
-      // note that even though we may visit a face twice if the neighboring
-      // cells are equally refined, we can only visit each face with
-      // hanging nodes once
-      typename DH::active_cell_iterator cell = dof_handler.begin_active(),
-                                        endc = dof_handler.end();
-      for (; cell!=endc; ++cell)
-        // artificial cells can at best neighbor ghost cells, but we're not
-        // interested in these interfaces
-        if (!cell->is_artificial ())
-          for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
-            if (cell->face(face)->has_children())
-              {
-                // first of all, make sure that we treat a case which is
-                // possible, i.e. either no dofs on the face at all or no
-                // anisotropic refinement
-                if (cell->get_fe().dofs_per_face == 0)
-                  continue;
-
-                Assert(cell->face(face)->refinement_case()==RefinementCase<dim-1>::isotropic_refinement,
-                       ExcNotImplemented());
-
-                // so now we've found a face of an active cell that has
-                // children. that means that there are hanging nodes here.
-
-                // in any case, faces can have at most two sets of active
-                // fe indices, but here the face can have only one (namely
-                // the same as that from the cell we're sitting on), and
-                // each of the children can have only one as well. check
-                // this
-                Assert (cell->face(face)->n_active_fe_indices() == 1,
-                        ExcInternalError());
-                Assert (cell->face(face)->fe_index_is_active(cell->active_fe_index())
-                        == true,
-                        ExcInternalError());
-                for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
-                  Assert (cell->face(face)->child(c)->n_active_fe_indices() == 1,
-                          ExcInternalError());
-
-                // first find out whether we can constrain each of the
-                // subfaces to the mother face. in the lingo of the hp
-                // paper, this would be the simple case. note that we can
-                // short-circuit this decision if the dof_handler doesn't
-                // support hp at all
-                //
-                // ignore all interfaces with artificial cells
-                FiniteElementDomination::Domination
-                mother_face_dominates = FiniteElementDomination::either_element_can_dominate;
-
-                if (DoFHandlerSupportsDifferentFEs<DH>::value == true)
-                  for (unsigned int c=0; c<cell->face(face)->number_of_children(); ++c)
-                    if (!cell->neighbor_child_on_subface (face, c)->is_artificial())
-                      mother_face_dominates = mother_face_dominates &
-                                              (cell->get_fe().compare_for_face_domination
-                                               (cell->neighbor_child_on_subface (face, c)->get_fe()));
-
-                switch (mother_face_dominates)
-                  {
-                  case FiniteElementDomination::this_element_dominates:
-                  case FiniteElementDomination::either_element_can_dominate:
-                  {
-                    // Case 1 (the simple case and the only case that can
-                    // happen for non-hp DoFHandlers): The coarse element
-                    // dominates the elements on the subfaces (or they are
-                    // all the same)
-                    //
-                    // so we are going to constrain the DoFs on the face
-                    // children against the DoFs on the face itself
-                    master_dofs.resize (cell->get_fe().dofs_per_face);
-
-                    cell->face(face)->get_dof_indices (master_dofs,
-                                                       cell->active_fe_index ());
-
-                    // Now create constraint matrix for the subfaces and
-                    // assemble it. ignore all interfaces with artificial
-                    // cells because we can only get to such interfaces if
-                    // the current cell is a ghost cell
-                    for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
-                      {
-                        if (cell->neighbor_child_on_subface (face, c)->is_artificial())
-                          continue;
-
-                        const typename DH::active_face_iterator
-                        subface = cell->face(face)->child(c);
-
-                        Assert (subface->n_active_fe_indices() == 1,
-                                ExcInternalError());
-
-                        const unsigned int
-                        subface_fe_index = subface->nth_active_fe_index(0);
-
-                        // we sometime run into the situation where for
-                        // example on one big cell we have a FE_Q(1) and on
-                        // the subfaces we have a mixture of FE_Q(1) and
-                        // FE_Nothing. In that case, the face domination is
-                        // either_element_can_dominate for the whole
-                        // collection of subfaces, but on the particular
-                        // subface between FE_Q(1) and FE_Nothing, there
-                        // are no constraints that we need to take care of.
-                        // in that case, just continue
-                        if (cell->get_fe().compare_for_face_domination
-                            (subface->get_fe(subface_fe_index))
-                            ==
-                            FiniteElementDomination::no_requirements)
-                          continue;
-
-                        // Same procedure as for the mother cell. Extract
-                        // the face DoFs from the cell DoFs.
-                        slave_dofs.resize (subface->get_fe(subface_fe_index)
-                                           .dofs_per_face);
-                        subface->get_dof_indices (slave_dofs, subface_fe_index);
-
-                        for (unsigned int i=0; i<slave_dofs.size(); ++i)
-                          Assert (slave_dofs[i] != numbers::invalid_dof_index,
-                                  ExcInternalError());
-
-                        // Now create the element constraint for this
-                        // subface.
-                        //
-                        // As a side remark, one may wonder the following:
-                        // neighbor_child is clearly computed correctly,
-                        // i.e. taking into account face_orientation (just
-                        // look at the implementation of that function).
-                        // however, we don't care about this here, when we
-                        // ask for subface_interpolation on subface c. the
-                        // question rather is: do we have to translate 'c'
-                        // here as well?
-                        //
-                        // the answer is in fact 'no'. if one does that,
-                        // results are wrong: constraints are added twice
-                        // for the same pair of nodes but with differing
-                        // weights. in addition, one can look at the
-                        // deal.II/project_*_03 tests that look at exactly
-                        // this case: there, we have a mesh with at least
-                        // one face_orientation==false and hanging nodes,
-                        // and the results of those tests show that the
-                        // result of projection verifies the approximation
-                        // properties of a finite element onto that mesh
-                        ensure_existence_of_subface_matrix
-                        (cell->get_fe(),
-                         subface->get_fe(subface_fe_index),
-                         c,
-                         subface_interpolation_matrices
-                         [cell->active_fe_index()][subface_fe_index][c]);
-
-                        // Add constraints to global constraint matrix.
-                        filter_constraints (master_dofs,
-                                            slave_dofs,
-                                            *(subface_interpolation_matrices
-                                              [cell->active_fe_index()][subface_fe_index][c]),
-                                            constraints);
-                      }
-
-                    break;
-                  }
-
-                  case FiniteElementDomination::other_element_dominates:
-                  case FiniteElementDomination::neither_element_dominates:
-                  {
-                    // Case 2 (the "complex" case): at least one (the
-                    // neither_... case) of the finer elements or all of
-                    // them (the other_... case) is dominating. See the hp
-                    // paper for a way how to deal with this situation
-                    //
-                    // since this is something that can only happen for hp
-                    // dof handlers, add a check here...
-                    Assert (DoFHandlerSupportsDifferentFEs<DH>::value == true,
-                            ExcInternalError());
-
-                    // we first have to find the finite element that is
-                    // able to generate a space that all the other ones can
-                    // be constrained to
-                    const unsigned int dominating_fe_index
-                      = get_most_dominating_subface_fe_index (cell->face(face));
-
-                    const FiniteElement<dim,spacedim> &dominating_fe
-                      = dof_handler.get_fe()[dominating_fe_index];
-
-                    // check also that it is able to constrain the mother
-                    // face. it should be, or we wouldn't have gotten into
-                    // the branch for the 'complex' case
-                    Assert ((dominating_fe.compare_for_face_domination
-                             (cell->face(face)->get_fe(cell->face(face)->nth_active_fe_index(0)))
-                             == FiniteElementDomination::this_element_dominates)
-                            ||
-                            (dominating_fe.compare_for_face_domination
-                             (cell->face(face)->get_fe(cell->face(face)->nth_active_fe_index(0)))
-                             == FiniteElementDomination::either_element_can_dominate),
-                            ExcInternalError());
-
-
-                    // first get the interpolation matrix from the mother
-                    // to the virtual dofs
-                    Assert (dominating_fe.dofs_per_face <=
-                            cell->get_fe().dofs_per_face,
-                            ExcInternalError());
-
-                    ensure_existence_of_face_matrix
-                    (dominating_fe,
-                     cell->get_fe(),
-                     face_interpolation_matrices
-                     [dominating_fe_index][cell->active_fe_index()]);
-
-                    // split this matrix into master and slave components.
-                    // invert the master component
-                    ensure_existence_of_master_dof_mask
-                    (cell->get_fe(),
-                     dominating_fe,
-                     (*face_interpolation_matrices
-                      [dominating_fe_index]
-                      [cell->active_fe_index()]),
-                     master_dof_masks
-                     [dominating_fe_index]
-                     [cell->active_fe_index()]);
-
-                    ensure_existence_of_split_face_matrix
-                    (*face_interpolation_matrices
-                     [dominating_fe_index][cell->active_fe_index()],
-                     (*master_dof_masks
-                      [dominating_fe_index][cell->active_fe_index()]),
-                     split_face_interpolation_matrices
-                     [dominating_fe_index][cell->active_fe_index()]);
-
-                    const FullMatrix<double> &restrict_mother_to_virtual_master_inv
-                      = (split_face_interpolation_matrices
-                         [dominating_fe_index][cell->active_fe_index()]->first);
-
-                    const FullMatrix<double> &restrict_mother_to_virtual_slave
-                      = (split_face_interpolation_matrices
-                         [dominating_fe_index][cell->active_fe_index()]->second);
-
-                    // now compute the constraint matrix as the product
-                    // between the inverse matrix and the slave part
-                    constraint_matrix.reinit (cell->get_fe().dofs_per_face -
-                                              dominating_fe.dofs_per_face,
-                                              dominating_fe.dofs_per_face);
-                    restrict_mother_to_virtual_slave
-                    .mmult (constraint_matrix,
-                            restrict_mother_to_virtual_master_inv);
-
-                    // then figure out the global numbers of master and
-                    // slave dofs and apply constraints
-                    scratch_dofs.resize (cell->get_fe().dofs_per_face);
-                    cell->face(face)->get_dof_indices (scratch_dofs,
-                                                       cell->active_fe_index ());
-
-                    // split dofs into master and slave components
-                    master_dofs.clear ();
-                    slave_dofs.clear ();
-                    for (unsigned int i=0; i<cell->get_fe().dofs_per_face; ++i)
-                      if ((*master_dof_masks
-                           [dominating_fe_index][cell->active_fe_index()])[i] == true)
-                        master_dofs.push_back (scratch_dofs[i]);
-                      else
-                        slave_dofs.push_back (scratch_dofs[i]);
-
-                    AssertDimension (master_dofs.size(), dominating_fe.dofs_per_face);
-                    AssertDimension (slave_dofs.size(),
-                                     cell->get_fe().dofs_per_face - dominating_fe.dofs_per_face);
-
-                    filter_constraints (master_dofs,
-                                        slave_dofs,
-                                        constraint_matrix,
-                                        constraints);
-
-
-
-                    // next we have to deal with the subfaces. do as
-                    // discussed in the hp paper
-                    for (unsigned int sf=0;
-                         sf<cell->face(face)->n_children(); ++sf)
-                      {
-                        // ignore interfaces with artificial cells as well
-                        // as interfaces between ghost cells in 2d
-                        if (cell->neighbor_child_on_subface (face, sf)->is_artificial()
-                            ||
-                            (dim==2 && cell->is_ghost()
-                             &&
-                             cell->neighbor_child_on_subface (face, sf)->is_ghost()))
-                          continue;
-
-                        Assert (cell->face(face)->child(sf)
-                                ->n_active_fe_indices() == 1,
-                                ExcInternalError());
-
-                        const unsigned int subface_fe_index
-                          = cell->face(face)->child(sf)->nth_active_fe_index(0);
-                        const FiniteElement<dim,spacedim> &subface_fe
-                          = dof_handler.get_fe()[subface_fe_index];
-
-                        // first get the interpolation matrix from the
-                        // subface to the virtual dofs
-                        Assert (dominating_fe.dofs_per_face <=
-                                subface_fe.dofs_per_face,
-                                ExcInternalError());
-                        ensure_existence_of_subface_matrix
-                        (dominating_fe,
-                         subface_fe,
-                         sf,
-                         subface_interpolation_matrices
-                         [dominating_fe_index][subface_fe_index][sf]);
-
-                        const FullMatrix<double> &restrict_subface_to_virtual
-                          = *(subface_interpolation_matrices
-                              [dominating_fe_index][subface_fe_index][sf]);
-
-                        constraint_matrix.reinit (subface_fe.dofs_per_face,
-                                                  dominating_fe.dofs_per_face);
-
-                        restrict_subface_to_virtual
-                        .mmult (constraint_matrix,
-                                restrict_mother_to_virtual_master_inv);
-
-                        slave_dofs.resize (subface_fe.dofs_per_face);
-                        cell->face(face)->child(sf)->get_dof_indices (slave_dofs,
-                                                                      subface_fe_index);
-
-                        filter_constraints (master_dofs,
-                                            slave_dofs,
-                                            constraint_matrix,
-                                            constraints);
-                      }
-
-                    break;
-                  }
-
-                  case FiniteElementDomination::no_requirements:
-                    // there are no continuity requirements between the two
-                    // elements. record no constraints
-                    break;
-
-                  default:
-                    // we shouldn't get here
-                    Assert (false, ExcInternalError());
-                  }
-              }
-            else
-              {
-                // this face has no children, but it could still be that it
-                // is shared by two cells that use a different fe index
-                Assert (cell->face(face)
-                        ->fe_index_is_active(cell->active_fe_index()) == true,
-                        ExcInternalError());
-
-                // see if there is a neighbor that is an artificial cell.
-                // in that case, we're not interested in this interface. we
-                // test this case first since artificial cells may not have
-                // an active_fe_index set, etc
-                if (!cell->at_boundary(face)
-                    &&
-                    cell->neighbor(face)->is_artificial())
-                  continue;
-
-                // Only if there is a neighbor with a different
-                // active_fe_index and the same h-level, some action has to
-                // be taken.
-                if ((DoFHandlerSupportsDifferentFEs<DH>::value == true)
-                    &&
-                    !cell->face(face)->at_boundary ()
-                    &&
-                    (cell->neighbor(face)->active_fe_index () !=
-                     cell->active_fe_index ())
-                    &&
-                    (!cell->face(face)->has_children() &&
-                     !cell->neighbor_is_coarser(face) ))
-                  {
-                    const typename DH::level_cell_iterator neighbor = cell->neighbor (face);
-
-                    // see which side of the face we have to constrain
-                    switch (cell->get_fe().compare_for_face_domination (neighbor->get_fe ()))
-                      {
-                      case FiniteElementDomination::this_element_dominates:
-                      {
-                        // Get DoFs on dominating and dominated side of the
-                        // face
-                        master_dofs.resize (cell->get_fe().dofs_per_face);
-                        cell->face(face)->get_dof_indices (master_dofs,
-                                                           cell->active_fe_index ());
-
-                        slave_dofs.resize (neighbor->get_fe().dofs_per_face);
-                        cell->face(face)->get_dof_indices (slave_dofs,
-                                                           neighbor->active_fe_index ());
-
-                        // break if the n_master_dofs == 0, because we are
-                        // attempting to constrain to an element that has
-                        // no face dofs
-                        if (master_dofs.size() == 0) break;
-
-                        // make sure the element constraints for this face
-                        // are available
-                        ensure_existence_of_face_matrix
-                        (cell->get_fe(),
-                         neighbor->get_fe(),
-                         face_interpolation_matrices
-                         [cell->active_fe_index()][neighbor->active_fe_index()]);
-
-                        // Add constraints to global constraint matrix.
-                        filter_constraints (master_dofs,
-                                            slave_dofs,
-                                            *(face_interpolation_matrices
-                                              [cell->active_fe_index()]
-                                              [neighbor->active_fe_index()]),
-                                            constraints);
-
-                        break;
-                      }
-
-                      case FiniteElementDomination::other_element_dominates:
-                      {
-                        // we don't do anything here since we will come
-                        // back to this face from the other cell, at which
-                        // time we will fall into the first case clause
-                        // above
-                        break;
-                      }
-
-                      case FiniteElementDomination::either_element_can_dominate:
-                      {
-                        // it appears as if neither element has any
-                        // constraints on its neighbor. this may be because
-                        // neither element has any DoFs on faces at all. or
-                        // that the two elements are actually the same,
-                        // although they happen to run under different
-                        // fe_indices (this is what happens in
-                        // hp/hp_hanging_nodes_01 for example).
-                        //
-                        // another possibility is what happens in crash_13.
-                        // there, we have FESystem(FE_Q(1),FE_DGQ(0)) vs.
-                        // FESystem(FE_Q(1),FE_DGQ(1)). neither of them
-                        // dominates the other.
-                       //
-                       // a final possibility is that we have something like
-                       // FESystem(FE_Q(1),FE_Q(1)) vs
-                       // FESystem(FE_Q(1),FE_Nothing()), see
-                       // hp/fe_nothing_18/19.
-                       //
-                       // in any case, the point is that it doesn't
-                        // matter. there is nothing to do here.
-                        break;
-                      }
-
-                      case FiniteElementDomination::neither_element_dominates:
-                      {
-                        // we don't presently know what exactly to do here.
-                        // it isn't quite clear what exactly we would have
-                        // to do here. sit tight until someone trips over
-                        // the following statement and see what exactly is
-                        // going on
-                        Assert (false, ExcNotImplemented());
-                        break;
-                      }
-
-                      case FiniteElementDomination::no_requirements:
-                      {
-                        // nothing to do here
-                        break;
-                      }
-
-                      default:
-                        // we shouldn't get here
-                        Assert (false, ExcInternalError());
-                      }
-                  }
-              }
-    }
-  }
-
-
-
-
-  template <class DH>
-  void
-  make_hanging_node_constraints (const DH &dof_handler,
-                                 ConstraintMatrix &constraints)
-  {
-    // Decide whether to use the new or old make_hanging_node_constraints
-    // function. If all the FiniteElement or all elements in a FECollection
-    // support the new face constraint matrix, the new code will be used.
-    // Otherwise, the old implementation is used for the moment.
-    if (dof_handler.get_fe().hp_constraints_are_implemented ())
-      internal::
-      make_hp_hanging_node_constraints (dof_handler,
-                                        constraints);
-    else
-      internal::
-      make_oldstyle_hanging_node_constraints (dof_handler,
-                                              constraints,
-                                              dealii::internal::int2type<DH::dimension>());
-  }
-
-
-
-  namespace
-  {
-    // enter constraints for periodicity into the given ConstraintMatrix object.
-    // this function is called when at least one of the two face iterators corresponds
-    // to an active object without further children
-    //
-    // @param transformation A matrix that maps degrees of freedom from one face
-    // to another. If the DoFs on the two faces are supposed to match exactly, then
-    // the matrix so provided will be the identity matrix. if face 2 is once refined
-    // from face 1, then the matrix needs to be the interpolation matrix from a face
-    // to this particular child
-    //
-    // @precondition: face_1 is supposed to be active
-    //
-    // @note As bug #82 ((http://code.google.com/p/dealii/issues/detail?id=82) and the
-    // corresponding testcase bits/periodicity_05 demonstrate, we can occasionally
-    // get into trouble if we already have the constraint x1=x2 and want to insert
-    // x2=x1. we avoid this by skipping an identity constraint if the opposite
-    // constraint already exists
-    template <typename FaceIterator>
-    void
-    set_periodicity_constraints (const FaceIterator                          &face_1,
-                                 const typename identity<FaceIterator>::type &face_2,
-                                 const FullMatrix<double>                    &transformation,
-                                 dealii::ConstraintMatrix                    &constraint_matrix,
-                                 const ComponentMask                         &component_mask,
-                                 const bool                                   face_orientation,
-                                 const bool                                   face_flip,
-                                 const bool                                   face_rotation)
-    {
-      static const int dim      = FaceIterator::AccessorType::dimension;
-      static const int spacedim = FaceIterator::AccessorType::space_dimension;
-
-      // we should be in the case where face_1 is active, i.e. has no children:
-      Assert (!face_1->has_children(),
-              ExcInternalError());
-
-      Assert (face_1->n_active_fe_indices() == 1,
-              ExcInternalError());
-
-      // if face_2 does have children, then we need to iterate over them
-      if (face_2->has_children())
-        {
-          Assert (face_2->n_children() == GeometryInfo<dim>::max_children_per_face,
-                  ExcNotImplemented());
-          const unsigned int dofs_per_face
-            = face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face;
-          FullMatrix<double> child_transformation (dofs_per_face, dofs_per_face);
-          FullMatrix<double> subface_interpolation (dofs_per_face, dofs_per_face);
-          for (unsigned int c=0; c<face_2->n_children(); ++c)
-            {
-              // get the interpolation matrix recursively from the one that
-              // interpolated from face_1 to face_2 by multiplying from the
-              // left with the one that interpolates from face_2 to
-              // its child
-              face_1->get_fe(face_1->nth_active_fe_index(0))
-              .get_subface_interpolation_matrix (face_1->get_fe(face_1->nth_active_fe_index(0)),
-                                                 c,
-                                                 subface_interpolation);
-              subface_interpolation.mmult (child_transformation, transformation);
-              set_periodicity_constraints(face_1, face_2->child(c),
-                                          child_transformation,
-                                          constraint_matrix, component_mask,
-                                          face_orientation, face_flip, face_rotation);
-            }
-        }
-      else
-        // both faces are active. we need to match the corresponding DoFs of both faces
-        {
-          const unsigned int face_1_index = face_1->nth_active_fe_index(0);
-          const unsigned int face_2_index = face_2->nth_active_fe_index(0);
-          Assert(face_1->get_fe(face_1_index) == face_2->get_fe(face_1_index),
-                 ExcMessage ("Matching periodic cells need to use the same finite element"));
-
-          const FiniteElement<dim, spacedim> &fe = face_1->get_fe(face_1_index);
-
-          Assert(component_mask.represents_n_components(fe.n_components()),
-                 ExcMessage ("The number of components in the mask has to be either "
-                             "zero or equal to the number of components in the finite " "element."));
-
-          const unsigned int dofs_per_face = fe.dofs_per_face;
-
-          std::vector<types::global_dof_index> dofs_1(dofs_per_face);
-          std::vector<types::global_dof_index> dofs_2(dofs_per_face);
-
-          face_1->get_dof_indices(dofs_1, face_1_index);
-          face_2->get_dof_indices(dofs_2, face_2_index);
-
-          // Well, this is a hack:
-          //
-          // There is no
-          //   face_to_face_index(face_index,
-          //                      face_orientation,
-          //                      face_flip,
-          //                      face_rotation)
-          // function in FiniteElementData, so we have to use
-          //   face_to_cell_index(face_index, face
-          //                      face_orientation,
-          //                      face_flip,
-          //                      face_rotation)
-          // But this will give us an index on a cell - something we cannot work
-          // with directly. But luckily we can match them back :-]
-
-          std::map<unsigned int, unsigned int> cell_to_rotated_face_index;
-
-          // Build up a cell to face index for face_2:
-          for (unsigned int i = 0; i < dofs_per_face; ++i)
-            {
-              const unsigned int cell_index = fe.face_to_cell_index(i, 0, /* It doesn't really matter, just assume
-                                                                           * we're on the first face...
-                                                                           */
-                                                                    true, false, false // default orientation
-                                                                   );
-              cell_to_rotated_face_index[cell_index] = i;
-            }
-
-          // loop over all dofs on face 2 and constrain them again the ones on face 1
-          for (unsigned int i=0; i<dofs_per_face; ++i)
-            if (!constraint_matrix.is_constrained(dofs_2[i]))
-              if ((component_mask.n_selected_components(fe.n_components())
-                   == fe.n_components())
-                  ||
-                  component_mask[fe.face_system_to_component_index(i).first])
-                {
-                  // as mentioned in the comment above this function, we need
-                  // to be careful about treating identity constraints differently.
-                  // consequently, find out whether this dof 'i' will be
-                  // identity constrained
-                  //
-                  // to check whether this is the case, first see whether there are
-                  // any weights other than 0 and 1, then in a first stage make sure
-                  // that if so there is only one weight equal to 1
-                  bool is_identity_constrained = true;
-                  for (unsigned int jj=0; jj<dofs_per_face; ++jj)
-                    if (((transformation(i,jj) == 0) || (transformation(i,jj) == 1)) == false)
-                      {
-                        is_identity_constrained = false;
-                        break;
-                      }
-                  unsigned int identity_constraint_target = numbers::invalid_unsigned_int;
-                  if (is_identity_constrained == true)
-                    {
-                      bool one_identity_found = false;
-                      for (unsigned int jj=0; jj<dofs_per_face; ++jj)
-                        if (transformation(i,jj) == 1)
-                          {
-                            if (one_identity_found == false)
-                              {
-                                one_identity_found = true;
-                                identity_constraint_target = jj;
-                              }
-                            else
-                              {
-                                is_identity_constrained = false;
-                                identity_constraint_target = numbers::invalid_unsigned_int;
-                                break;
-                              }
-                          }
-                    }
-
-                  // now treat constraints, either as an equality constraint or
-                  // as a sequence of constraints
-                  if (is_identity_constrained == true)
-                    {
-                      // Query the correct face_index on face_2 respecting the given
-                      // orientation:
-                      const unsigned int j =
-                        cell_to_rotated_face_index[fe.face_to_cell_index(identity_constraint_target,
-                            0, /* It doesn't really matter, just assume
-                           * we're on the first face...
-                           */
-                                                                         face_orientation, face_flip, face_rotation)];
-
-                      // if the two aren't already identity constrained (whichever way
-                      // around, then enter the constraint. otherwise there is nothing
-                      // for us still to do
-                      if (constraint_matrix.are_identity_constrained(dofs_2[i], dofs_1[i]) == false)
-                        {
-                          constraint_matrix.add_line(dofs_2[i]);
-                          constraint_matrix.add_entry(dofs_2[i], dofs_1[j], 1);
-                        }
-                    }
-                  else
-                    {
-                      // this is just a regular constraint. enter it piece by piece
-                      constraint_matrix.add_line(dofs_2[i]);
-                      for (unsigned int jj=0; jj<dofs_per_face; ++jj)
-                        {
-                          // Query the correct face_index on face_2 respecting the given
-                          // orientation:
-                          const unsigned int j =
-                            cell_to_rotated_face_index[fe.face_to_cell_index(jj, 0, /* It doesn't really matter, just assume
-                               * we're on the first face...
-                               */
-                                                                             face_orientation, face_flip, face_rotation)];
-
-                          // And finally constrain the two DoFs respecting component_mask:
-                          if (transformation(i,jj) != 0)
-                            constraint_matrix.add_entry(dofs_2[i], dofs_1[j],
-                                                        transformation(i,jj));
-                        }
-                    }
-                }
-        }
-    }
-  }
-
-
-  template <typename FaceIterator>
-  void
-  make_periodicity_constraints (const FaceIterator                          &face_1,
-                                const typename identity<FaceIterator>::type &face_2,
-                                dealii::ConstraintMatrix                    &constraint_matrix,
-                                const ComponentMask                         &component_mask,
-                                const bool                                   face_orientation,
-                                const bool                                   face_flip,
-                                const bool                                   face_rotation)
-  {
-    static const int dim = FaceIterator::AccessorType::dimension;
-
-    Assert( (dim != 1) ||
-            (face_orientation == true &&
-             face_flip == false &&
-             face_rotation == false),
-            ExcMessage ("The supplied orientation "
-                        "(face_orientation, face_flip, face_rotation) "
-                        "is invalid for 1D"));
-
-    Assert( (dim != 2) ||
-            (face_orientation == true &&
-             face_rotation == false),
-            ExcMessage ("The supplied orientation "
-                        "(face_orientation, face_flip, face_rotation) "
-                        "is invalid for 2D"));
-
-    Assert(face_1 != face_2,
-           ExcMessage ("face_1 and face_2 are equal! Cannot constrain DoFs "
-                       "on the very same face"));
-
-    Assert(face_1->at_boundary() && face_2->at_boundary(),
-           ExcMessage ("Faces for periodicity constraints must be on the boundary"));
-
-
-    // A lookup table on how to go through the child faces depending on the
-    // orientation:
-
-    static const int lookup_table_2d[2][2] =
-    {
-      //          flip:
-      {0, 1}, //  false
-      {1, 0}, //  true
-    };
-
-    static const int lookup_table_3d[2][2][2][4] =
-    {
-      //                    orientation flip  rotation
-      { { {0, 2, 1, 3}, //  false       false false
-          {2, 3, 0, 1}, //  false       false true
-        },
-        { {3, 1, 2, 0}, //  false       true  false
-          {1, 0, 3, 2}, //  false       true  true
-        },
-      },
-      { { {0, 1, 2, 3}, //  true        false false
-          {1, 3, 0, 2}, //  true        false true
-        },
-        { {3, 2, 1, 0}, //  true        true  false
-          {2, 0, 3, 1}, //  true        true  true
-        },
-      },
-    };
-
-    // In the case that both faces have children, we loop over all
-    // children and apply make_periodicty_constrains recursively:
-    if (face_1->has_children() && face_2->has_children())
-      {
-        Assert(face_1->n_children() == GeometryInfo<dim>::max_children_per_face &&
-               face_2->n_children() == GeometryInfo<dim>::max_children_per_face,
-               ExcNotImplemented());
-
-        for (unsigned int i = 0; i < GeometryInfo<dim>::max_children_per_face; ++i)
-          {
-            // Lookup the index for the second face
-            unsigned int j;
-            switch (dim)
-              {
-              case 2:
-                j = lookup_table_2d[face_flip][i];
-                break;
-              case 3:
-                j = lookup_table_3d[face_orientation][face_flip][face_rotation][i];
-                break;
-              default:
-                AssertThrow(false, ExcNotImplemented());
-              }
-
-            make_periodicity_constraints (face_1->child(i),
-                                          face_2->child(j),
-                                          constraint_matrix,
-                                          component_mask,
-                                          face_orientation,
-                                          face_flip,
-                                          face_rotation);
-          }
-      }
-    else
-      // otherwise at least one of the two faces is active and
-      // we need to enter the constraints
-      {
-        if (face_2->has_children() == false)
-          set_periodicity_constraints(face_2, face_1,
-                                      FullMatrix<double>(IdentityMatrix(face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face)),
-                                      constraint_matrix,
-                                      component_mask,
-                                      face_orientation, face_flip, face_rotation);
-        else
-          set_periodicity_constraints(face_1, face_2,
-                                      FullMatrix<double>(IdentityMatrix(face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face)),
-                                      constraint_matrix,
-                                      component_mask,
-                                      face_orientation, face_flip, face_rotation);
-      }
-  }
-
-
-
-  template<typename DH>
-  void
-  make_periodicity_constraints (const DH                       &dof_handler,
-                                const types::boundary_id       b_id1,
-                                const types::boundary_id       b_id2,
-                                const int                      direction,
-                                dealii::ConstraintMatrix       &constraint_matrix,
-                                const ComponentMask            &component_mask)
-  {
-    Tensor<1,DH::space_dimension> dummy;
-    make_periodicity_constraints (dof_handler,
-                                  b_id1,
-                                  b_id2,
-                                  direction,
-                                  dummy,
-                                  constraint_matrix,
-                                  component_mask);
-  }
-
-
-
-  template<typename DH>
-  void
-  make_periodicity_constraints (const DH                  &dof_handler,
-                                const types::boundary_id  b_id1,
-                                const types::boundary_id  b_id2,
-                                const int                 direction,
-                                dealii::Tensor<1,DH::space_dimension> &offset,
-                                dealii::ConstraintMatrix  &constraint_matrix,
-                                const ComponentMask       &component_mask)
-  {
-    static const int space_dim = DH::space_dimension;
-    Assert (0<=direction && direction<space_dim,
-            ExcIndexRange (direction, 0, space_dim));
-
-#if defined(DEBUG) && defined(DEAL_II_WITH_P4EST)
-    // Check whether we run on a non parallel mesh or on a
-    // parallel::distributed::Triangulation in serial
-    {
-      typedef parallel::distributed::Triangulation<DH::dimension,DH::space_dimension> PTRIA;
-      const PTRIA *ptria_p = dynamic_cast<const PTRIA *> (&dof_handler.get_tria());
-      Assert ((ptria_p == 0 || Utilities::MPI::n_mpi_processes(ptria_p->get_communicator()) == 1),
-              ExcMessage ("This function can not be used with distributed triangulations."
-                          "See the documentation for more information."));
-    }
-#endif
-
-    Assert (b_id1 != b_id2,
-            ExcMessage ("The boundary indicators b_id1 and b_id2 must be"
-                        "different to denote different boundaries."));
-
-    typedef typename DH::face_iterator FaceIterator;
-    typedef std::map<FaceIterator, std::pair<FaceIterator, std::bitset<3> > > FaceMap;
-
-    // Collect matching periodic cells on the coarsest level:
-    FaceMap matched_cells =
-      GridTools::collect_periodic_face_pairs(dof_handler,
-                                             b_id1, b_id2,
-                                             direction, offset);
-
-    // And apply the low level make_periodicity_constraints function to
-    // every matching pair:
-    for (typename FaceMap::iterator it = matched_cells.begin();
-         it != matched_cells.end(); ++it)
-      {
-        typedef typename DH::face_iterator FaceIterator;
-        const FaceIterator &face_1 = it->first;
-        const FaceIterator &face_2 = it->second.first;
-        const std::bitset<3> &orientation = it->second.second;
-
-        Assert(face_1->at_boundary() && face_2->at_boundary(),
-               ExcInternalError());
-
-        Assert (face_1->boundary_indicator() == b_id1 &&
-                face_2->boundary_indicator() == b_id2,
-                ExcInternalError());
-
-        Assert (face_1 != face_2,
-                ExcInternalError());
-
-        make_periodicity_constraints(face_1,
-                                     face_2,
-                                     constraint_matrix,
-                                     component_mask,
-                                     orientation[0],
-                                     orientation[1],
-                                     orientation[2]);
-      }
-  }
-
-
-
-  template<typename DH>
-  void
-  make_periodicity_constraints (const DH                       &dof_handler,
-                                const types::boundary_id       b_id,
-                                const int                      direction,
-                                dealii::ConstraintMatrix       &constraint_matrix,
-                                const ComponentMask            &component_mask)
-  {
-    Tensor<1,DH::space_dimension> dummy;
-    make_periodicity_constraints (dof_handler,
-                                  b_id,
-                                  direction,
-                                  dummy,
-                                  constraint_matrix,
-                                  component_mask);
-  }
-
-
-
-  template<typename DH>
-  void
-  make_periodicity_constraints (const DH                  &dof_handler,
-                                const types::boundary_id  b_id,
-                                const int                 direction,
-                                dealii::Tensor<1,DH::space_dimension> &offset,
-                                dealii::ConstraintMatrix  &constraint_matrix,
-                                const ComponentMask       &component_mask)
-  {
-    static const int dim = DH::dimension;
-    static const int space_dim = DH::space_dimension;
-
-    Assert (0<=direction && direction<space_dim,
-            ExcIndexRange (direction, 0, space_dim));
-
-    Assert(dim == space_dim,
-           ExcNotImplemented());
-
-#if defined(DEBUG) && defined(DEAL_II_WITH_P4EST)
-    // Check whether we run on a non parallel mesh or on a
-    // parallel::distributed::Triangulation in serial
-    {
-      typedef typename parallel::distributed::Triangulation<DH::dimension,DH::space_dimension> PTRIA;
-      const PTRIA *ptria_p = dynamic_cast<const PTRIA *> (&dof_handler.get_tria());
-      Assert ((ptria_p == 0 || Utilities::MPI::n_mpi_processes(ptria_p->get_communicator()) == 1),
-              ExcMessage ("This function can not be used with distributed triangulations."
-                          "See the documentation for more information."));
-    }
-#endif
-
-    typedef typename DH::face_iterator FaceIterator;
-    typedef std::map<FaceIterator, FaceIterator> FaceMap;
-
-    // Collect matching periodic cells on the coarsest level:
-    FaceMap matched_cells =
-      GridTools::collect_periodic_face_pairs(dof_handler,
-                                             b_id,
-                                             direction, offset);
-
-    // And apply the low level make_periodicity_constraints function to
-    // every matching pair:
-    for (typename FaceMap::iterator it = matched_cells.begin();
-         it != matched_cells.end(); ++it)
-      {
-        typedef typename DH::face_iterator FaceIterator;
-        const FaceIterator &face_1 = it->first;
-        const FaceIterator &face_2 = it->second;
-
-        Assert(face_1->at_boundary() && face_2->at_boundary(),
-               ExcInternalError());
-
-        Assert (face_1->boundary_indicator() == b_id &&
-                face_2->boundary_indicator() == b_id,
-                ExcInternalError());
-
-        Assert (face_1 != face_2,
-                ExcInternalError());
-
-        make_periodicity_constraints(face_1,
-                                     face_2,
-                                     constraint_matrix,
-                                     component_mask
-                                     /* standard orientation */);
-      }
-  }
-
-
-
   namespace internal
   {
     // return an array that for each dof on the reference cell
@@ -4719,677 +1512,6 @@ namespace DoFTools
 
 
 
-
-  namespace internal
-  {
-    namespace
-    {
-      /**
-       * This is a function that is called by the _2 function and that
-       * operates on a range of cells only. It is used to split up the
-       * whole range of cells into chunks which are then worked on in
-       * parallel, if multithreading is available.
-       */
-      template <int dim, int spacedim>
-      void
-      compute_intergrid_weights_3 (
-        const dealii::DoFHandler<dim,spacedim>              &coarse_grid,
-        const unsigned int                  coarse_component,
-        const InterGridMap<dealii::DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
-        const std::vector<dealii::Vector<double> > &parameter_dofs,
-        const std::vector<types::global_dof_index>             &weight_mapping,
-        std::vector<std::map<types::global_dof_index, float> > &weights,
-        const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &begin,
-        const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &end)
-      {
-        // aliases to the finite elements used by the dof handlers:
-        const FiniteElement<dim,spacedim> &coarse_fe = coarse_grid.get_fe();
-
-        // for each cell on the parameter grid: find out which degrees of
-        // freedom on the fine grid correspond in which way to the degrees
-        // of freedom on the parameter grid
-        //
-        // since for continuous FEs some dofs exist on more than one cell,
-        // we have to track which ones were already visited. the problem is
-        // that if we visit a dof first on one cell and compute its weight
-        // with respect to some global dofs to be non-zero, and later visit
-        // the dof again on another cell and (since we are on another cell)
-        // recompute the weights with respect to the same dofs as above to
-        // be zero now, we have to preserve them. we therefore overwrite
-        // all weights if they are nonzero and do not enforce zero weights
-        // since that might be only due to the fact that we are on another
-        // cell.
-        //
-        // example:
-        // coarse grid
-        //  |     |     |
-        //  *-----*-----*
-        //  | cell|cell |
-        //  |  1  |  2  |
-        //  |     |     |
-        //  0-----1-----*
-        //
-        // fine grid
-        //  |  |  |  |  |
-        //  *--*--*--*--*
-        //  |  |  |  |  |
-        //  *--*--*--*--*
-        //  |  |  |  |  |
-        //  *--x--y--*--*
-        //
-        // when on cell 1, we compute the weights of dof 'x' to be 1/2 from
-        // parameter dofs 0 and 1, respectively. however, when later we are
-        // on cell 2, we again compute the prolongation of shape function 1
-        // restricted to cell 2 to the globla grid and find that the weight
-        // of global dof 'x' now is zero. however, we should not overwrite
-        // the old value.
-        //
-        // we therefore always only set nonzero values. why adding up is
-        // not useful: dof 'y' would get weight 1 from parameter dof 1 on
-        // both cells 1 and 2, but the correct weight is nevertheless only
-        // 1.
-
-        // vector to hold the representation of a single degree of freedom
-        // on the coarse grid (for the selected fe) on the fine grid
-        const types::global_dof_index n_fine_dofs = weight_mapping.size();
-        dealii::Vector<double> global_parameter_representation (n_fine_dofs);
-
-        typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator cell;
-        std::vector<types::global_dof_index> parameter_dof_indices (coarse_fe.dofs_per_cell);
-
-        for (cell=begin; cell!=end; ++cell)
-          {
-            // get the global indices of the parameter dofs on this
-            // parameter grid cell
-            cell->get_dof_indices (parameter_dof_indices);
-
-            // loop over all dofs on this cell and check whether they are
-            // interesting for us
-            for (unsigned int local_dof=0;
-                 local_dof<coarse_fe.dofs_per_cell;
-                 ++local_dof)
-              if (coarse_fe.system_to_component_index(local_dof).first
-                  ==
-                  coarse_component)
-                {
-                  // the how-many-th parameter is this on this cell?
-                  const unsigned int local_parameter_dof
-                    = coarse_fe.system_to_component_index(local_dof).second;
-
-                  global_parameter_representation = 0;
-
-                  // distribute the representation of
-                  // @p{local_parameter_dof} on the parameter grid cell
-                  // @p{cell} to the global data space
-                  coarse_to_fine_grid_map[cell]->
-                  set_dof_values_by_interpolation (parameter_dofs[local_parameter_dof],
-                                                   global_parameter_representation);
-                  // now that we've got the global representation of each
-                  // parameter dof, we've only got to clobber the non-zero
-                  // entries in that vector and store the result
-                  //
-                  // what we have learned: if entry @p{i} of the global
-                  // vector holds the value @p{v[i]}, then this is the
-                  // weight with which the present dof contributes to
-                  // @p{i}. there may be several such @p{i}s and their
-                  // weights' sum should be one. Then, @p{v[i]} should be
-                  // equal to @p{\sum_j w_{ij} p[j]} with @p{p[j]} be the
-                  // values of the degrees of freedom on the coarse grid.
-                  // we can thus compute constraints which link the degrees
-                  // of freedom @p{v[i]} on the fine grid to those on the
-                  // coarse grid, @p{p[j]}. Now to use these as real
-                  // constraints, rather than as additional equations, we
-                  // have to identify representants among the @p{i} for
-                  // each @p{j}. this will be done by simply taking the
-                  // first @p{i} for which @p{w_{ij}==1}.
-                  //
-                  // guard modification of the weights array by a Mutex.
-                  // since it should happen rather rarely that there are
-                  // several threads operating on different intergrid
-                  // weights, have only one mutex for all of them
-                  static Threads::Mutex mutex;
-                  Threads::Mutex::ScopedLock lock (mutex);
-                  for (types::global_dof_index i=0; i<global_parameter_representation.size(); ++i)
-                    // set this weight if it belongs to a parameter dof.
-                    if (weight_mapping[i] != numbers::invalid_dof_index)
-                      {
-                        // only overwrite old value if not by zero
-                        if (global_parameter_representation(i) != 0)
-                          {
-                            const types::global_dof_index wi = parameter_dof_indices[local_dof],
-                                                          wj = weight_mapping[i];
-                            weights[wi][wj] = global_parameter_representation(i);
-                          };
-                      }
-                    else
-                      Assert (global_parameter_representation(i) == 0,
-                              ExcInternalError());
-                }
-          }
-      }
-
-
-      /**
-       * This is a helper function that is used in the computation of
-       * integrid constraints. See the function for a thorough description
-       * of how it works.
-       */
-      template <int dim, int spacedim>
-      void
-      compute_intergrid_weights_2 (
-        const dealii::DoFHandler<dim,spacedim>              &coarse_grid,
-        const unsigned int                  coarse_component,
-        const InterGridMap<dealii::DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
-        const std::vector<dealii::Vector<double> > &parameter_dofs,
-        const std::vector<types::global_dof_index>             &weight_mapping,
-        std::vector<std::map<types::global_dof_index,float> > &weights)
-      {
-        // simply distribute the range of cells to different threads
-        typedef typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator active_cell_iterator;
-        std::vector<std::pair<active_cell_iterator,active_cell_iterator> >
-        cell_intervals = Threads::split_range<active_cell_iterator> (coarse_grid.begin_active(),
-                         coarse_grid.end(),
-                         multithread_info.n_default_threads);
-
-        // TODO: use WorkStream here
-
-        Threads::TaskGroup<> tasks;
-        void (*fun_ptr) (const dealii::DoFHandler<dim,spacedim> &,
-                         const unsigned int                  ,
-                         const InterGridMap<dealii::DoFHandler<dim,spacedim> > &,
-                         const std::vector<dealii::Vector<double> > &,
-                         const std::vector<types::global_dof_index> &,
-                         std::vector<std::map<types::global_dof_index, float> > &,
-                         const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &,
-                         const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &)
-          = &compute_intergrid_weights_3<dim>;
-        for (unsigned int i=0; i<multithread_info.n_default_threads; ++i)
-          tasks += Threads::new_task (fun_ptr,
-                                      coarse_grid, coarse_component,
-                                      coarse_to_fine_grid_map, parameter_dofs,
-                                      weight_mapping, weights,
-                                      cell_intervals[i].first,
-                                      cell_intervals[i].second);
-
-        // wait for the tasks to finish
-        tasks.join_all ();
-      }
-
-
-
-      /**
-       * This is a helper function that is used in the computation of
-       * integrid constraints. See the function for a thorough description
-       * of how it works.
-       */
-      template <int dim, int spacedim>
-      unsigned int
-      compute_intergrid_weights_1 (
-        const dealii::DoFHandler<dim,spacedim>              &coarse_grid,
-        const unsigned int                  coarse_component,
-        const dealii::DoFHandler<dim,spacedim>              &fine_grid,
-        const unsigned int                  fine_component,
-        const InterGridMap<dealii::DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
-        std::vector<std::map<types::global_dof_index, float> > &weights,
-        std::vector<types::global_dof_index>                   &weight_mapping)
-      {
-        // aliases to the finite elements used by the dof handlers:
-        const FiniteElement<dim,spacedim> &coarse_fe = coarse_grid.get_fe(),
-                                           &fine_fe   = fine_grid.get_fe();
-
-        // global numbers of dofs
-        const types::global_dof_index n_coarse_dofs = coarse_grid.n_dofs(),
-                                      n_fine_dofs   = fine_grid.n_dofs();
-
-        // local numbers of dofs
-        const unsigned int fine_dofs_per_cell   = fine_fe.dofs_per_cell;
-
-        // alias the number of dofs per cell belonging to the
-        // coarse_component which is to be the restriction of the fine
-        // grid:
-        const unsigned int coarse_dofs_per_cell_component
-          = coarse_fe.base_element(coarse_fe.component_to_base_index(coarse_component).first).dofs_per_cell;
-
-
-        // Try to find out whether the grids stem from the same coarse
-        // grid. This is a rather crude test, but better than nothing
-        Assert (coarse_grid.get_tria().n_cells(0) == fine_grid.get_tria().n_cells(0),
-                ExcGridsDontMatch());
-
-        // check whether the map correlates the right objects
-        Assert (&coarse_to_fine_grid_map.get_source_grid() == &coarse_grid,
-                ExcGridsDontMatch ());
-        Assert (&coarse_to_fine_grid_map.get_destination_grid() == &fine_grid,
-                ExcGridsDontMatch ());
-
-
-        // check whether component numbers are valid
-        AssertIndexRange (coarse_component,coarse_fe.n_components());
-        AssertIndexRange (fine_component, fine_fe.n_components());
-
-        // check whether respective finite elements are equal
-        Assert (coarse_fe.base_element (coarse_fe.component_to_base_index(coarse_component).first)
-                ==
-                fine_fe.base_element (fine_fe.component_to_base_index(fine_component).first),
-                ExcFiniteElementsDontMatch());
-
-#ifdef DEBUG
-        // if in debug mode, check whether the coarse grid is indeed
-        // coarser everywhere than the fine grid
-        for (typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator
-             cell=coarse_grid.begin_active();
-             cell != coarse_grid.end(); ++cell)
-          Assert (cell->level() <= coarse_to_fine_grid_map[cell]->level(),
-                  ExcGridNotCoarser());
-#endif
-
-        /*
-         * From here on: the term `parameter' refers to the selected
-         * component on the coarse grid and its analogon on the fine grid.
-         * The naming of variables containing this term is due to the fact
-         * that `selected_component' is longer, but also due to the fact
-         * that the code of this function was initially written for a
-         * program where the component which we wanted to match between
-         * grids was actually the `parameter' variable.
-         *
-         * Likewise, the terms `parameter grid' and `state grid' refer to
-         * the coarse and fine grids, respectively.
-         *
-         * Changing the names of variables would in principle be a good
-         * idea, but would not make things simpler and would be another
-         * source of errors. If anyone feels like doing so: patches would
-         * be welcome!
-         */
-
-
-
-        // set up vectors of cell-local data; each vector represents one
-        // degree of freedom of the coarse-grid variable in the fine-grid
-        // element
-        std::vector<dealii::Vector<double> >
-        parameter_dofs (coarse_dofs_per_cell_component,
-                        dealii::Vector<double>(fine_dofs_per_cell));
-        // for each coarse dof: find its position within the fine element
-        // and set this value to one in the respective vector (all other
-        // values are zero by construction)
-        for (unsigned int local_coarse_dof=0;
-             local_coarse_dof<coarse_dofs_per_cell_component;
-             ++local_coarse_dof)
-          for (unsigned int fine_dof=0; fine_dof<fine_fe.dofs_per_cell; ++fine_dof)
-            if (fine_fe.system_to_component_index(fine_dof)
-                ==
-                std::make_pair (fine_component, local_coarse_dof))
-              {
-                parameter_dofs[local_coarse_dof](fine_dof) = 1.;
-                break;
-              };
-
-
-        // find out how many DoFs there are on the grids belonging to the
-        // components we want to match
-        unsigned int n_parameters_on_fine_grid=0;
-        if (true)
-          {
-            // have a flag for each dof on the fine grid and set it to true
-            // if this is an interesting dof. finally count how many true's
-            // there
-            std::vector<bool> dof_is_interesting (fine_grid.n_dofs(), false);
-            std::vector<types::global_dof_index>  local_dof_indices (fine_fe.dofs_per_cell);
-
-            for (typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator
-                 cell=fine_grid.begin_active();
-                 cell!=fine_grid.end(); ++cell)
-              {
-                cell->get_dof_indices (local_dof_indices);
-                for (unsigned int i=0; i<fine_fe.dofs_per_cell; ++i)
-                  if (fine_fe.system_to_component_index(i).first == fine_component)
-                    dof_is_interesting[local_dof_indices[i]] = true;
-              };
-
-            n_parameters_on_fine_grid = std::count (dof_is_interesting.begin(),
-                                                    dof_is_interesting.end(),
-                                                    true);
-          };
-
-
-        // set up the weights mapping
-        weights.clear ();
-        weights.resize (n_coarse_dofs);
-
-        weight_mapping.clear ();
-        weight_mapping.resize (n_fine_dofs, numbers::invalid_dof_index);
-
-        if (true)
-          {
-            std::vector<types::global_dof_index> local_dof_indices(fine_fe.dofs_per_cell);
-            unsigned int next_free_index=0;
-            for (typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator
-                 cell=fine_grid.begin_active();
-                 cell != fine_grid.end(); ++cell)
-              {
-                cell->get_dof_indices (local_dof_indices);
-                for (unsigned int i=0; i<fine_fe.dofs_per_cell; ++i)
-                  // if this DoF is a parameter dof and has not yet been
-                  // numbered, then do so
-                  if ((fine_fe.system_to_component_index(i).first == fine_component) &&
-                      (weight_mapping[local_dof_indices[i]] == numbers::invalid_dof_index))
-                    {
-                      weight_mapping[local_dof_indices[i]] = next_free_index;
-                      ++next_free_index;
-                    };
-              };
-
-            Assert (next_free_index == n_parameters_on_fine_grid,
-                    ExcInternalError());
-          };
-
-
-        // for each cell on the parameter grid: find out which degrees of
-        // freedom on the fine grid correspond in which way to the degrees
-        // of freedom on the parameter grid
-        //
-        // do this in a separate function to allow for multithreading
-        // there. see this function also if you want to read more
-        // information on the algorithm used.
-        compute_intergrid_weights_2 (coarse_grid, coarse_component,
-                                     coarse_to_fine_grid_map, parameter_dofs,
-                                     weight_mapping, weights);
-
-
-        // ok, now we have all weights for each dof on the fine grid. if in
-        // debug mode lets see if everything went smooth, i.e. each dof has
-        // sum of weights one
-        //
-        // in other words this means that if the sum of all shape functions
-        // on the parameter grid is one (which is always the case), then
-        // the representation on the state grid should be as well (division
-        // of unity)
-        //
-        // if the parameter grid has more than one component, then the
-        // respective dofs of the other components have sum of weights
-        // zero, of course. we do not explicitly ask which component a dof
-        // belongs to, but this at least tests some errors
-#ifdef DEBUG
-        for (unsigned int col=0; col<n_parameters_on_fine_grid; ++col)
-          {
-            double sum=0;
-            for (types::global_dof_index row=0; row<n_coarse_dofs; ++row)
-              if (weights[row].find(col) != weights[row].end())
-                sum += weights[row][col];
-            Assert ((std::fabs(sum-1) < 1.e-12) ||
-                    ((coarse_fe.n_components()>1) && (sum==0)), ExcInternalError());
-          };
-#endif
-
-
-        return n_parameters_on_fine_grid;
-      }
-
-
-    }
-  }
-
-
-
-  template <int dim, int spacedim>
-  void
-  compute_intergrid_constraints (
-    const DoFHandler<dim,spacedim>              &coarse_grid,
-    const unsigned int                  coarse_component,
-    const DoFHandler<dim,spacedim>              &fine_grid,
-    const unsigned int                  fine_component,
-    const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
-    ConstraintMatrix                   &constraints)
-  {
-    // store the weights with which a dof on the parameter grid contributes
-    // to a dof on the fine grid. see the long doc below for more info
-    //
-    // allocate as many rows as there are parameter dofs on the coarse grid
-    // and as many columns as there are parameter dofs on the fine grid.
-    //
-    // weight_mapping is used to map the global (fine grid) parameter dof
-    // indices to the columns
-    //
-    // in the original implementation, the weights array was actually of
-    // FullMatrix<double> type. this wasted huge amounts of memory, but was
-    // fast. nonetheless, since the memory consumption was quadratic in the
-    // number of degrees of freedom, this was not very practical, so we now
-    // use a vector of rows of the matrix, and in each row a vector of
-    // pairs (colnum,value). this seems like the best tradeoff between
-    // memory and speed, as it is now linear in memory and still fast
-    // enough.
-    //
-    // to save some memory and since the weights are usually (negative)
-    // powers of 2, we choose the value type of the matrix to be @p{float}
-    // rather than @p{double}.
-    std::vector<std::map<types::global_dof_index, float> > weights;
-
-    // this is this mapping. there is one entry for each dof on the fine
-    // grid; if it is a parameter dof, then its value is the column in
-    // weights for that parameter dof, if it is any other dof, then its
-    // value is -1, indicating an error
-    std::vector<types::global_dof_index> weight_mapping;
-
-    const unsigned int n_parameters_on_fine_grid
-      = internal::compute_intergrid_weights_1 (coarse_grid, coarse_component,
-                                               fine_grid, fine_component,
-                                               coarse_to_fine_grid_map,
-                                               weights, weight_mapping);
-
-    // global numbers of dofs
-    const types::global_dof_index n_coarse_dofs = coarse_grid.n_dofs(),
-                                  n_fine_dofs   = fine_grid.n_dofs();
-
-
-    // get an array in which we store which dof on the coarse grid is a
-    // parameter and which is not
-    std::vector<bool> coarse_dof_is_parameter (coarse_grid.n_dofs());
-    if (true)
-      {
-        std::vector<bool> mask (coarse_grid.get_fe().n_components(),
-                                false);
-        mask[coarse_component] = true;
-        extract_dofs (coarse_grid, ComponentMask(mask), coarse_dof_is_parameter);
-      }
-
-    // now we know that the weights in each row constitute a constraint.
-    // enter this into the constraints object
-    //
-    // first task: for each parameter dof on the parameter grid, find a
-    // representant on the fine, global grid. this is possible since we use
-    // conforming finite element. we take this representant to be the first
-    // element in this row with weight identical to one. the representant
-    // will become an unconstrained degree of freedom, while all others
-    // will be constrained to this dof (and possibly others)
-    std::vector<types::global_dof_index> representants(n_coarse_dofs, numbers::invalid_dof_index);
-    for (types::global_dof_index parameter_dof=0; parameter_dof<n_coarse_dofs;
-         ++parameter_dof)
-      if (coarse_dof_is_parameter[parameter_dof] == true)
-        {
-          // if this is the line of a parameter dof on the coarse grid,
-          // then it should have at least one dependent node on the fine
-          // grid
-          Assert (weights[parameter_dof].size() > 0, ExcInternalError());
-
-          // find the column where the representant is mentioned
-          std::map<types::global_dof_index,float>::const_iterator i = weights[parameter_dof].begin();
-          for (; i!=weights[parameter_dof].end(); ++i)
-            if (i->second == 1)
-              break;
-          Assert (i!=weights[parameter_dof].end(), ExcInternalError());
-          const types::global_dof_index column = i->first;
-
-          // now we know in which column of weights the representant is,
-          // but we don't know its global index. get it using the inverse
-          // operation of the weight_mapping
-          types::global_dof_index global_dof=0;
-          for (; global_dof<weight_mapping.size(); ++global_dof)
-            if (weight_mapping[global_dof] == static_cast<types::global_dof_index>(column))
-              break;
-          Assert (global_dof < weight_mapping.size(), ExcInternalError());
-
-          // now enter the representants global index into our list
-          representants[parameter_dof] = global_dof;
-        }
-      else
-        {
-          // consistency check: if this is no parameter dof on the coarse
-          // grid, then the respective row must be empty!
-          Assert (weights[parameter_dof].size() == 0, ExcInternalError());
-        };
-
-
-
-    // note for people that want to optimize this function: the largest
-    // part of the computing time is spent in the following, rather
-    // innocent block of code. basically, it must be the
-    // ConstraintMatrix::add_entry call which takes the bulk of the time,
-    // but it is not known to the author how to make it faster...
-    std::vector<std::pair<types::global_dof_index,double> > constraint_line;
-    for (types::global_dof_index global_dof=0; global_dof<n_fine_dofs; ++global_dof)
-      if (weight_mapping[global_dof] != numbers::invalid_dof_index)
-        // this global dof is a parameter dof, so it may carry a constraint
-        // note that for each global dof, the sum of weights shall be one,
-        // so we can find out whether this dof is constrained in the
-        // following way: if the only weight in this row is a one, and the
-        // representant for the parameter dof of the line in which this one
-        // is is the present dof, then we consider this dof to be
-        // unconstrained. otherwise, all other dofs are constrained
-        {
-          const types::global_dof_index col = weight_mapping[global_dof];
-          Assert (col < n_parameters_on_fine_grid, ExcInternalError());
-
-          types::global_dof_index first_used_row=0;
-
-          {
-            Assert (weights.size() > 0, ExcInternalError());
-            std::map<types::global_dof_index,float>::const_iterator
-            col_entry = weights[0].end();
-            for (; first_used_row<n_coarse_dofs; ++first_used_row)
-              {
-                col_entry = weights[first_used_row].find(col);
-                if (col_entry != weights[first_used_row].end())
-                  break;
-              }
-
-            Assert (col_entry != weights[first_used_row].end(), ExcInternalError());
-
-            if ((col_entry->second == 1) &&
-                (representants[first_used_row] == global_dof))
-              // dof unconstrained or constrained to itself (in case this
-              // cell is mapped to itself, rather than to children of
-              // itself)
-              continue;
-          }
-
-
-          // otherwise enter all constraints
-          constraints.add_line (global_dof);
-
-          constraint_line.clear ();
-          for (types::global_dof_index row=first_used_row; row<n_coarse_dofs; ++row)
-            {
-              const std::map<types::global_dof_index,float>::const_iterator
-              j = weights[row].find(col);
-              if ((j != weights[row].end()) && (j->second != 0))
-                constraint_line.push_back (std::pair<types::global_dof_index,double>(representants[row],
-                                           j->second));
-            };
-
-          constraints.add_entries (global_dof, constraint_line);
-        };
-  }
-
-
-
-  template <int dim, int spacedim>
-  void
-  compute_intergrid_transfer_representation (
-    const DoFHandler<dim,spacedim>              &coarse_grid,
-    const unsigned int                  coarse_component,
-    const DoFHandler<dim,spacedim>              &fine_grid,
-    const unsigned int                  fine_component,
-    const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
-    std::vector<std::map<types::global_dof_index, float> > &transfer_representation)
-  {
-    // store the weights with which a dof on the parameter grid contributes
-    // to a dof on the fine grid. see the long doc below for more info
-    //
-    // allocate as many rows as there are parameter dofs on the coarse grid
-    // and as many columns as there are parameter dofs on the fine grid.
-    //
-    // weight_mapping is used to map the global (fine grid) parameter dof
-    // indices to the columns
-    //
-    // in the original implementation, the weights array was actually of
-    // FullMatrix<double> type. this wasted huge amounts of memory, but was
-    // fast. nonetheless, since the memory consumption was quadratic in the
-    // number of degrees of freedom, this was not very practical, so we now
-    // use a vector of rows of the matrix, and in each row a vector of
-    // pairs (colnum,value). this seems like the best tradeoff between
-    // memory and speed, as it is now linear in memory and still fast
-    // enough.
-    //
-    // to save some memory and since the weights are usually (negative)
-    // powers of 2, we choose the value type of the matrix to be @p{float}
-    // rather than @p{double}.
-    std::vector<std::map<types::global_dof_index, float> > weights;
-
-    // this is this mapping. there is one entry for each dof on the fine
-    // grid; if it is a parameter dof, then its value is the column in
-    // weights for that parameter dof, if it is any other dof, then its
-    // value is -1, indicating an error
-    std::vector<types::global_dof_index> weight_mapping;
-
-    internal::compute_intergrid_weights_1 (coarse_grid, coarse_component,
-                                           fine_grid, fine_component,
-                                           coarse_to_fine_grid_map,
-                                           weights, weight_mapping);
-
-    // now compute the requested representation
-    const types::global_dof_index n_global_parm_dofs
-      = std::count_if (weight_mapping.begin(), weight_mapping.end(),
-                       std::bind2nd (std::not_equal_to<types::global_dof_index> (), numbers::invalid_dof_index));
-
-    // first construct the inverse mapping of weight_mapping
-    std::vector<types::global_dof_index> inverse_weight_mapping (n_global_parm_dofs,
-        DoFHandler<dim,spacedim>::invalid_dof_index);
-    for (types::global_dof_index i=0; i<weight_mapping.size(); ++i)
-      {
-        const types::global_dof_index parameter_dof = weight_mapping[i];
-        // if this global dof is a parameter
-        if (parameter_dof != numbers::invalid_dof_index)
-          {
-            Assert (parameter_dof < n_global_parm_dofs, ExcInternalError());
-            Assert ((inverse_weight_mapping[parameter_dof] == DoFHandler<dim,spacedim>::invalid_dof_index),
-                    ExcInternalError());
-
-            inverse_weight_mapping[parameter_dof] = i;
-          };
-      };
-
-    // next copy over weights array and replace respective numbers
-    const types::global_dof_index n_rows = weight_mapping.size();
-
-    transfer_representation.clear ();
-    transfer_representation.resize (n_rows);
-
-    const types::global_dof_index n_coarse_dofs = coarse_grid.n_dofs();
-    for (types::global_dof_index i=0; i<n_coarse_dofs; ++i)
-      {
-        std::map<types::global_dof_index, float>::const_iterator j = weights[i].begin();
-        for (; j!=weights[i].end(); ++j)
-          {
-            const types::global_dof_index p = inverse_weight_mapping[j->first];
-            Assert (p<n_rows, ExcInternalError());
-
-            transfer_representation[p][i] = j->second;
-          };
-      };
-  }
-
-
-
   template <class DH>
   void
   map_dof_to_boundary_indices (const DH                  &dof_handler,
@@ -5689,87 +1811,6 @@ namespace DoFTools
 
 
 
-  template <int dim, int spacedim, template <int,int> class DH>
-  void
-  make_zero_boundary_constraints (const DH<dim, spacedim> &dof,
-                                  const types::boundary_id boundary_indicator,
-                                  ConstraintMatrix        &zero_boundary_constraints,
-                                  const ComponentMask     &component_mask)
-  {
-    Assert (component_mask.represents_n_components(dof.get_fe().n_components()),
-            ExcMessage ("The number of components in the mask has to be either "
-                        "zero or equal to the number of components in the finite "
-                        "element."));
-
-    const unsigned int n_components = DoFTools::n_components (dof);
-
-    Assert (component_mask.n_selected_components(n_components) > 0,
-            VectorTools::ExcNoComponentSelected());
-
-    // a field to store the indices
-    std::vector<types::global_dof_index> face_dofs;
-    face_dofs.reserve (max_dofs_per_face(dof));
-
-    typename DH<dim,spacedim>::active_cell_iterator
-    cell = dof.begin_active(),
-    endc = dof.end();
-    for (; cell!=endc; ++cell)
-      if (!cell->is_artificial())
-        for (unsigned int face_no = 0; face_no < GeometryInfo<dim>::faces_per_cell;
-             ++face_no)
-          {
-            const FiniteElement<dim,spacedim> &fe = cell->get_fe();
-
-            const typename DH<dim,spacedim>::face_iterator face = cell->face(face_no);
-
-            // if face is on the boundary and satisfies the correct
-            // boundary id property
-            if (face->at_boundary ()
-                &&
-                ((boundary_indicator == numbers::invalid_boundary_id)
-                 ||
-                 (face->boundary_indicator() == boundary_indicator)))
-              {
-                // get indices and physical location on this face
-                face_dofs.resize (fe.dofs_per_face);
-                face->get_dof_indices (face_dofs, cell->active_fe_index());
-
-                // enter those dofs into the list that match the component
-                // signature.
-                for (unsigned int i=0; i<face_dofs.size(); ++i)
-                  {
-                    // Find out if a dof has a contribution in this
-                    // component, and if so, add it to the list
-                    const ComponentMask &nonzero_component_array
-                      = cell->get_fe().get_nonzero_components (i);
-                    bool nonzero = false;
-                    for (unsigned int c=0; c<n_components; ++c)
-                      if (nonzero_component_array[c] && component_mask[c])
-                        {
-                          nonzero = true;
-                          break;
-                        }
-
-                    if (nonzero)
-                      zero_boundary_constraints.add_line (face_dofs[i]);
-                  }
-              }
-          }
-  }
-
-
-
-  template <int dim, int spacedim, template <int,int> class DH>
-  void
-  make_zero_boundary_constraints (const DH<dim, spacedim> &dof,
-                                  ConstraintMatrix        &zero_boundary_constraints,
-                                  const ComponentMask     &component_mask)
-  {
-    make_zero_boundary_constraints(dof, numbers::invalid_boundary_id,
-                                   zero_boundary_constraints, component_mask);
-  }
-
-
   template <class DH, class Sparsity>
   void make_cell_patches(
     Sparsity &block_list,
@@ -6029,7 +2070,9 @@ namespace DoFTools
           }
       }
   }
-}
+
+
+} // end of namespace DoFTools
 
 
 
index 17d1beaa6caae0580143f1fd7da74d51ae016837..f4121a9d63dc3533974f6883880f0b7bcfde8115 100644 (file)
 // ---------------------------------------------------------------------
 
 
-
 for (SP : SPARSITY_PATTERNS; deal_II_dimension : DIMENSIONS)
   {
-    template void
-    DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
-    (const DoFHandler<deal_II_dimension,deal_II_dimension> &dof,
-     SP    &sparsity,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
-    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension> &dof,
-     SP    &sparsity,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<MGDoFHandler<deal_II_dimension,deal_II_dimension>, SP>
-    (const MGDoFHandler<deal_II_dimension,deal_II_dimension> &dof,
-     SP    &sparsity,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
-    (const DoFHandler<deal_II_dimension,deal_II_dimension>&,
-     const Table<2,Coupling>&,
-     SP &,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
-    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension>&,
-     const Table<2,Coupling>&,
-     SP &,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<MGDoFHandler<deal_II_dimension,deal_II_dimension>, SP>
-    (const MGDoFHandler<deal_II_dimension,deal_II_dimension>&,
-     const Table<2,Coupling>&,
-     SP &,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
-    (const DoFHandler<deal_II_dimension,deal_II_dimension> &dof_row,
-     const DoFHandler<deal_II_dimension,deal_II_dimension> &dof_col,
-     SP    &sparsity);
-
-    template void
-    DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
-    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension> &dof_row,
-     const hp::DoFHandler<deal_II_dimension,deal_II_dimension> &dof_col,
-     SP    &sparsity);
-
-    template void
-    DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
-    (const DoFHandler<deal_II_dimension>& dof,
-     const std::vector<types::global_dof_index>  &,
-     SP    &);
-
-    template void
-    DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
-    (const hp::DoFHandler<deal_II_dimension>& dof,
-     const std::vector<types::global_dof_index>  &,
-     SP    &);
-
-    template void
-    DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
-    (const DoFHandler<deal_II_dimension>& dof,
-     const FunctionMap<deal_II_dimension>::type  &boundary_indicators,
-     const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
-     SP    &sparsity);
-
-    template void
-    DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
-    (const hp::DoFHandler<deal_II_dimension>& dof,
-     const FunctionMap<deal_II_dimension>::type  &boundary_indicators,
-     const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
-     SP    &sparsity);
-
-#if deal_II_dimension < 3
-    template void
-    DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
-    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
-     const FunctionMap<deal_II_dimension+1>::type  &boundary_indicators,
-     const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
-     SP    &sparsity);
- #endif
-
-    template void
-    DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
-    (const DoFHandler<deal_II_dimension> &dof,
-     SP    &sparsity);
-
-    template void
-    DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
-    (const hp::DoFHandler<deal_II_dimension> &dof,
-     SP    &sparsity);
-
-    template void
-      DoFTools::make_cell_patches<DoFHandler<deal_II_dimension>,SP>
-      (SP&, const DoFHandler<deal_II_dimension>&, const unsigned int, const std::vector<bool>&, types::global_dof_index);
-
-    template void
-      DoFTools::make_cell_patches<MGDoFHandler<deal_II_dimension>,SP>
-      (SP&, const MGDoFHandler<deal_II_dimension>&, const unsigned int, const std::vector<bool>&, types::global_dof_index);
-
-#if deal_II_dimension > 1
-
-    template void
-    DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
-    (const DoFHandler<deal_II_dimension> &dof,
-     SP    &,
-     const Table<2,Coupling>&,
-     const Table<2,Coupling>&);
-
-    template void
-    DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
-    (const DoFHandler<deal_II_dimension> &dof,
-     SP    &sparsity,
-     const ConstraintMatrix &constraints,
-     const bool, const unsigned int);
-
-    template void
-    DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
-    (const hp::DoFHandler<deal_II_dimension> &dof,
-     SP    &sparsity,
-     const ConstraintMatrix &constraints,
-     const bool, const unsigned int);
-
-    template void
-    DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
-    (const hp::DoFHandler<deal_II_dimension> &dof,
-     SP    &,
-     const Table<2,Coupling>&,
-     const Table<2,Coupling>&);
-#endif
-
-#if deal_II_dimension < 3
-
-    template void
-    DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
-    (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof,
-     SP    &sparsity,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
-    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof,
-     SP    &sparsity,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
-    (const DoFHandler<deal_II_dimension,deal_II_dimension+1>&,
-     const Table<2,Coupling>&,
-     SP &,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
-    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>&,
-     const Table<2,Coupling>&,
-     SP &,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
-    (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_row,
-     const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_col,
-     SP    &sparsity);
-
-    template void
-    DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
-    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_row,
-     const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_col,
-     SP    &sparsity);
-
-    template void
-    DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
-    (const DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
-     const std::vector<types::global_dof_index>  &,
-     SP    &);
-
-    //template void
-    //DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
-    //(const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
-    // const std::vector<types::global_dof_index>  &,
-    // SP    &);
-
-    template void
-    DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
-    (const DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
-     const FunctionMap<deal_II_dimension+1>::type  &boundary_indicators,
-     const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
-     SP    &sparsity);
-
-    //template void
-    //DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
-    //(const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
-    // const FunctionMap<deal_II_dimension+1>::type  &boundary_indicators,
-    // const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
-    // SP    &sparsity);
-
-#endif
-
-
-#if deal_II_dimension == 3
-
-    template void
-    DoFTools::make_sparsity_pattern<DoFHandler<1,3>, SP>
-    (const DoFHandler<1,3> &dof,
-     SP    &sparsity,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<hp::DoFHandler<1,3>, SP>
-    (const hp::DoFHandler<1,3> &dof,
-     SP    &sparsity,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<DoFHandler<1,3>, SP>
-    (const DoFHandler<1,3>&,
-     const Table<2,Coupling>&,
-     SP &,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<hp::DoFHandler<1,3>, SP>
-    (const hp::DoFHandler<1,3>&,
-     const Table<2,Coupling>&,
-     SP &,
-     const ConstraintMatrix &,
-     const bool,
-     const unsigned int);
-
-    template void
-    DoFTools::make_sparsity_pattern<DoFHandler<1,3>, SP>
-    (const DoFHandler<1,3> &dof_row,
-     const DoFHandler<1,3> &dof_col,
-     SP    &sparsity);
-
-    template void
-    DoFTools::make_sparsity_pattern<hp::DoFHandler<1,3>, SP>
-    (const hp::DoFHandler<1,3> &dof_row,
-     const hp::DoFHandler<1,3> &dof_col,
-     SP    &sparsity);
-
-    template void
-    DoFTools::make_boundary_sparsity_pattern<DoFHandler<1,3>,SP>
-    (const DoFHandler<1,3>& dof,
-     const std::vector<types::global_dof_index>  &,
-     SP    &);
-
-    template void
-    DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<1,3>,SP>
-    (const hp::DoFHandler<1,3>& dof,
-     const std::vector<types::global_dof_index>  &,
-     SP    &);
-
-    template void
-    DoFTools::make_boundary_sparsity_pattern<DoFHandler<1,3>,SP>
-    (const DoFHandler<1,3>& dof,
-     const FunctionMap<3>::type  &boundary_indicators,
-     const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
-     SP    &sparsity);
-
-    template void
-    DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<1,3>,SP>
-    (const hp::DoFHandler<1,3>& dof,
-     const FunctionMap<3>::type  &boundary_indicators,
-     const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
-     SP    &sparsity);
-
-#endif
-
-  }
-
+   template void
+   DoFTools::make_cell_patches<DoFHandler<deal_II_dimension>,SP>
+   (SP&, const DoFHandler<deal_II_dimension>&, const unsigned int, const std::vector<bool>&, types::global_dof_index);
 
-
-
-for (DH : DOFHANDLERS; deal_II_dimension : DIMENSIONS)
-{
-  template
-  void
-  DoFTools::make_hanging_node_constraints (const DH &dof_handler,
-                                           ConstraintMatrix &constraints);
-}
-
-
-
-for (DH : DOFHANDLERS; deal_II_dimension : DIMENSIONS)
-{
-
-#if deal_II_dimension != 1
-  template
-  void
-  DoFTools::make_periodicity_constraints (const DH::face_iterator &,
-                                          const DH::face_iterator &,
-                                          dealii::ConstraintMatrix &,
-                                          const ComponentMask &,
-                                          bool, bool, bool);
-
-  template
-  void
-  DoFTools::make_periodicity_constraints(const DH &,
-                                         const types::boundary_id,
-                                         const types::boundary_id,
-                                         const int,
-                                         dealii::ConstraintMatrix &,
-                                         const ComponentMask &);
-
-  template
-  void
-  DoFTools::make_periodicity_constraints(const DH &,
-                                         const types::boundary_id,
-                                         const types::boundary_id,
-                                         const int,
-                                         dealii::Tensor<1,DH::space_dimension> &,
-                                         dealii::ConstraintMatrix &,
-                                         const ComponentMask &);
-
-  template
-  void
-  DoFTools::make_periodicity_constraints(const DH &,
-                                         const types::boundary_id,
-                                         const int,
-                                         dealii::ConstraintMatrix &,
-                                         const ComponentMask &);
-
-  template
-  void
-  DoFTools::make_periodicity_constraints(const DH &,
-                                         const types::boundary_id,
-                                         const int,
-                                         dealii::Tensor<1,DH::space_dimension> &,
-                                         dealii::ConstraintMatrix &,
-                                         const ComponentMask &);
-#endif
+   template void
+   DoFTools::make_cell_patches<MGDoFHandler<deal_II_dimension>,SP>
+   (SP&, const MGDoFHandler<deal_II_dimension>&, const unsigned int, const std::vector<bool>&, types::global_dof_index);
 }
 
-for (deal_II_dimension : DIMENSIONS)
-{
-#if deal_II_dimension != 1
-  template
-  void
-  DoFTools::make_hanging_node_constraints (const MGDoFHandler<deal_II_dimension> &dof_handler,
-                                           ConstraintMatrix &constraints);
-
-#endif
- }
 
 
 for (deal_II_dimension : DIMENSIONS)
 {
-  template
-  Table<2,DoFTools::Coupling>
-  DoFTools::dof_couplings_from_component_couplings
-  (const FiniteElement<deal_II_dimension> &fe,
-   const Table<2,DoFTools::Coupling> &component_couplings);
-
   template
   void DoFTools::make_vertex_patches (SparsityPattern&, const DoFHandler<deal_II_dimension>&,
   unsigned int, bool, bool, bool, bool);
@@ -427,22 +54,6 @@ for (deal_II_dimension : DIMENSIONS)
   void DoFTools::make_child_patches(SparsityPattern&, const MGDoFHandler<deal_II_dimension>&,
   unsigned int, bool, bool);
 
-#if deal_II_dimension < 3
-template
-void
-DoFTools::
-make_hanging_node_constraints (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_handler,
-                               ConstraintMatrix &constraints);
-#endif
-
-#if deal_II_dimension == 3
-template
-void
-DoFTools::
-make_hanging_node_constraints (const DoFHandler<1,3> &dof_handler,
-                               ConstraintMatrix &constraints);
-#endif
-
 
 // TODO: can cleanup a bit more to fit into the scheme used above
 
@@ -912,23 +523,6 @@ DoFTools::count_dofs_per_component<deal_II_dimension> (
   const DoFHandler<deal_II_dimension>&,
   std::vector<types::global_dof_index>&, std::vector<unsigned int>);
 
-template
-void
-DoFTools::compute_intergrid_constraints<deal_II_dimension> (
-  const DoFHandler<deal_II_dimension> &, const unsigned int,
-  const DoFHandler<deal_II_dimension> &, const unsigned int,
-  const InterGridMap<DoFHandler<deal_II_dimension> > &,
-  ConstraintMatrix&);
-
-template
-void
-DoFTools::compute_intergrid_transfer_representation<deal_II_dimension>
-(const DoFHandler<deal_II_dimension> &, const unsigned int,
- const DoFHandler<deal_II_dimension> &, const unsigned int,
- const InterGridMap<DoFHandler<deal_II_dimension> > &,
- std::vector<std::map<types::global_dof_index, float> > &);
-
-
 template
 void
 DoFTools::map_dof_to_boundary_indices<DoFHandler<deal_II_dimension> >
@@ -1089,36 +683,6 @@ DoFTools::convert_couplings_to_blocks (
   const hp::DoFHandler<deal_II_dimension>&, const Table<2, Coupling>&,
   std::vector<Table<2,Coupling> >&);
 
-template
-void
-DoFTools::make_zero_boundary_constraints
-(const DoFHandler<deal_II_dimension> &,
- ConstraintMatrix                    &,
- const ComponentMask             &);
-
-template
-void
-DoFTools::make_zero_boundary_constraints
-(const DoFHandler<deal_II_dimension> &,
- const types::boundary_id          ,
- ConstraintMatrix                    &,
- const ComponentMask             &);
-
-template
-void
-DoFTools::make_zero_boundary_constraints
-(const hp::DoFHandler<deal_II_dimension> &,
- ConstraintMatrix                        &,
- const ComponentMask                 &);
-
-template
-void
-DoFTools::make_zero_boundary_constraints
-(const hp::DoFHandler<deal_II_dimension> &,
- const types::boundary_id          ,
- ConstraintMatrix                        &,
- const ComponentMask                 &);
-
 
 #if deal_II_dimension < 3
 
diff --git a/deal.II/source/dofs/dof_tools_constraints.cc b/deal.II/source/dofs/dof_tools_constraints.cc
new file mode 100644 (file)
index 0000000..6e21770
--- /dev/null
@@ -0,0 +1,2891 @@
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1999 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/base/multithread_info.h>
+#include <deal.II/base/thread_management.h>
+#include <deal.II/base/table.h>
+#include <deal.II/base/template_constraints.h>
+#include <deal.II/base/utilities.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/intergrid_map.h>
+#include <deal.II/grid/grid_tools.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/fe/fe.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/fe/fe_tools.h>
+#include <deal.II/hp/fe_collection.h>
+#include <deal.II/hp/fe_values.h>
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/multigrid/mg_dof_handler.h>
+
+#include <algorithm>
+#include <numeric>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+
+namespace DoFTools
+{
+  namespace internal
+  {
+    namespace
+    {
+      inline bool
+      check_master_dof_list (const FullMatrix<double> &face_interpolation_matrix,
+                             const std::vector<types::global_dof_index> &master_dof_list)
+      {
+        const unsigned int N = master_dof_list.size();
+
+        FullMatrix<double> tmp (N,N);
+        for (unsigned int i=0; i<N; ++i)
+          for (unsigned int j=0; j<N; ++j)
+            tmp(i,j) = face_interpolation_matrix (master_dof_list[i], j);
+
+        // then use the algorithm from FullMatrix::gauss_jordan on this
+        // matrix to find out whether it is singular. the algorithm there
+        // does piviting and at the end swaps rows back into their proper
+        // order -- we omit this step here, since we don't care about the
+        // inverse matrix, all we care about is whether the matrix is
+        // regular or singular
+
+        // first get an estimate of the size of the elements of this
+        // matrix, for later checks whether the pivot element is large
+        // enough, or whether we have to fear that the matrix is not
+        // regular
+        double diagonal_sum = 0;
+        for (unsigned int i=0; i<N; ++i)
+          diagonal_sum += std::fabs(tmp(i,i));
+        const double typical_diagonal_element = diagonal_sum/N;
+
+        // initialize the array that holds the permutations that we find
+        // during pivot search
+        std::vector<unsigned int> p(N);
+        for (unsigned int i=0; i<N; ++i)
+          p[i] = i;
+
+        for (unsigned int j=0; j<N; ++j)
+          {
+            // pivot search: search that part of the line on and right of
+            // the diagonal for the largest element
+            double       max = std::fabs(tmp(j,j));
+            unsigned int r   = j;
+            for (unsigned int i=j+1; i<N; ++i)
+              {
+                if (std::fabs(tmp(i,j)) > max)
+                  {
+                    max = std::fabs(tmp(i,j));
+                    r = i;
+                  }
+              }
+            // check whether the pivot is too small. if that is the case,
+            // then the matrix is singular and we shouldn't use this set of
+            // master dofs
+            if (max < 1.e-12*typical_diagonal_element)
+              return false;
+
+            // row interchange
+            if (r>j)
+              {
+                for (unsigned int k=0; k<N; ++k)
+                  std::swap (tmp(j,k), tmp(r,k));
+
+                std::swap (p[j], p[r]);
+              }
+
+            // transformation
+            const double hr = 1./tmp(j,j);
+            tmp(j,j) = hr;
+            for (unsigned int k=0; k<N; ++k)
+              {
+                if (k==j) continue;
+                for (unsigned int i=0; i<N; ++i)
+                  {
+                    if (i==j) continue;
+                    tmp(i,k) -= tmp(i,j)*tmp(j,k)*hr;
+                  }
+              }
+            for (unsigned int i=0; i<N; ++i)
+              {
+                tmp(i,j) *= hr;
+                tmp(j,i) *= -hr;
+              }
+            tmp(j,j) = hr;
+          }
+
+        // everything went fine, so we can accept this set of master dofs
+        // (at least as far as they have already been collected)
+        return true;
+      }
+
+
+
+      /**
+       * When restricting, on a face, the degrees of freedom of fe1 to the
+       * space described by fe2 (for example for the complex case described
+       * in the @ref hp_paper "hp paper"), we have to select
+       * fe2.dofs_per_face out of the fe1.dofs_per_face face DoFs as the
+       * master DoFs, and the rest become slave dofs. This function selects
+       * which ones will be masters, and which ones will be slaves.
+       *
+       * The function assumes that master_dofs already has size
+       * fe1.dofs_per_face. After the function, exactly fe2.dofs_per_face
+       * entries will be true.
+       *
+       * The function is a bit complicated since it has to figure out a set
+       * a DoFs so that the corresponding rows in the face interpolation
+       * matrix are all linearly independent. we have a good heuristic (see
+       * the function body) for selecting these rows, but there are cases
+       * where this fails and we have to pick them differently. what we do
+       * is to run the heuristic and then go back to determine whether we
+       * have a set of rows with full row rank. if this isn't the case, go
+       * back and select dofs differently
+       */
+      template <int dim, int spacedim>
+      void
+      select_master_dofs_for_face_restriction (const FiniteElement<dim,spacedim> &fe1,
+                                               const FiniteElement<dim,spacedim> &fe2,
+                                               const FullMatrix<double> &face_interpolation_matrix,
+                                               std::vector<bool>        &master_dof_mask)
+      {
+        Assert (fe1.dofs_per_face >= fe2.dofs_per_face,
+                ExcInternalError());
+        AssertDimension (master_dof_mask.size(), fe1.dofs_per_face);
+
+        Assert (fe2.dofs_per_vertex <= fe1.dofs_per_vertex,
+                ExcInternalError());
+        Assert (fe2.dofs_per_line <= fe1.dofs_per_line,
+                ExcInternalError());
+        Assert ((dim < 3)
+                ||
+                (fe2.dofs_per_quad <= fe1.dofs_per_quad),
+                ExcInternalError());
+
+        // the idea here is to designate as many DoFs in fe1 per object
+        // (vertex, line, quad) as master as there are such dofs in fe2
+        // (indices are int, because we want to avoid the 'unsigned int < 0
+        // is always false warning for the cases at the bottom in 1d and
+        // 2d)
+        //
+        // as mentioned in the paper, it is not always easy to find a set
+        // of master dofs that produces an invertible matrix. to this end,
+        // we check in each step whether the matrix is still invertible and
+        // simply discard this dof if the matrix is not invertible anymore.
+        //
+        // the cases where we did have trouble in the past were with adding
+        // more quad dofs when Q3 and Q4 elements meet at a refined face in
+        // 3d (see the hp/crash_12 test that tests that we can do exactly
+        // this, and failed before we had code to compensate for this
+        // case). the other case are system elements: if we have say a Q1Q2
+        // vs a Q2Q3 element, then we can't just take all master dofs on a
+        // line from a single base element, since the shape functions of
+        // that base element are independent of that of the other one. this
+        // latter case shows up when running hp/hp_constraints_q_system_06
+
+        std::vector<types::global_dof_index> master_dof_list;
+        unsigned int index = 0;
+        for (int v=0;
+             v<static_cast<signed int>(GeometryInfo<dim>::vertices_per_face);
+             ++v)
+          {
+            unsigned int dofs_added = 0;
+            unsigned int i          = 0;
+            while (dofs_added < fe2.dofs_per_vertex)
+              {
+                // make sure that we were able to find a set of master dofs
+                // and that the code down below didn't just reject all our
+                // efforts
+                Assert (i < fe1.dofs_per_vertex,
+                        ExcInternalError());
+
+                // tentatively push this vertex dof
+                master_dof_list.push_back (index+i);
+
+                // then see what happens. if it succeeds, fine
+                if (check_master_dof_list (face_interpolation_matrix,
+                                           master_dof_list)
+                    == true)
+                  ++dofs_added;
+                else
+                  // well, it didn't. simply pop that dof from the list
+                  // again and try with the next dof
+                  master_dof_list.pop_back ();
+
+                // forward counter by one
+                ++i;
+              }
+            index += fe1.dofs_per_vertex;
+          }
+
+        for (int l=0;
+             l<static_cast<signed int>(GeometryInfo<dim>::lines_per_face);
+             ++l)
+          {
+            // same algorithm as above
+            unsigned int dofs_added = 0;
+            unsigned int i          = 0;
+            while (dofs_added < fe2.dofs_per_line)
+              {
+                Assert (i < fe1.dofs_per_line,
+                        ExcInternalError());
+
+                master_dof_list.push_back (index+i);
+                if (check_master_dof_list (face_interpolation_matrix,
+                                           master_dof_list)
+                    == true)
+                  ++dofs_added;
+                else
+                  master_dof_list.pop_back ();
+
+                ++i;
+              }
+            index += fe1.dofs_per_line;
+          }
+
+        for (int q=0;
+             q<static_cast<signed int>(GeometryInfo<dim>::quads_per_face);
+             ++q)
+          {
+            // same algorithm as above
+            unsigned int dofs_added = 0;
+            unsigned int i          = 0;
+            while (dofs_added < fe2.dofs_per_quad)
+              {
+                Assert (i < fe1.dofs_per_quad,
+                        ExcInternalError());
+
+                master_dof_list.push_back (index+i);
+                if (check_master_dof_list (face_interpolation_matrix,
+                                           master_dof_list)
+                    == true)
+                  ++dofs_added;
+                else
+                  master_dof_list.pop_back ();
+
+                ++i;
+              }
+            index += fe1.dofs_per_quad;
+          }
+
+        AssertDimension (index, fe1.dofs_per_face);
+        AssertDimension (master_dof_list.size(), fe2.dofs_per_face);
+
+        // finally copy the list into the mask
+        std::fill (master_dof_mask.begin(), master_dof_mask.end(), false);
+        for (std::vector<types::global_dof_index>::const_iterator i=master_dof_list.begin();
+             i!=master_dof_list.end(); ++i)
+          master_dof_mask[*i] = true;
+      }
+
+
+
+      /**
+       * Make sure that the mask exists that determines which dofs will be
+       * the masters on refined faces where an fe1 and a fe2 meet.
+       */
+      template <int dim, int spacedim>
+      void
+      ensure_existence_of_master_dof_mask (const FiniteElement<dim,spacedim> &fe1,
+                                           const FiniteElement<dim,spacedim> &fe2,
+                                           const FullMatrix<double> &face_interpolation_matrix,
+                                           std_cxx1x::shared_ptr<std::vector<bool> > &master_dof_mask)
+      {
+        if (master_dof_mask == std_cxx1x::shared_ptr<std::vector<bool> >())
+          {
+            master_dof_mask = std_cxx1x::shared_ptr<std::vector<bool> >
+                              (new std::vector<bool> (fe1.dofs_per_face));
+            select_master_dofs_for_face_restriction (fe1,
+                                                     fe2,
+                                                     face_interpolation_matrix,
+                                                     *master_dof_mask);
+          }
+      }
+
+
+
+      /**
+       * Make sure that the given @p face_interpolation_matrix pointer
+       * points to a valid matrix. If the pointer is zero beforehand,
+       * create an entry with the correct data. If it is nonzero, don't
+       * touch it.
+       */
+      template <int dim, int spacedim>
+      void
+      ensure_existence_of_face_matrix (const FiniteElement<dim,spacedim> &fe1,
+                                       const FiniteElement<dim,spacedim> &fe2,
+                                       std_cxx1x::shared_ptr<FullMatrix<double> > &matrix)
+      {
+        if (matrix == std_cxx1x::shared_ptr<FullMatrix<double> >())
+          {
+            matrix = std_cxx1x::shared_ptr<FullMatrix<double> >
+                     (new FullMatrix<double> (fe2.dofs_per_face,
+                                              fe1.dofs_per_face));
+            fe1.get_face_interpolation_matrix (fe2,
+                                               *matrix);
+          }
+      }
+
+
+
+      /**
+       * Same, but for subface interpolation matrices.
+       */
+      template <int dim, int spacedim>
+      void
+      ensure_existence_of_subface_matrix (const FiniteElement<dim,spacedim> &fe1,
+                                          const FiniteElement<dim,spacedim> &fe2,
+                                          const unsigned int        subface,
+                                          std_cxx1x::shared_ptr<FullMatrix<double> > &matrix)
+      {
+        if (matrix == std_cxx1x::shared_ptr<FullMatrix<double> >())
+          {
+            matrix = std_cxx1x::shared_ptr<FullMatrix<double> >
+                     (new FullMatrix<double> (fe2.dofs_per_face,
+                                              fe1.dofs_per_face));
+            fe1.get_subface_interpolation_matrix (fe2,
+                                                  subface,
+                                                  *matrix);
+          }
+      }
+
+
+
+      /**
+       * Given the face interpolation matrix between two elements, split it
+       * into its master and slave parts and invert the master part as
+       * explained in the @ref hp_paper "hp paper".
+       */
+      void
+      ensure_existence_of_split_face_matrix (const FullMatrix<double> &face_interpolation_matrix,
+                                             const std::vector<bool> &master_dof_mask,
+                                             std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > > &split_matrix)
+      {
+        AssertDimension (master_dof_mask.size(), face_interpolation_matrix.m());
+        Assert (std::count (master_dof_mask.begin(), master_dof_mask.end(), true) ==
+                static_cast<signed int>(face_interpolation_matrix.n()),
+                ExcInternalError());
+
+        if (split_matrix ==
+            std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > >())
+          {
+            split_matrix
+              = std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > >
+                (new std::pair<FullMatrix<double>,FullMatrix<double> >());
+
+            const unsigned int n_master_dofs = face_interpolation_matrix.n();
+            const unsigned int n_dofs        = face_interpolation_matrix.m();
+
+            Assert (n_master_dofs <= n_dofs, ExcInternalError());
+
+            // copy and invert the master
+            // component, copy the slave
+            // component
+            split_matrix->first.reinit (n_master_dofs, n_master_dofs);
+            split_matrix->second.reinit (n_dofs-n_master_dofs, n_master_dofs);
+
+            unsigned int nth_master_dof = 0,
+                         nth_slave_dof  = 0;
+
+            for (unsigned int i=0; i<n_dofs; ++i)
+              if (master_dof_mask[i] == true)
+                {
+                  for (unsigned int j=0; j<n_master_dofs; ++j)
+                    split_matrix->first(nth_master_dof,j)
+                      = face_interpolation_matrix(i,j);
+                  ++nth_master_dof;
+                }
+              else
+                {
+                  for (unsigned int j=0; j<n_master_dofs; ++j)
+                    split_matrix->second(nth_slave_dof,j)
+                      = face_interpolation_matrix(i,j);
+                  ++nth_slave_dof;
+                }
+
+            AssertDimension (nth_master_dof, n_master_dofs);
+            AssertDimension (nth_slave_dof, n_dofs-n_master_dofs);
+
+            //TODO[WB]: We should make sure very small entries are removed after inversion
+            split_matrix->first.gauss_jordan ();
+          }
+      }
+
+
+      // a template that can determine statically whether a given
+      // DoFHandler class supports different finite element elements
+      template <typename>
+      struct DoFHandlerSupportsDifferentFEs
+      {
+        static const bool value = true;
+      };
+
+
+      template <int dim, int spacedim>
+      struct DoFHandlerSupportsDifferentFEs< dealii::DoFHandler<dim,spacedim> >
+      {
+        static const bool value = false;
+      };
+
+
+      /**
+       * A function that returns how many different finite elements a dof
+       * handler uses. This is one for non-hp DoFHandlers and
+       * dof_handler.get_fe().size() for the hp-versions.
+       */
+      template <int dim, int spacedim>
+      unsigned int
+      n_finite_elements (const dealii::hp::DoFHandler<dim,spacedim> &dof_handler)
+      {
+        return dof_handler.get_fe().size();
+      }
+
+
+      template <class DH>
+      unsigned int
+      n_finite_elements (const DH &)
+      {
+        return 1;
+      }
+
+
+      /**
+       * For a given face belonging to an active cell that borders to a
+       * more refined cell, return the fe_index of the most dominating
+       * finite element used on any of the face's subfaces.
+       */
+      template <typename face_iterator>
+      unsigned int
+      get_most_dominating_subface_fe_index (const face_iterator &face)
+      {
+        const unsigned int dim
+          = face_iterator::AccessorType::dimension;
+        const unsigned int spacedim
+          = face_iterator::AccessorType::space_dimension;
+
+        unsigned int dominating_subface_no = 0;
+        for (; dominating_subface_no<face->n_children();
+             ++dominating_subface_no)
+          {
+            // each of the subfaces can have only a single fe_index
+            // associated with them, since there is no cell on the other
+            // side
+            Assert (face->child(dominating_subface_no)
+                    ->n_active_fe_indices()
+                    == 1,
+                    ExcInternalError());
+
+            const FiniteElement<dim,spacedim> &
+            this_subface_fe = (face->child(dominating_subface_no)
+                               ->get_fe (face->child(dominating_subface_no)
+                                         ->nth_active_fe_index(0)));
+
+            FiniteElementDomination::Domination
+            domination = FiniteElementDomination::either_element_can_dominate;
+            for (unsigned int sf=0; sf<face->n_children(); ++sf)
+              if (sf != dominating_subface_no)
+                {
+                  const FiniteElement<dim,spacedim> &
+                  that_subface_fe = (face->child(sf)
+                                     ->get_fe (face->child(sf)
+                                               ->nth_active_fe_index(0)));
+
+                  domination = domination &
+                               this_subface_fe.compare_for_face_domination(that_subface_fe);
+                }
+
+            // see if the element on this subface is able to dominate the
+            // ones on all other subfaces, and if so take it
+            if ((domination == FiniteElementDomination::this_element_dominates)
+                ||
+                (domination == FiniteElementDomination::either_element_can_dominate))
+              break;
+          }
+
+        // check that we have found one such subface
+        Assert (dominating_subface_no < face->n_children(),
+                ExcNotImplemented());
+
+        // return the finite element index used on it. note that only a
+        // single fe can be active on such subfaces
+        return face->child (dominating_subface_no)->nth_active_fe_index(0);
+      }
+
+
+
+      /**
+       * Copy constraints into a constraint matrix object.
+       *
+       * This function removes zero constraints and those, which constrain
+       * a DoF which was already eliminated in one of the previous steps of
+       * the hp hanging node procedure.
+       *
+       * It also suppresses very small entries in the constraint matrix to
+       * avoid making the sparsity pattern fuller than necessary.
+       */
+      void
+      filter_constraints (const std::vector<types::global_dof_index> &master_dofs,
+                          const std::vector<types::global_dof_index> &slave_dofs,
+                          const FullMatrix<double> &face_constraints,
+                          ConstraintMatrix &constraints)
+      {
+        Assert (face_constraints.n () == master_dofs.size (),
+                ExcDimensionMismatch(master_dofs.size (),
+                                     face_constraints.n()));
+        Assert (face_constraints.m () == slave_dofs.size (),
+                ExcDimensionMismatch(slave_dofs.size (),
+                                     face_constraints.m()));
+
+        const unsigned int n_master_dofs = master_dofs.size ();
+        const unsigned int n_slave_dofs = slave_dofs.size ();
+
+        // check for a couple conditions that happened in parallel
+        // distributed mode
+        for (unsigned int row=0; row!=n_slave_dofs; ++row)
+          Assert (slave_dofs[row] != numbers::invalid_dof_index,
+                  ExcInternalError());
+        for (unsigned int col=0; col!=n_master_dofs; ++col)
+          Assert (master_dofs[col] != numbers::invalid_dof_index,
+                  ExcInternalError());
+
+
+        for (unsigned int row=0; row!=n_slave_dofs; ++row)
+          if (constraints.is_constrained (slave_dofs[row]) == false)
+            {
+              bool constraint_already_satisfied = false;
+
+              // Check if we have an identity constraint, which is already
+              // satisfied by unification of the corresponding global dof
+              // indices
+              for (unsigned int i=0; i<n_master_dofs; ++i)
+                if (face_constraints (row,i) == 1.0)
+                  if (master_dofs[i] == slave_dofs[row])
+                    {
+                      constraint_already_satisfied = true;
+                      break;
+                    }
+
+              if (constraint_already_satisfied == false)
+                {
+                  // add up the absolute values of all constraints in this
+                  // line to get a measure of their absolute size
+                  double abs_sum = 0;
+                  for (unsigned int i=0; i<n_master_dofs; ++i)
+                    abs_sum += std::abs (face_constraints(row,i));
+
+                  // then enter those constraints that are larger than
+                  // 1e-14*abs_sum. everything else probably originated
+                  // from inexact inversion of matrices and similar
+                  // effects. having those constraints in here will only
+                  // lead to problems because it makes sparsity patterns
+                  // fuller than necessary without producing any
+                  // significant effect
+                  constraints.add_line (slave_dofs[row]);
+                  for (unsigned int i=0; i<n_master_dofs; ++i)
+                    if ((face_constraints(row,i) != 0)
+                        &&
+                        (std::fabs(face_constraints(row,i)) >= 1e-14*abs_sum))
+                      constraints.add_entry (slave_dofs[row],
+                                             master_dofs[i],
+                                             face_constraints (row,i));
+                  constraints.set_inhomogeneity (slave_dofs[row], 0.);
+                }
+            }
+      }
+
+    }
+
+
+
+    void
+    make_hp_hanging_node_constraints (const dealii::DoFHandler<1> &,
+                                      ConstraintMatrix &)
+    {
+      // nothing to do for regular dof handlers in 1d
+    }
+
+
+
+    void
+    make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1> &,
+                                            ConstraintMatrix &,
+                                            dealii::internal::int2type<1>)
+    {
+      // nothing to do for regular dof handlers in 1d
+    }
+
+
+    void
+    make_hp_hanging_node_constraints (const dealii::MGDoFHandler<1> &,
+                                      ConstraintMatrix &)
+    {
+      // nothing to do for regular dof handlers in 1d
+    }
+
+
+
+    void
+    make_oldstyle_hanging_node_constraints (const dealii::MGDoFHandler<1> &,
+                                            ConstraintMatrix &,
+                                            dealii::internal::int2type<1>)
+    {
+      // nothing to do for regular dof handlers in 1d
+    }
+
+
+    void
+    make_hp_hanging_node_constraints (const dealii::hp::DoFHandler<1> &/*dof_handler*/,
+                                      ConstraintMatrix        &/*constraints*/)
+    {
+      // we may have to compute constraints for vertices. gotta think about
+      // that a bit more
+
+      //TODO[WB]: think about what to do here...
+    }
+
+
+
+    void
+    make_oldstyle_hanging_node_constraints (const dealii::hp::DoFHandler<1> &/*dof_handler*/,
+                                            ConstraintMatrix        &/*constraints*/,
+                                            dealii::internal::int2type<1>)
+    {
+      // we may have to compute constraints for vertices. gotta think about
+      // that a bit more
+
+      //TODO[WB]: think about what to do here...
+    }
+
+
+    void
+    make_hp_hanging_node_constraints (const dealii::DoFHandler<1,2> &,
+                                      ConstraintMatrix &)
+    {
+      // nothing to do for regular dof handlers in 1d
+    }
+
+
+
+    void
+    make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1,2> &,
+                                            ConstraintMatrix &,
+                                            dealii::internal::int2type<1>)
+    {
+      // nothing to do for regular dof handlers in 1d
+    }
+
+
+    void
+    make_hp_hanging_node_constraints (const dealii::DoFHandler<1,3> &,
+                                      ConstraintMatrix &)
+    {
+      // nothing to do for regular dof handlers in 1d
+    }
+
+    void
+    make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1,3> &,
+                                            ConstraintMatrix &,
+                                            dealii::internal::int2type<1>)
+    {
+      // nothing to do for regular dof handlers in 1d
+    }
+
+
+//   currently not used but may be in the future:
+
+//     void
+//     make_hp_hanging_node_constraints (const dealii::MDoFHandler<1,2> &,
+//                                    ConstraintMatrix    &)
+//     {
+//                                     // nothing to do for regular
+//                                     // dof handlers in 1d
+//     }
+
+
+
+//     void
+//     make_oldstyle_hanging_node_constraints (const dealii::DoFHandler<1,2> &,
+//                                          ConstraintMatrix    &,
+//                                          dealii::internal::int2type<1>)
+//     {
+//                                     // nothing to do for regular
+//                                     // dof handlers in 1d
+//     }
+
+
+//     void
+//     make_oldstyle_hanging_node_constraints (const dealii::hp::DoFHandler<1,2> &/*dof_handler*/,
+//                                          ConstraintMatrix        &/*constraints*/,
+//                                          dealii::internal::int2type<1>)
+//     {
+//                                     // we may have to compute
+//                                     // constraints for
+//                                     // vertices. gotta think about
+//                                     // that a bit more
+//
+// //TODO[WB]: think about what to do here...
+//     }
+//#endif
+
+
+
+    template <class DH>
+    void
+    make_oldstyle_hanging_node_constraints (const DH         &dof_handler,
+                                            ConstraintMatrix &constraints,
+                                            dealii::internal::int2type<2>)
+    {
+      const unsigned int dim = 2;
+
+      const unsigned int spacedim = DH::space_dimension;
+
+      std::vector<types::global_dof_index> dofs_on_mother;
+      std::vector<types::global_dof_index> dofs_on_children;
+
+      // loop over all lines; only on lines there can be constraints. We do
+      // so by looping over all active cells and checking whether any of
+      // the faces are refined which can only be from the neighboring cell
+      // because this one is active. In that case, the face is subject to
+      // constraints
+      //
+      // note that even though we may visit a face twice if the neighboring
+      // cells are equally refined, we can only visit each face with
+      // hanging nodes once
+      typename DH::active_cell_iterator cell = dof_handler.begin_active(),
+                                        endc = dof_handler.end();
+      for (; cell!=endc; ++cell)
+        // artificial cells can at best neighbor ghost cells, but we're not
+        // interested in these interfaces
+        if (!cell->is_artificial ())
+          for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+            if (cell->face(face)->has_children())
+              {
+                // in any case, faces can have at most two active fe
+                // indices, but here the face can have only one (namely the
+                // same as that from the cell we're sitting on), and each
+                // of the children can have only one as well. check this
+                Assert (cell->face(face)->n_active_fe_indices() == 1,
+                        ExcInternalError());
+                Assert (cell->face(face)->fe_index_is_active(cell->active_fe_index())
+                        == true,
+                        ExcInternalError());
+                for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
+                  if (!cell->neighbor_child_on_subface(face,c)->is_artificial())
+                    Assert (cell->face(face)->child(c)->n_active_fe_indices() == 1,
+                            ExcInternalError());
+
+                // right now, all that is implemented is the case that both
+                // sides use the same fe
+                for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
+                  if (!cell->neighbor_child_on_subface(face,c)->is_artificial())
+                    Assert (cell->face(face)->child(c)
+                            ->fe_index_is_active(cell->active_fe_index()) == true,
+                            ExcNotImplemented());
+
+                // ok, start up the work
+                const FiniteElement<dim,spacedim> &fe       = cell->get_fe();
+                const unsigned int        fe_index = cell->active_fe_index();
+
+                const unsigned int
+                n_dofs_on_mother   = 2*fe.dofs_per_vertex + fe.dofs_per_line,
+                n_dofs_on_children = fe.dofs_per_vertex + 2*fe.dofs_per_line;
+
+                dofs_on_mother.resize (n_dofs_on_mother);
+                dofs_on_children.resize (n_dofs_on_children);
+
+                Assert(n_dofs_on_mother == fe.constraints().n(),
+                       ExcDimensionMismatch(n_dofs_on_mother,
+                                            fe.constraints().n()));
+                Assert(n_dofs_on_children == fe.constraints().m(),
+                       ExcDimensionMismatch(n_dofs_on_children,
+                                            fe.constraints().m()));
+
+                const typename DH::line_iterator this_face = cell->face(face);
+
+                // fill the dofs indices. Use same enumeration scheme as in
+                // @p{FiniteElement::constraints()}
+                unsigned int next_index = 0;
+                for (unsigned int vertex=0; vertex<2; ++vertex)
+                  for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
+                    dofs_on_mother[next_index++] = this_face->vertex_dof_index(vertex,dof,
+                                                                               fe_index);
+                for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
+                  dofs_on_mother[next_index++] = this_face->dof_index(dof, fe_index);
+                AssertDimension (next_index, dofs_on_mother.size());
+
+                next_index = 0;
+                for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
+                  dofs_on_children[next_index++]
+                    = this_face->child(0)->vertex_dof_index(1,dof,fe_index);
+                for (unsigned int child=0; child<2; ++child)
+                  for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
+                    dofs_on_children[next_index++]
+                      = this_face->child(child)->dof_index(dof, fe_index);
+                AssertDimension (next_index, dofs_on_children.size());
+
+                // for each row in the constraint matrix for this line:
+                for (unsigned int row=0; row!=dofs_on_children.size(); ++row)
+                  {
+                    constraints.add_line (dofs_on_children[row]);
+                    for (unsigned int i=0; i!=dofs_on_mother.size(); ++i)
+                      constraints.add_entry (dofs_on_children[row],
+                                             dofs_on_mother[i],
+                                             fe.constraints()(row,i));
+
+                    constraints.set_inhomogeneity (dofs_on_children[row], 0.);
+                  }
+              }
+            else
+              {
+                // this face has no children, but it could still be that it
+                // is shared by two cells that use a different fe index.
+                // check a couple of things, but ignore the case that the
+                // neighbor is an artificial cell
+                if (!cell->at_boundary(face) &&
+                    !cell->neighbor(face)->is_artificial())
+                  {
+                    Assert (cell->face(face)->n_active_fe_indices() == 1,
+                            ExcNotImplemented());
+                    Assert (cell->face(face)
+                            ->fe_index_is_active(cell->active_fe_index()) == true,
+                            ExcInternalError());
+                  }
+              }
+    }
+
+
+
+    template <class DH>
+    void
+    make_oldstyle_hanging_node_constraints (const DH         &dof_handler,
+                                            ConstraintMatrix &constraints,
+                                            dealii::internal::int2type<3>)
+    {
+      const unsigned int dim = 3;
+
+      std::vector<types::global_dof_index> dofs_on_mother;
+      std::vector<types::global_dof_index> dofs_on_children;
+
+      // loop over all quads; only on quads there can be constraints. We do
+      // so by looping over all active cells and checking whether any of
+      // the faces are refined which can only be from the neighboring cell
+      // because this one is active. In that case, the face is subject to
+      // constraints
+      //
+      // note that even though we may visit a face twice if the neighboring
+      // cells are equally refined, we can only visit each face with
+      // hanging nodes once
+      typename DH::active_cell_iterator cell = dof_handler.begin_active(),
+                                        endc = dof_handler.end();
+      for (; cell!=endc; ++cell)
+        // artificial cells can at best neighbor ghost cells, but we're not
+        // interested in these interfaces
+        if (!cell->is_artificial ())
+          for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+            if (cell->face(face)->has_children())
+              {
+                // first of all, make sure that we treat a case which is
+                // possible, i.e. either no dofs on the face at all or no
+                // anisotropic refinement
+                if (cell->get_fe().dofs_per_face == 0)
+                  continue;
+
+                Assert(cell->face(face)->refinement_case()==RefinementCase<dim-1>::isotropic_refinement,
+                       ExcNotImplemented());
+
+                // in any case, faces can have at most two active fe
+                // indices, but here the face can have only one (namely the
+                // same as that from the cell we're sitting on), and each
+                // of the children can have only one as well. check this
+                AssertDimension (cell->face(face)->n_active_fe_indices(), 1);
+                Assert (cell->face(face)->fe_index_is_active(cell->active_fe_index())
+                        == true,
+                        ExcInternalError());
+                for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
+                  AssertDimension (cell->face(face)->child(c)->n_active_fe_indices(), 1);
+
+                // right now, all that is implemented is the case that both
+                // sides use the same fe, and not only that but also that
+                // all lines bounding this face and the children have the
+                // same fe
+                for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
+                  if (!cell->neighbor_child_on_subface(face,c)->is_artificial())
+                    {
+                      Assert (cell->face(face)->child(c)
+                              ->fe_index_is_active(cell->active_fe_index()) == true,
+                              ExcNotImplemented());
+                      for (unsigned int e=0; e<4; ++e)
+                        {
+                          Assert (cell->face(face)->child(c)->line(e)
+                                  ->n_active_fe_indices() == 1,
+                                  ExcNotImplemented());
+                          Assert (cell->face(face)->child(c)->line(e)
+                                  ->fe_index_is_active(cell->active_fe_index()) == true,
+                                  ExcNotImplemented());
+                        }
+                    }
+                for (unsigned int e=0; e<4; ++e)
+                  {
+                    Assert (cell->face(face)->line(e)
+                            ->n_active_fe_indices() == 1,
+                            ExcNotImplemented());
+                    Assert (cell->face(face)->line(e)
+                            ->fe_index_is_active(cell->active_fe_index()) == true,
+                            ExcNotImplemented());
+                  }
+
+                // ok, start up the work
+                const FiniteElement<dim> &fe       = cell->get_fe();
+                const unsigned int        fe_index = cell->active_fe_index();
+
+                const unsigned int n_dofs_on_mother = fe.dofs_per_face;
+                const unsigned int n_dofs_on_children = (5*fe.dofs_per_vertex+
+                                                         12*fe.dofs_per_line+
+                                                         4*fe.dofs_per_quad);
+
+                //TODO[TL]: think about this and the following in case of anisotropic refinement
+
+                dofs_on_mother.resize (n_dofs_on_mother);
+                dofs_on_children.resize (n_dofs_on_children);
+
+                Assert(n_dofs_on_mother == fe.constraints().n(),
+                       ExcDimensionMismatch(n_dofs_on_mother,
+                                            fe.constraints().n()));
+                Assert(n_dofs_on_children == fe.constraints().m(),
+                       ExcDimensionMismatch(n_dofs_on_children,
+                                            fe.constraints().m()));
+
+                const typename DH::face_iterator this_face = cell->face(face);
+
+                // fill the dofs indices. Use same enumeration scheme as in
+                // @p{FiniteElement::constraints()}
+                unsigned int next_index = 0;
+                for (unsigned int vertex=0; vertex<4; ++vertex)
+                  for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
+                    dofs_on_mother[next_index++] = this_face->vertex_dof_index(vertex,dof,
+                                                                               fe_index);
+                for (unsigned int line=0; line<4; ++line)
+                  for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
+                    dofs_on_mother[next_index++]
+                      = this_face->line(line)->dof_index(dof, fe_index);
+                for (unsigned int dof=0; dof!=fe.dofs_per_quad; ++dof)
+                  dofs_on_mother[next_index++] = this_face->dof_index(dof, fe_index);
+                AssertDimension (next_index, dofs_on_mother.size());
+
+                next_index = 0;
+
+                // assert some consistency assumptions
+
+                //TODO[TL]: think about this in case of anisotropic
+                //refinement
+
+                Assert (dof_handler.get_tria().get_anisotropic_refinement_flag() ||
+                        ((this_face->child(0)->vertex_index(3) ==
+                          this_face->child(1)->vertex_index(2)) &&
+                         (this_face->child(0)->vertex_index(3) ==
+                          this_face->child(2)->vertex_index(1)) &&
+                         (this_face->child(0)->vertex_index(3) ==
+                          this_face->child(3)->vertex_index(0))),
+                        ExcInternalError());
+                for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
+                  dofs_on_children[next_index++]
+                    = this_face->child(0)->vertex_dof_index(3,dof);
+
+                // dof numbers on the centers of the lines bounding this
+                // face
+                for (unsigned int line=0; line<4; ++line)
+                  for (unsigned int dof=0; dof!=fe.dofs_per_vertex; ++dof)
+                    dofs_on_children[next_index++]
+                      = this_face->line(line)->child(0)->vertex_dof_index(1,dof, fe_index);
+
+                // next the dofs on the lines interior to the face; the
+                // order of these lines is laid down in the FiniteElement
+                // class documentation
+                for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
+                  dofs_on_children[next_index++]
+                    = this_face->child(0)->line(1)->dof_index(dof, fe_index);
+                for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
+                  dofs_on_children[next_index++]
+                    = this_face->child(2)->line(1)->dof_index(dof, fe_index);
+                for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
+                  dofs_on_children[next_index++]
+                    = this_face->child(0)->line(3)->dof_index(dof, fe_index);
+                for (unsigned int dof=0; dof<fe.dofs_per_line; ++dof)
+                  dofs_on_children[next_index++]
+                    = this_face->child(1)->line(3)->dof_index(dof, fe_index);
+
+                // dofs on the bordering lines
+                for (unsigned int line=0; line<4; ++line)
+                  for (unsigned int child=0; child<2; ++child)
+                    for (unsigned int dof=0; dof!=fe.dofs_per_line; ++dof)
+                      dofs_on_children[next_index++]
+                        = this_face->line(line)->child(child)->dof_index(dof, fe_index);
+
+                // finally, for the dofs interior to the four child faces
+                for (unsigned int child=0; child<4; ++child)
+                  for (unsigned int dof=0; dof!=fe.dofs_per_quad; ++dof)
+                    dofs_on_children[next_index++]
+                      = this_face->child(child)->dof_index(dof, fe_index);
+                AssertDimension (next_index, dofs_on_children.size());
+
+                // for each row in the constraint matrix for this line:
+                for (unsigned int row=0; row!=dofs_on_children.size(); ++row)
+                  {
+                    constraints.add_line (dofs_on_children[row]);
+                    for (unsigned int i=0; i!=dofs_on_mother.size(); ++i)
+                      constraints.add_entry (dofs_on_children[row],
+                                             dofs_on_mother[i],
+                                             fe.constraints()(row,i));
+
+                    constraints.set_inhomogeneity(dofs_on_children[row], 0.);
+                  }
+              }
+            else
+              {
+                // this face has no children, but it could still be that it
+                // is shared by two cells that use a different fe index.
+                // check a couple of things, but ignore the case that the
+                // neighbor is an artificial cell
+                if (!cell->at_boundary(face) &&
+                    !cell->neighbor(face)->is_artificial())
+                  {
+                    Assert (cell->face(face)->n_active_fe_indices() == 1,
+                            ExcNotImplemented());
+                    Assert (cell->face(face)
+                            ->fe_index_is_active(cell->active_fe_index()) == true,
+                            ExcInternalError());
+                  }
+              }
+    }
+
+
+    template <class DH>
+    void
+    make_hp_hanging_node_constraints (const DH         &dof_handler,
+                                      ConstraintMatrix &constraints)
+    {
+      // note: this function is going to be hard to understand if you
+      // haven't read the hp paper. however, we try to follow the notation
+      // laid out there, so go read the paper before you try to understand
+      // what is going on here
+
+      const unsigned int dim = DH::dimension;
+
+      const unsigned int spacedim = DH::space_dimension;
+
+
+      // a matrix to be used for constraints below. declared here and
+      // simply resized down below to avoid permanent re-allocation of
+      // memory
+      FullMatrix<double> constraint_matrix;
+
+      // similarly have arrays that will hold master and slave dof numbers,
+      // as well as a scratch array needed for the complicated case below
+      std::vector<types::global_dof_index> master_dofs;
+      std::vector<types::global_dof_index> slave_dofs;
+      std::vector<types::global_dof_index> scratch_dofs;
+
+      // caches for the face and subface interpolation matrices between
+      // different (or the same) finite elements. we compute them only
+      // once, namely the first time they are needed, and then just reuse
+      // them
+      Table<2,std_cxx1x::shared_ptr<FullMatrix<double> > >
+      face_interpolation_matrices (n_finite_elements (dof_handler),
+                                   n_finite_elements (dof_handler));
+      Table<3,std_cxx1x::shared_ptr<FullMatrix<double> > >
+      subface_interpolation_matrices (n_finite_elements (dof_handler),
+                                      n_finite_elements (dof_handler),
+                                      GeometryInfo<dim>::max_children_per_face);
+
+      // similarly have a cache for the matrices that are split into their
+      // master and slave parts, and for which the master part is inverted.
+      // these two matrices are derived from the face interpolation matrix
+      // as described in the @ref hp_paper "hp paper"
+      Table<2,std_cxx1x::shared_ptr<std::pair<FullMatrix<double>,FullMatrix<double> > > >
+      split_face_interpolation_matrices (n_finite_elements (dof_handler),
+                                         n_finite_elements (dof_handler));
+
+      // finally, for each pair of finite elements, have a mask that states
+      // which of the degrees of freedom on the coarse side of a refined
+      // face will act as master dofs.
+      Table<2,std_cxx1x::shared_ptr<std::vector<bool> > >
+      master_dof_masks (n_finite_elements (dof_handler),
+                        n_finite_elements (dof_handler));
+
+      // loop over all faces
+      //
+      // note that even though we may visit a face twice if the neighboring
+      // cells are equally refined, we can only visit each face with
+      // hanging nodes once
+      typename DH::active_cell_iterator cell = dof_handler.begin_active(),
+                                        endc = dof_handler.end();
+      for (; cell!=endc; ++cell)
+        // artificial cells can at best neighbor ghost cells, but we're not
+        // interested in these interfaces
+        if (!cell->is_artificial ())
+          for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+            if (cell->face(face)->has_children())
+              {
+                // first of all, make sure that we treat a case which is
+                // possible, i.e. either no dofs on the face at all or no
+                // anisotropic refinement
+                if (cell->get_fe().dofs_per_face == 0)
+                  continue;
+
+                Assert(cell->face(face)->refinement_case()==RefinementCase<dim-1>::isotropic_refinement,
+                       ExcNotImplemented());
+
+                // so now we've found a face of an active cell that has
+                // children. that means that there are hanging nodes here.
+
+                // in any case, faces can have at most two sets of active
+                // fe indices, but here the face can have only one (namely
+                // the same as that from the cell we're sitting on), and
+                // each of the children can have only one as well. check
+                // this
+                Assert (cell->face(face)->n_active_fe_indices() == 1,
+                        ExcInternalError());
+                Assert (cell->face(face)->fe_index_is_active(cell->active_fe_index())
+                        == true,
+                        ExcInternalError());
+                for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
+                  Assert (cell->face(face)->child(c)->n_active_fe_indices() == 1,
+                          ExcInternalError());
+
+                // first find out whether we can constrain each of the
+                // subfaces to the mother face. in the lingo of the hp
+                // paper, this would be the simple case. note that we can
+                // short-circuit this decision if the dof_handler doesn't
+                // support hp at all
+                //
+                // ignore all interfaces with artificial cells
+                FiniteElementDomination::Domination
+                mother_face_dominates = FiniteElementDomination::either_element_can_dominate;
+
+                if (DoFHandlerSupportsDifferentFEs<DH>::value == true)
+                  for (unsigned int c=0; c<cell->face(face)->number_of_children(); ++c)
+                    if (!cell->neighbor_child_on_subface (face, c)->is_artificial())
+                      mother_face_dominates = mother_face_dominates &
+                                              (cell->get_fe().compare_for_face_domination
+                                               (cell->neighbor_child_on_subface (face, c)->get_fe()));
+
+                switch (mother_face_dominates)
+                  {
+                  case FiniteElementDomination::this_element_dominates:
+                  case FiniteElementDomination::either_element_can_dominate:
+                  {
+                    // Case 1 (the simple case and the only case that can
+                    // happen for non-hp DoFHandlers): The coarse element
+                    // dominates the elements on the subfaces (or they are
+                    // all the same)
+                    //
+                    // so we are going to constrain the DoFs on the face
+                    // children against the DoFs on the face itself
+                    master_dofs.resize (cell->get_fe().dofs_per_face);
+
+                    cell->face(face)->get_dof_indices (master_dofs,
+                                                       cell->active_fe_index ());
+
+                    // Now create constraint matrix for the subfaces and
+                    // assemble it. ignore all interfaces with artificial
+                    // cells because we can only get to such interfaces if
+                    // the current cell is a ghost cell
+                    for (unsigned int c=0; c<cell->face(face)->n_children(); ++c)
+                      {
+                        if (cell->neighbor_child_on_subface (face, c)->is_artificial())
+                          continue;
+
+                        const typename DH::active_face_iterator
+                        subface = cell->face(face)->child(c);
+
+                        Assert (subface->n_active_fe_indices() == 1,
+                                ExcInternalError());
+
+                        const unsigned int
+                        subface_fe_index = subface->nth_active_fe_index(0);
+
+                        // we sometime run into the situation where for
+                        // example on one big cell we have a FE_Q(1) and on
+                        // the subfaces we have a mixture of FE_Q(1) and
+                        // FE_Nothing. In that case, the face domination is
+                        // either_element_can_dominate for the whole
+                        // collection of subfaces, but on the particular
+                        // subface between FE_Q(1) and FE_Nothing, there
+                        // are no constraints that we need to take care of.
+                        // in that case, just continue
+                        if (cell->get_fe().compare_for_face_domination
+                            (subface->get_fe(subface_fe_index))
+                            ==
+                            FiniteElementDomination::no_requirements)
+                          continue;
+
+                        // Same procedure as for the mother cell. Extract
+                        // the face DoFs from the cell DoFs.
+                        slave_dofs.resize (subface->get_fe(subface_fe_index)
+                                           .dofs_per_face);
+                        subface->get_dof_indices (slave_dofs, subface_fe_index);
+
+                        for (unsigned int i=0; i<slave_dofs.size(); ++i)
+                          Assert (slave_dofs[i] != numbers::invalid_dof_index,
+                                  ExcInternalError());
+
+                        // Now create the element constraint for this
+                        // subface.
+                        //
+                        // As a side remark, one may wonder the following:
+                        // neighbor_child is clearly computed correctly,
+                        // i.e. taking into account face_orientation (just
+                        // look at the implementation of that function).
+                        // however, we don't care about this here, when we
+                        // ask for subface_interpolation on subface c. the
+                        // question rather is: do we have to translate 'c'
+                        // here as well?
+                        //
+                        // the answer is in fact 'no'. if one does that,
+                        // results are wrong: constraints are added twice
+                        // for the same pair of nodes but with differing
+                        // weights. in addition, one can look at the
+                        // deal.II/project_*_03 tests that look at exactly
+                        // this case: there, we have a mesh with at least
+                        // one face_orientation==false and hanging nodes,
+                        // and the results of those tests show that the
+                        // result of projection verifies the approximation
+                        // properties of a finite element onto that mesh
+                        ensure_existence_of_subface_matrix
+                        (cell->get_fe(),
+                         subface->get_fe(subface_fe_index),
+                         c,
+                         subface_interpolation_matrices
+                         [cell->active_fe_index()][subface_fe_index][c]);
+
+                        // Add constraints to global constraint matrix.
+                        filter_constraints (master_dofs,
+                                            slave_dofs,
+                                            *(subface_interpolation_matrices
+                                              [cell->active_fe_index()][subface_fe_index][c]),
+                                            constraints);
+                      }
+
+                    break;
+                  }
+
+                  case FiniteElementDomination::other_element_dominates:
+                  case FiniteElementDomination::neither_element_dominates:
+                  {
+                    // Case 2 (the "complex" case): at least one (the
+                    // neither_... case) of the finer elements or all of
+                    // them (the other_... case) is dominating. See the hp
+                    // paper for a way how to deal with this situation
+                    //
+                    // since this is something that can only happen for hp
+                    // dof handlers, add a check here...
+                    Assert (DoFHandlerSupportsDifferentFEs<DH>::value == true,
+                            ExcInternalError());
+
+                    // we first have to find the finite element that is
+                    // able to generate a space that all the other ones can
+                    // be constrained to
+                    const unsigned int dominating_fe_index
+                      = get_most_dominating_subface_fe_index (cell->face(face));
+
+                    const FiniteElement<dim,spacedim> &dominating_fe
+                      = dof_handler.get_fe()[dominating_fe_index];
+
+                    // check also that it is able to constrain the mother
+                    // face. it should be, or we wouldn't have gotten into
+                    // the branch for the 'complex' case
+                    Assert ((dominating_fe.compare_for_face_domination
+                             (cell->face(face)->get_fe(cell->face(face)->nth_active_fe_index(0)))
+                             == FiniteElementDomination::this_element_dominates)
+                            ||
+                            (dominating_fe.compare_for_face_domination
+                             (cell->face(face)->get_fe(cell->face(face)->nth_active_fe_index(0)))
+                             == FiniteElementDomination::either_element_can_dominate),
+                            ExcInternalError());
+
+
+                    // first get the interpolation matrix from the mother
+                    // to the virtual dofs
+                    Assert (dominating_fe.dofs_per_face <=
+                            cell->get_fe().dofs_per_face,
+                            ExcInternalError());
+
+                    ensure_existence_of_face_matrix
+                    (dominating_fe,
+                     cell->get_fe(),
+                     face_interpolation_matrices
+                     [dominating_fe_index][cell->active_fe_index()]);
+
+                    // split this matrix into master and slave components.
+                    // invert the master component
+                    ensure_existence_of_master_dof_mask
+                    (cell->get_fe(),
+                     dominating_fe,
+                     (*face_interpolation_matrices
+                      [dominating_fe_index]
+                      [cell->active_fe_index()]),
+                     master_dof_masks
+                     [dominating_fe_index]
+                     [cell->active_fe_index()]);
+
+                    ensure_existence_of_split_face_matrix
+                    (*face_interpolation_matrices
+                     [dominating_fe_index][cell->active_fe_index()],
+                     (*master_dof_masks
+                      [dominating_fe_index][cell->active_fe_index()]),
+                     split_face_interpolation_matrices
+                     [dominating_fe_index][cell->active_fe_index()]);
+
+                    const FullMatrix<double> &restrict_mother_to_virtual_master_inv
+                      = (split_face_interpolation_matrices
+                         [dominating_fe_index][cell->active_fe_index()]->first);
+
+                    const FullMatrix<double> &restrict_mother_to_virtual_slave
+                      = (split_face_interpolation_matrices
+                         [dominating_fe_index][cell->active_fe_index()]->second);
+
+                    // now compute the constraint matrix as the product
+                    // between the inverse matrix and the slave part
+                    constraint_matrix.reinit (cell->get_fe().dofs_per_face -
+                                              dominating_fe.dofs_per_face,
+                                              dominating_fe.dofs_per_face);
+                    restrict_mother_to_virtual_slave
+                    .mmult (constraint_matrix,
+                            restrict_mother_to_virtual_master_inv);
+
+                    // then figure out the global numbers of master and
+                    // slave dofs and apply constraints
+                    scratch_dofs.resize (cell->get_fe().dofs_per_face);
+                    cell->face(face)->get_dof_indices (scratch_dofs,
+                                                       cell->active_fe_index ());
+
+                    // split dofs into master and slave components
+                    master_dofs.clear ();
+                    slave_dofs.clear ();
+                    for (unsigned int i=0; i<cell->get_fe().dofs_per_face; ++i)
+                      if ((*master_dof_masks
+                           [dominating_fe_index][cell->active_fe_index()])[i] == true)
+                        master_dofs.push_back (scratch_dofs[i]);
+                      else
+                        slave_dofs.push_back (scratch_dofs[i]);
+
+                    AssertDimension (master_dofs.size(), dominating_fe.dofs_per_face);
+                    AssertDimension (slave_dofs.size(),
+                                     cell->get_fe().dofs_per_face - dominating_fe.dofs_per_face);
+
+                    filter_constraints (master_dofs,
+                                        slave_dofs,
+                                        constraint_matrix,
+                                        constraints);
+
+
+
+                    // next we have to deal with the subfaces. do as
+                    // discussed in the hp paper
+                    for (unsigned int sf=0;
+                         sf<cell->face(face)->n_children(); ++sf)
+                      {
+                        // ignore interfaces with artificial cells as well
+                        // as interfaces between ghost cells in 2d
+                        if (cell->neighbor_child_on_subface (face, sf)->is_artificial()
+                            ||
+                            (dim==2 && cell->is_ghost()
+                             &&
+                             cell->neighbor_child_on_subface (face, sf)->is_ghost()))
+                          continue;
+
+                        Assert (cell->face(face)->child(sf)
+                                ->n_active_fe_indices() == 1,
+                                ExcInternalError());
+
+                        const unsigned int subface_fe_index
+                          = cell->face(face)->child(sf)->nth_active_fe_index(0);
+                        const FiniteElement<dim,spacedim> &subface_fe
+                          = dof_handler.get_fe()[subface_fe_index];
+
+                        // first get the interpolation matrix from the
+                        // subface to the virtual dofs
+                        Assert (dominating_fe.dofs_per_face <=
+                                subface_fe.dofs_per_face,
+                                ExcInternalError());
+                        ensure_existence_of_subface_matrix
+                        (dominating_fe,
+                         subface_fe,
+                         sf,
+                         subface_interpolation_matrices
+                         [dominating_fe_index][subface_fe_index][sf]);
+
+                        const FullMatrix<double> &restrict_subface_to_virtual
+                          = *(subface_interpolation_matrices
+                              [dominating_fe_index][subface_fe_index][sf]);
+
+                        constraint_matrix.reinit (subface_fe.dofs_per_face,
+                                                  dominating_fe.dofs_per_face);
+
+                        restrict_subface_to_virtual
+                        .mmult (constraint_matrix,
+                                restrict_mother_to_virtual_master_inv);
+
+                        slave_dofs.resize (subface_fe.dofs_per_face);
+                        cell->face(face)->child(sf)->get_dof_indices (slave_dofs,
+                                                                      subface_fe_index);
+
+                        filter_constraints (master_dofs,
+                                            slave_dofs,
+                                            constraint_matrix,
+                                            constraints);
+                      }
+
+                    break;
+                  }
+
+                  case FiniteElementDomination::no_requirements:
+                    // there are no continuity requirements between the two
+                    // elements. record no constraints
+                    break;
+
+                  default:
+                    // we shouldn't get here
+                    Assert (false, ExcInternalError());
+                  }
+              }
+            else
+              {
+                // this face has no children, but it could still be that it
+                // is shared by two cells that use a different fe index
+                Assert (cell->face(face)
+                        ->fe_index_is_active(cell->active_fe_index()) == true,
+                        ExcInternalError());
+
+                // see if there is a neighbor that is an artificial cell.
+                // in that case, we're not interested in this interface. we
+                // test this case first since artificial cells may not have
+                // an active_fe_index set, etc
+                if (!cell->at_boundary(face)
+                    &&
+                    cell->neighbor(face)->is_artificial())
+                  continue;
+
+                // Only if there is a neighbor with a different
+                // active_fe_index and the same h-level, some action has to
+                // be taken.
+                if ((DoFHandlerSupportsDifferentFEs<DH>::value == true)
+                    &&
+                    !cell->face(face)->at_boundary ()
+                    &&
+                    (cell->neighbor(face)->active_fe_index () !=
+                     cell->active_fe_index ())
+                    &&
+                    (!cell->face(face)->has_children() &&
+                     !cell->neighbor_is_coarser(face) ))
+                  {
+                    const typename DH::level_cell_iterator neighbor = cell->neighbor (face);
+
+                    // see which side of the face we have to constrain
+                    switch (cell->get_fe().compare_for_face_domination (neighbor->get_fe ()))
+                      {
+                      case FiniteElementDomination::this_element_dominates:
+                      {
+                        // Get DoFs on dominating and dominated side of the
+                        // face
+                        master_dofs.resize (cell->get_fe().dofs_per_face);
+                        cell->face(face)->get_dof_indices (master_dofs,
+                                                           cell->active_fe_index ());
+
+                        slave_dofs.resize (neighbor->get_fe().dofs_per_face);
+                        cell->face(face)->get_dof_indices (slave_dofs,
+                                                           neighbor->active_fe_index ());
+
+                        // break if the n_master_dofs == 0, because we are
+                        // attempting to constrain to an element that has
+                        // no face dofs
+                        if (master_dofs.size() == 0) break;
+
+                        // make sure the element constraints for this face
+                        // are available
+                        ensure_existence_of_face_matrix
+                        (cell->get_fe(),
+                         neighbor->get_fe(),
+                         face_interpolation_matrices
+                         [cell->active_fe_index()][neighbor->active_fe_index()]);
+
+                        // Add constraints to global constraint matrix.
+                        filter_constraints (master_dofs,
+                                            slave_dofs,
+                                            *(face_interpolation_matrices
+                                              [cell->active_fe_index()]
+                                              [neighbor->active_fe_index()]),
+                                            constraints);
+
+                        break;
+                      }
+
+                      case FiniteElementDomination::other_element_dominates:
+                      {
+                        // we don't do anything here since we will come
+                        // back to this face from the other cell, at which
+                        // time we will fall into the first case clause
+                        // above
+                        break;
+                      }
+
+                      case FiniteElementDomination::either_element_can_dominate:
+                      {
+                        // it appears as if neither element has any
+                        // constraints on its neighbor. this may be because
+                        // neither element has any DoFs on faces at all. or
+                        // that the two elements are actually the same,
+                        // although they happen to run under different
+                        // fe_indices (this is what happens in
+                        // hp/hp_hanging_nodes_01 for example).
+                        //
+                        // another possibility is what happens in crash_13.
+                        // there, we have FESystem(FE_Q(1),FE_DGQ(0)) vs.
+                        // FESystem(FE_Q(1),FE_DGQ(1)). neither of them
+                        // dominates the other.
+                       //
+                       // a final possibility is that we have something like
+                       // FESystem(FE_Q(1),FE_Q(1)) vs
+                       // FESystem(FE_Q(1),FE_Nothing()), see
+                       // hp/fe_nothing_18/19.
+                       //
+                       // in any case, the point is that it doesn't
+                        // matter. there is nothing to do here.
+                        break;
+                      }
+
+                      case FiniteElementDomination::neither_element_dominates:
+                      {
+                        // we don't presently know what exactly to do here.
+                        // it isn't quite clear what exactly we would have
+                        // to do here. sit tight until someone trips over
+                        // the following statement and see what exactly is
+                        // going on
+                        Assert (false, ExcNotImplemented());
+                        break;
+                      }
+
+                      case FiniteElementDomination::no_requirements:
+                      {
+                        // nothing to do here
+                        break;
+                      }
+
+                      default:
+                        // we shouldn't get here
+                        Assert (false, ExcInternalError());
+                      }
+                  }
+              }
+    }
+  }
+
+
+
+
+  template <class DH>
+  void
+  make_hanging_node_constraints (const DH &dof_handler,
+                                 ConstraintMatrix &constraints)
+  {
+    // Decide whether to use the new or old make_hanging_node_constraints
+    // function. If all the FiniteElement or all elements in a FECollection
+    // support the new face constraint matrix, the new code will be used.
+    // Otherwise, the old implementation is used for the moment.
+    if (dof_handler.get_fe().hp_constraints_are_implemented ())
+      internal::
+      make_hp_hanging_node_constraints (dof_handler,
+                                        constraints);
+    else
+      internal::
+      make_oldstyle_hanging_node_constraints (dof_handler,
+                                              constraints,
+                                              dealii::internal::int2type<DH::dimension>());
+  }
+
+
+
+  namespace
+  {
+    // enter constraints for periodicity into the given ConstraintMatrix object.
+    // this function is called when at least one of the two face iterators corresponds
+    // to an active object without further children
+    //
+    // @param transformation A matrix that maps degrees of freedom from one face
+    // to another. If the DoFs on the two faces are supposed to match exactly, then
+    // the matrix so provided will be the identity matrix. if face 2 is once refined
+    // from face 1, then the matrix needs to be the interpolation matrix from a face
+    // to this particular child
+    //
+    // @precondition: face_1 is supposed to be active
+    //
+    // @note As bug #82 ((http://code.google.com/p/dealii/issues/detail?id=82) and the
+    // corresponding testcase bits/periodicity_05 demonstrate, we can occasionally
+    // get into trouble if we already have the constraint x1=x2 and want to insert
+    // x2=x1. we avoid this by skipping an identity constraint if the opposite
+    // constraint already exists
+    template <typename FaceIterator>
+    void
+    set_periodicity_constraints (const FaceIterator                          &face_1,
+                                 const typename identity<FaceIterator>::type &face_2,
+                                 const FullMatrix<double>                    &transformation,
+                                 dealii::ConstraintMatrix                    &constraint_matrix,
+                                 const ComponentMask                         &component_mask,
+                                 const bool                                   face_orientation,
+                                 const bool                                   face_flip,
+                                 const bool                                   face_rotation)
+    {
+      static const int dim      = FaceIterator::AccessorType::dimension;
+      static const int spacedim = FaceIterator::AccessorType::space_dimension;
+
+      // we should be in the case where face_1 is active, i.e. has no children:
+      Assert (!face_1->has_children(),
+              ExcInternalError());
+
+      Assert (face_1->n_active_fe_indices() == 1,
+              ExcInternalError());
+
+      // if face_2 does have children, then we need to iterate over them
+      if (face_2->has_children())
+        {
+          Assert (face_2->n_children() == GeometryInfo<dim>::max_children_per_face,
+                  ExcNotImplemented());
+          const unsigned int dofs_per_face
+            = face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face;
+          FullMatrix<double> child_transformation (dofs_per_face, dofs_per_face);
+          FullMatrix<double> subface_interpolation (dofs_per_face, dofs_per_face);
+          for (unsigned int c=0; c<face_2->n_children(); ++c)
+            {
+              // get the interpolation matrix recursively from the one that
+              // interpolated from face_1 to face_2 by multiplying from the
+              // left with the one that interpolates from face_2 to
+              // its child
+              face_1->get_fe(face_1->nth_active_fe_index(0))
+              .get_subface_interpolation_matrix (face_1->get_fe(face_1->nth_active_fe_index(0)),
+                                                 c,
+                                                 subface_interpolation);
+              subface_interpolation.mmult (child_transformation, transformation);
+              set_periodicity_constraints(face_1, face_2->child(c),
+                                          child_transformation,
+                                          constraint_matrix, component_mask,
+                                          face_orientation, face_flip, face_rotation);
+            }
+        }
+      else
+        // both faces are active. we need to match the corresponding DoFs of both faces
+        {
+          const unsigned int face_1_index = face_1->nth_active_fe_index(0);
+          const unsigned int face_2_index = face_2->nth_active_fe_index(0);
+          Assert(face_1->get_fe(face_1_index) == face_2->get_fe(face_1_index),
+                 ExcMessage ("Matching periodic cells need to use the same finite element"));
+
+          const FiniteElement<dim, spacedim> &fe = face_1->get_fe(face_1_index);
+
+          Assert(component_mask.represents_n_components(fe.n_components()),
+                 ExcMessage ("The number of components in the mask has to be either "
+                             "zero or equal to the number of components in the finite " "element."));
+
+          const unsigned int dofs_per_face = fe.dofs_per_face;
+
+          std::vector<types::global_dof_index> dofs_1(dofs_per_face);
+          std::vector<types::global_dof_index> dofs_2(dofs_per_face);
+
+          face_1->get_dof_indices(dofs_1, face_1_index);
+          face_2->get_dof_indices(dofs_2, face_2_index);
+
+          // Well, this is a hack:
+          //
+          // There is no
+          //   face_to_face_index(face_index,
+          //                      face_orientation,
+          //                      face_flip,
+          //                      face_rotation)
+          // function in FiniteElementData, so we have to use
+          //   face_to_cell_index(face_index, face
+          //                      face_orientation,
+          //                      face_flip,
+          //                      face_rotation)
+          // But this will give us an index on a cell - something we cannot work
+          // with directly. But luckily we can match them back :-]
+
+          std::map<unsigned int, unsigned int> cell_to_rotated_face_index;
+
+          // Build up a cell to face index for face_2:
+          for (unsigned int i = 0; i < dofs_per_face; ++i)
+            {
+              const unsigned int cell_index = fe.face_to_cell_index(i, 0, /* It doesn't really matter, just assume
+                                                                           * we're on the first face...
+                                                                           */
+                                                                    true, false, false // default orientation
+                                                                   );
+              cell_to_rotated_face_index[cell_index] = i;
+            }
+
+          // loop over all dofs on face 2 and constrain them again the ones on face 1
+          for (unsigned int i=0; i<dofs_per_face; ++i)
+            if (!constraint_matrix.is_constrained(dofs_2[i]))
+              if ((component_mask.n_selected_components(fe.n_components())
+                   == fe.n_components())
+                  ||
+                  component_mask[fe.face_system_to_component_index(i).first])
+                {
+                  // as mentioned in the comment above this function, we need
+                  // to be careful about treating identity constraints differently.
+                  // consequently, find out whether this dof 'i' will be
+                  // identity constrained
+                  //
+                  // to check whether this is the case, first see whether there are
+                  // any weights other than 0 and 1, then in a first stage make sure
+                  // that if so there is only one weight equal to 1
+                  bool is_identity_constrained = true;
+                  for (unsigned int jj=0; jj<dofs_per_face; ++jj)
+                    if (((transformation(i,jj) == 0) || (transformation(i,jj) == 1)) == false)
+                      {
+                        is_identity_constrained = false;
+                        break;
+                      }
+                  unsigned int identity_constraint_target = numbers::invalid_unsigned_int;
+                  if (is_identity_constrained == true)
+                    {
+                      bool one_identity_found = false;
+                      for (unsigned int jj=0; jj<dofs_per_face; ++jj)
+                        if (transformation(i,jj) == 1)
+                          {
+                            if (one_identity_found == false)
+                              {
+                                one_identity_found = true;
+                                identity_constraint_target = jj;
+                              }
+                            else
+                              {
+                                is_identity_constrained = false;
+                                identity_constraint_target = numbers::invalid_unsigned_int;
+                                break;
+                              }
+                          }
+                    }
+
+                  // now treat constraints, either as an equality constraint or
+                  // as a sequence of constraints
+                  if (is_identity_constrained == true)
+                    {
+                      // Query the correct face_index on face_2 respecting the given
+                      // orientation:
+                      const unsigned int j =
+                        cell_to_rotated_face_index[fe.face_to_cell_index(identity_constraint_target,
+                            0, /* It doesn't really matter, just assume
+                           * we're on the first face...
+                           */
+                                                                         face_orientation, face_flip, face_rotation)];
+
+                      // if the two aren't already identity constrained (whichever way
+                      // around, then enter the constraint. otherwise there is nothing
+                      // for us still to do
+                      if (constraint_matrix.are_identity_constrained(dofs_2[i], dofs_1[i]) == false)
+                        {
+                          constraint_matrix.add_line(dofs_2[i]);
+                          constraint_matrix.add_entry(dofs_2[i], dofs_1[j], 1);
+                        }
+                    }
+                  else
+                    {
+                      // this is just a regular constraint. enter it piece by piece
+                      constraint_matrix.add_line(dofs_2[i]);
+                      for (unsigned int jj=0; jj<dofs_per_face; ++jj)
+                        {
+                          // Query the correct face_index on face_2 respecting the given
+                          // orientation:
+                          const unsigned int j =
+                            cell_to_rotated_face_index[fe.face_to_cell_index(jj, 0, /* It doesn't really matter, just assume
+                               * we're on the first face...
+                               */
+                                                                             face_orientation, face_flip, face_rotation)];
+
+                          // And finally constrain the two DoFs respecting component_mask:
+                          if (transformation(i,jj) != 0)
+                            constraint_matrix.add_entry(dofs_2[i], dofs_1[j],
+                                                        transformation(i,jj));
+                        }
+                    }
+                }
+        }
+    }
+  }
+
+
+  template <typename FaceIterator>
+  void
+  make_periodicity_constraints (const FaceIterator                          &face_1,
+                                const typename identity<FaceIterator>::type &face_2,
+                                dealii::ConstraintMatrix                    &constraint_matrix,
+                                const ComponentMask                         &component_mask,
+                                const bool                                   face_orientation,
+                                const bool                                   face_flip,
+                                const bool                                   face_rotation)
+  {
+    static const int dim = FaceIterator::AccessorType::dimension;
+
+    Assert( (dim != 1) ||
+            (face_orientation == true &&
+             face_flip == false &&
+             face_rotation == false),
+            ExcMessage ("The supplied orientation "
+                        "(face_orientation, face_flip, face_rotation) "
+                        "is invalid for 1D"));
+
+    Assert( (dim != 2) ||
+            (face_orientation == true &&
+             face_rotation == false),
+            ExcMessage ("The supplied orientation "
+                        "(face_orientation, face_flip, face_rotation) "
+                        "is invalid for 2D"));
+
+    Assert(face_1 != face_2,
+           ExcMessage ("face_1 and face_2 are equal! Cannot constrain DoFs "
+                       "on the very same face"));
+
+    Assert(face_1->at_boundary() && face_2->at_boundary(),
+           ExcMessage ("Faces for periodicity constraints must be on the boundary"));
+
+
+    // A lookup table on how to go through the child faces depending on the
+    // orientation:
+
+    static const int lookup_table_2d[2][2] =
+    {
+      //          flip:
+      {0, 1}, //  false
+      {1, 0}, //  true
+    };
+
+    static const int lookup_table_3d[2][2][2][4] =
+    {
+      //                    orientation flip  rotation
+      { { {0, 2, 1, 3}, //  false       false false
+          {2, 3, 0, 1}, //  false       false true
+        },
+        { {3, 1, 2, 0}, //  false       true  false
+          {1, 0, 3, 2}, //  false       true  true
+        },
+      },
+      { { {0, 1, 2, 3}, //  true        false false
+          {1, 3, 0, 2}, //  true        false true
+        },
+        { {3, 2, 1, 0}, //  true        true  false
+          {2, 0, 3, 1}, //  true        true  true
+        },
+      },
+    };
+
+    // In the case that both faces have children, we loop over all
+    // children and apply make_periodicty_constrains recursively:
+    if (face_1->has_children() && face_2->has_children())
+      {
+        Assert(face_1->n_children() == GeometryInfo<dim>::max_children_per_face &&
+               face_2->n_children() == GeometryInfo<dim>::max_children_per_face,
+               ExcNotImplemented());
+
+        for (unsigned int i = 0; i < GeometryInfo<dim>::max_children_per_face; ++i)
+          {
+            // Lookup the index for the second face
+            unsigned int j;
+            switch (dim)
+              {
+              case 2:
+                j = lookup_table_2d[face_flip][i];
+                break;
+              case 3:
+                j = lookup_table_3d[face_orientation][face_flip][face_rotation][i];
+                break;
+              default:
+                AssertThrow(false, ExcNotImplemented());
+              }
+
+            make_periodicity_constraints (face_1->child(i),
+                                          face_2->child(j),
+                                          constraint_matrix,
+                                          component_mask,
+                                          face_orientation,
+                                          face_flip,
+                                          face_rotation);
+          }
+      }
+    else
+      // otherwise at least one of the two faces is active and
+      // we need to enter the constraints
+      {
+        if (face_2->has_children() == false)
+          set_periodicity_constraints(face_2, face_1,
+                                      FullMatrix<double>(IdentityMatrix(face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face)),
+                                      constraint_matrix,
+                                      component_mask,
+                                      face_orientation, face_flip, face_rotation);
+        else
+          set_periodicity_constraints(face_1, face_2,
+                                      FullMatrix<double>(IdentityMatrix(face_1->get_fe(face_1->nth_active_fe_index(0)).dofs_per_face)),
+                                      constraint_matrix,
+                                      component_mask,
+                                      face_orientation, face_flip, face_rotation);
+      }
+  }
+
+
+
+  template<typename DH>
+  void
+  make_periodicity_constraints (const DH                       &dof_handler,
+                                const types::boundary_id       b_id1,
+                                const types::boundary_id       b_id2,
+                                const int                      direction,
+                                dealii::ConstraintMatrix       &constraint_matrix,
+                                const ComponentMask            &component_mask)
+  {
+    Tensor<1,DH::space_dimension> dummy;
+    make_periodicity_constraints (dof_handler,
+                                  b_id1,
+                                  b_id2,
+                                  direction,
+                                  dummy,
+                                  constraint_matrix,
+                                  component_mask);
+  }
+
+
+
+  template<typename DH>
+  void
+  make_periodicity_constraints (const DH                  &dof_handler,
+                                const types::boundary_id  b_id1,
+                                const types::boundary_id  b_id2,
+                                const int                 direction,
+                                dealii::Tensor<1,DH::space_dimension> &offset,
+                                dealii::ConstraintMatrix  &constraint_matrix,
+                                const ComponentMask       &component_mask)
+  {
+    static const int space_dim = DH::space_dimension;
+    Assert (0<=direction && direction<space_dim,
+            ExcIndexRange (direction, 0, space_dim));
+
+#if defined(DEBUG) && defined(DEAL_II_WITH_P4EST)
+    // Check whether we run on a non parallel mesh or on a
+    // parallel::distributed::Triangulation in serial
+    {
+      typedef parallel::distributed::Triangulation<DH::dimension,DH::space_dimension> PTRIA;
+      const PTRIA *ptria_p = dynamic_cast<const PTRIA *> (&dof_handler.get_tria());
+      Assert ((ptria_p == 0 || Utilities::MPI::n_mpi_processes(ptria_p->get_communicator()) == 1),
+              ExcMessage ("This function can not be used with distributed triangulations."
+                          "See the documentation for more information."));
+    }
+#endif
+
+    Assert (b_id1 != b_id2,
+            ExcMessage ("The boundary indicators b_id1 and b_id2 must be"
+                        "different to denote different boundaries."));
+
+    typedef typename DH::face_iterator FaceIterator;
+    typedef std::map<FaceIterator, std::pair<FaceIterator, std::bitset<3> > > FaceMap;
+
+    // Collect matching periodic cells on the coarsest level:
+    FaceMap matched_cells =
+      GridTools::collect_periodic_face_pairs(dof_handler,
+                                             b_id1, b_id2,
+                                             direction, offset);
+
+    // And apply the low level make_periodicity_constraints function to
+    // every matching pair:
+    for (typename FaceMap::iterator it = matched_cells.begin();
+         it != matched_cells.end(); ++it)
+      {
+        typedef typename DH::face_iterator FaceIterator;
+        const FaceIterator &face_1 = it->first;
+        const FaceIterator &face_2 = it->second.first;
+        const std::bitset<3> &orientation = it->second.second;
+
+        Assert(face_1->at_boundary() && face_2->at_boundary(),
+               ExcInternalError());
+
+        Assert (face_1->boundary_indicator() == b_id1 &&
+                face_2->boundary_indicator() == b_id2,
+                ExcInternalError());
+
+        Assert (face_1 != face_2,
+                ExcInternalError());
+
+        make_periodicity_constraints(face_1,
+                                     face_2,
+                                     constraint_matrix,
+                                     component_mask,
+                                     orientation[0],
+                                     orientation[1],
+                                     orientation[2]);
+      }
+  }
+
+
+
+  template<typename DH>
+  void
+  make_periodicity_constraints (const DH                       &dof_handler,
+                                const types::boundary_id       b_id,
+                                const int                      direction,
+                                dealii::ConstraintMatrix       &constraint_matrix,
+                                const ComponentMask            &component_mask)
+  {
+    Tensor<1,DH::space_dimension> dummy;
+    make_periodicity_constraints (dof_handler,
+                                  b_id,
+                                  direction,
+                                  dummy,
+                                  constraint_matrix,
+                                  component_mask);
+  }
+
+
+
+  template<typename DH>
+  void
+  make_periodicity_constraints (const DH                  &dof_handler,
+                                const types::boundary_id  b_id,
+                                const int                 direction,
+                                dealii::Tensor<1,DH::space_dimension> &offset,
+                                dealii::ConstraintMatrix  &constraint_matrix,
+                                const ComponentMask       &component_mask)
+  {
+    static const int dim = DH::dimension;
+    static const int space_dim = DH::space_dimension;
+
+    Assert (0<=direction && direction<space_dim,
+            ExcIndexRange (direction, 0, space_dim));
+
+    Assert(dim == space_dim,
+           ExcNotImplemented());
+
+#if defined(DEBUG) && defined(DEAL_II_WITH_P4EST)
+    // Check whether we run on a non parallel mesh or on a
+    // parallel::distributed::Triangulation in serial
+    {
+      typedef typename parallel::distributed::Triangulation<DH::dimension,DH::space_dimension> PTRIA;
+      const PTRIA *ptria_p = dynamic_cast<const PTRIA *> (&dof_handler.get_tria());
+      Assert ((ptria_p == 0 || Utilities::MPI::n_mpi_processes(ptria_p->get_communicator()) == 1),
+              ExcMessage ("This function can not be used with distributed triangulations."
+                          "See the documentation for more information."));
+    }
+#endif
+
+    typedef typename DH::face_iterator FaceIterator;
+    typedef std::map<FaceIterator, FaceIterator> FaceMap;
+
+    // Collect matching periodic cells on the coarsest level:
+    FaceMap matched_cells =
+      GridTools::collect_periodic_face_pairs(dof_handler,
+                                             b_id,
+                                             direction, offset);
+
+    // And apply the low level make_periodicity_constraints function to
+    // every matching pair:
+    for (typename FaceMap::iterator it = matched_cells.begin();
+         it != matched_cells.end(); ++it)
+      {
+        typedef typename DH::face_iterator FaceIterator;
+        const FaceIterator &face_1 = it->first;
+        const FaceIterator &face_2 = it->second;
+
+        Assert(face_1->at_boundary() && face_2->at_boundary(),
+               ExcInternalError());
+
+        Assert (face_1->boundary_indicator() == b_id &&
+                face_2->boundary_indicator() == b_id,
+                ExcInternalError());
+
+        Assert (face_1 != face_2,
+                ExcInternalError());
+
+        make_periodicity_constraints(face_1,
+                                     face_2,
+                                     constraint_matrix,
+                                     component_mask
+                                     /* standard orientation */);
+      }
+  }
+
+
+
+  namespace internal
+  {
+    namespace
+    {
+      /**
+       * This is a function that is called by the _2 function and that
+       * operates on a range of cells only. It is used to split up the
+       * whole range of cells into chunks which are then worked on in
+       * parallel, if multithreading is available.
+       */
+      template <int dim, int spacedim>
+      void
+      compute_intergrid_weights_3 (
+        const dealii::DoFHandler<dim,spacedim>              &coarse_grid,
+        const unsigned int                  coarse_component,
+        const InterGridMap<dealii::DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
+        const std::vector<dealii::Vector<double> > &parameter_dofs,
+        const std::vector<types::global_dof_index>             &weight_mapping,
+        std::vector<std::map<types::global_dof_index, float> > &weights,
+        const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &begin,
+        const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &end)
+      {
+        // aliases to the finite elements used by the dof handlers:
+        const FiniteElement<dim,spacedim> &coarse_fe = coarse_grid.get_fe();
+
+        // for each cell on the parameter grid: find out which degrees of
+        // freedom on the fine grid correspond in which way to the degrees
+        // of freedom on the parameter grid
+        //
+        // since for continuous FEs some dofs exist on more than one cell,
+        // we have to track which ones were already visited. the problem is
+        // that if we visit a dof first on one cell and compute its weight
+        // with respect to some global dofs to be non-zero, and later visit
+        // the dof again on another cell and (since we are on another cell)
+        // recompute the weights with respect to the same dofs as above to
+        // be zero now, we have to preserve them. we therefore overwrite
+        // all weights if they are nonzero and do not enforce zero weights
+        // since that might be only due to the fact that we are on another
+        // cell.
+        //
+        // example:
+        // coarse grid
+        //  |     |     |
+        //  *-----*-----*
+        //  | cell|cell |
+        //  |  1  |  2  |
+        //  |     |     |
+        //  0-----1-----*
+        //
+        // fine grid
+        //  |  |  |  |  |
+        //  *--*--*--*--*
+        //  |  |  |  |  |
+        //  *--*--*--*--*
+        //  |  |  |  |  |
+        //  *--x--y--*--*
+        //
+        // when on cell 1, we compute the weights of dof 'x' to be 1/2 from
+        // parameter dofs 0 and 1, respectively. however, when later we are
+        // on cell 2, we again compute the prolongation of shape function 1
+        // restricted to cell 2 to the globla grid and find that the weight
+        // of global dof 'x' now is zero. however, we should not overwrite
+        // the old value.
+        //
+        // we therefore always only set nonzero values. why adding up is
+        // not useful: dof 'y' would get weight 1 from parameter dof 1 on
+        // both cells 1 and 2, but the correct weight is nevertheless only
+        // 1.
+
+        // vector to hold the representation of a single degree of freedom
+        // on the coarse grid (for the selected fe) on the fine grid
+        const types::global_dof_index n_fine_dofs = weight_mapping.size();
+        dealii::Vector<double> global_parameter_representation (n_fine_dofs);
+
+        typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator cell;
+        std::vector<types::global_dof_index> parameter_dof_indices (coarse_fe.dofs_per_cell);
+
+        for (cell=begin; cell!=end; ++cell)
+          {
+            // get the global indices of the parameter dofs on this
+            // parameter grid cell
+            cell->get_dof_indices (parameter_dof_indices);
+
+            // loop over all dofs on this cell and check whether they are
+            // interesting for us
+            for (unsigned int local_dof=0;
+                 local_dof<coarse_fe.dofs_per_cell;
+                 ++local_dof)
+              if (coarse_fe.system_to_component_index(local_dof).first
+                  ==
+                  coarse_component)
+                {
+                  // the how-many-th parameter is this on this cell?
+                  const unsigned int local_parameter_dof
+                    = coarse_fe.system_to_component_index(local_dof).second;
+
+                  global_parameter_representation = 0;
+
+                  // distribute the representation of
+                  // @p{local_parameter_dof} on the parameter grid cell
+                  // @p{cell} to the global data space
+                  coarse_to_fine_grid_map[cell]->
+                  set_dof_values_by_interpolation (parameter_dofs[local_parameter_dof],
+                                                   global_parameter_representation);
+                  // now that we've got the global representation of each
+                  // parameter dof, we've only got to clobber the non-zero
+                  // entries in that vector and store the result
+                  //
+                  // what we have learned: if entry @p{i} of the global
+                  // vector holds the value @p{v[i]}, then this is the
+                  // weight with which the present dof contributes to
+                  // @p{i}. there may be several such @p{i}s and their
+                  // weights' sum should be one. Then, @p{v[i]} should be
+                  // equal to @p{\sum_j w_{ij} p[j]} with @p{p[j]} be the
+                  // values of the degrees of freedom on the coarse grid.
+                  // we can thus compute constraints which link the degrees
+                  // of freedom @p{v[i]} on the fine grid to those on the
+                  // coarse grid, @p{p[j]}. Now to use these as real
+                  // constraints, rather than as additional equations, we
+                  // have to identify representants among the @p{i} for
+                  // each @p{j}. this will be done by simply taking the
+                  // first @p{i} for which @p{w_{ij}==1}.
+                  //
+                  // guard modification of the weights array by a Mutex.
+                  // since it should happen rather rarely that there are
+                  // several threads operating on different intergrid
+                  // weights, have only one mutex for all of them
+                  static Threads::Mutex mutex;
+                  Threads::Mutex::ScopedLock lock (mutex);
+                  for (types::global_dof_index i=0; i<global_parameter_representation.size(); ++i)
+                    // set this weight if it belongs to a parameter dof.
+                    if (weight_mapping[i] != numbers::invalid_dof_index)
+                      {
+                        // only overwrite old value if not by zero
+                        if (global_parameter_representation(i) != 0)
+                          {
+                            const types::global_dof_index wi = parameter_dof_indices[local_dof],
+                                                          wj = weight_mapping[i];
+                            weights[wi][wj] = global_parameter_representation(i);
+                          };
+                      }
+                    else
+                      Assert (global_parameter_representation(i) == 0,
+                              ExcInternalError());
+                }
+          }
+      }
+
+
+      /**
+       * This is a helper function that is used in the computation of
+       * integrid constraints. See the function for a thorough description
+       * of how it works.
+       */
+      template <int dim, int spacedim>
+      void
+      compute_intergrid_weights_2 (
+        const dealii::DoFHandler<dim,spacedim>              &coarse_grid,
+        const unsigned int                  coarse_component,
+        const InterGridMap<dealii::DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
+        const std::vector<dealii::Vector<double> > &parameter_dofs,
+        const std::vector<types::global_dof_index>             &weight_mapping,
+        std::vector<std::map<types::global_dof_index,float> > &weights)
+      {
+        // simply distribute the range of cells to different threads
+        typedef typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator active_cell_iterator;
+        std::vector<std::pair<active_cell_iterator,active_cell_iterator> >
+        cell_intervals = Threads::split_range<active_cell_iterator> (coarse_grid.begin_active(),
+                         coarse_grid.end(),
+                         multithread_info.n_default_threads);
+
+        // TODO: use WorkStream here
+
+        Threads::TaskGroup<> tasks;
+        void (*fun_ptr) (const dealii::DoFHandler<dim,spacedim> &,
+                         const unsigned int                  ,
+                         const InterGridMap<dealii::DoFHandler<dim,spacedim> > &,
+                         const std::vector<dealii::Vector<double> > &,
+                         const std::vector<types::global_dof_index> &,
+                         std::vector<std::map<types::global_dof_index, float> > &,
+                         const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &,
+                         const typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator &)
+          = &compute_intergrid_weights_3<dim>;
+        for (unsigned int i=0; i<multithread_info.n_default_threads; ++i)
+          tasks += Threads::new_task (fun_ptr,
+                                      coarse_grid, coarse_component,
+                                      coarse_to_fine_grid_map, parameter_dofs,
+                                      weight_mapping, weights,
+                                      cell_intervals[i].first,
+                                      cell_intervals[i].second);
+
+        // wait for the tasks to finish
+        tasks.join_all ();
+      }
+
+
+
+      /**
+       * This is a helper function that is used in the computation of
+       * integrid constraints. See the function for a thorough description
+       * of how it works.
+       */
+      template <int dim, int spacedim>
+      unsigned int
+      compute_intergrid_weights_1 (
+        const dealii::DoFHandler<dim,spacedim>              &coarse_grid,
+        const unsigned int                  coarse_component,
+        const dealii::DoFHandler<dim,spacedim>              &fine_grid,
+        const unsigned int                  fine_component,
+        const InterGridMap<dealii::DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
+        std::vector<std::map<types::global_dof_index, float> > &weights,
+        std::vector<types::global_dof_index>                   &weight_mapping)
+      {
+        // aliases to the finite elements used by the dof handlers:
+        const FiniteElement<dim,spacedim> &coarse_fe = coarse_grid.get_fe(),
+                                           &fine_fe   = fine_grid.get_fe();
+
+        // global numbers of dofs
+        const types::global_dof_index n_coarse_dofs = coarse_grid.n_dofs(),
+                                      n_fine_dofs   = fine_grid.n_dofs();
+
+        // local numbers of dofs
+        const unsigned int fine_dofs_per_cell   = fine_fe.dofs_per_cell;
+
+        // alias the number of dofs per cell belonging to the
+        // coarse_component which is to be the restriction of the fine
+        // grid:
+        const unsigned int coarse_dofs_per_cell_component
+          = coarse_fe.base_element(coarse_fe.component_to_base_index(coarse_component).first).dofs_per_cell;
+
+
+        // Try to find out whether the grids stem from the same coarse
+        // grid. This is a rather crude test, but better than nothing
+        Assert (coarse_grid.get_tria().n_cells(0) == fine_grid.get_tria().n_cells(0),
+                ExcGridsDontMatch());
+
+        // check whether the map correlates the right objects
+        Assert (&coarse_to_fine_grid_map.get_source_grid() == &coarse_grid,
+                ExcGridsDontMatch ());
+        Assert (&coarse_to_fine_grid_map.get_destination_grid() == &fine_grid,
+                ExcGridsDontMatch ());
+
+
+        // check whether component numbers are valid
+        AssertIndexRange (coarse_component,coarse_fe.n_components());
+        AssertIndexRange (fine_component, fine_fe.n_components());
+
+        // check whether respective finite elements are equal
+        Assert (coarse_fe.base_element (coarse_fe.component_to_base_index(coarse_component).first)
+                ==
+                fine_fe.base_element (fine_fe.component_to_base_index(fine_component).first),
+                ExcFiniteElementsDontMatch());
+
+#ifdef DEBUG
+        // if in debug mode, check whether the coarse grid is indeed
+        // coarser everywhere than the fine grid
+        for (typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator
+             cell=coarse_grid.begin_active();
+             cell != coarse_grid.end(); ++cell)
+          Assert (cell->level() <= coarse_to_fine_grid_map[cell]->level(),
+                  ExcGridNotCoarser());
+#endif
+
+        /*
+         * From here on: the term `parameter' refers to the selected
+         * component on the coarse grid and its analogon on the fine grid.
+         * The naming of variables containing this term is due to the fact
+         * that `selected_component' is longer, but also due to the fact
+         * that the code of this function was initially written for a
+         * program where the component which we wanted to match between
+         * grids was actually the `parameter' variable.
+         *
+         * Likewise, the terms `parameter grid' and `state grid' refer to
+         * the coarse and fine grids, respectively.
+         *
+         * Changing the names of variables would in principle be a good
+         * idea, but would not make things simpler and would be another
+         * source of errors. If anyone feels like doing so: patches would
+         * be welcome!
+         */
+
+
+
+        // set up vectors of cell-local data; each vector represents one
+        // degree of freedom of the coarse-grid variable in the fine-grid
+        // element
+        std::vector<dealii::Vector<double> >
+        parameter_dofs (coarse_dofs_per_cell_component,
+                        dealii::Vector<double>(fine_dofs_per_cell));
+        // for each coarse dof: find its position within the fine element
+        // and set this value to one in the respective vector (all other
+        // values are zero by construction)
+        for (unsigned int local_coarse_dof=0;
+             local_coarse_dof<coarse_dofs_per_cell_component;
+             ++local_coarse_dof)
+          for (unsigned int fine_dof=0; fine_dof<fine_fe.dofs_per_cell; ++fine_dof)
+            if (fine_fe.system_to_component_index(fine_dof)
+                ==
+                std::make_pair (fine_component, local_coarse_dof))
+              {
+                parameter_dofs[local_coarse_dof](fine_dof) = 1.;
+                break;
+              };
+
+
+        // find out how many DoFs there are on the grids belonging to the
+        // components we want to match
+        unsigned int n_parameters_on_fine_grid=0;
+        if (true)
+          {
+            // have a flag for each dof on the fine grid and set it to true
+            // if this is an interesting dof. finally count how many true's
+            // there
+            std::vector<bool> dof_is_interesting (fine_grid.n_dofs(), false);
+            std::vector<types::global_dof_index>  local_dof_indices (fine_fe.dofs_per_cell);
+
+            for (typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator
+                 cell=fine_grid.begin_active();
+                 cell!=fine_grid.end(); ++cell)
+              {
+                cell->get_dof_indices (local_dof_indices);
+                for (unsigned int i=0; i<fine_fe.dofs_per_cell; ++i)
+                  if (fine_fe.system_to_component_index(i).first == fine_component)
+                    dof_is_interesting[local_dof_indices[i]] = true;
+              };
+
+            n_parameters_on_fine_grid = std::count (dof_is_interesting.begin(),
+                                                    dof_is_interesting.end(),
+                                                    true);
+          };
+
+
+        // set up the weights mapping
+        weights.clear ();
+        weights.resize (n_coarse_dofs);
+
+        weight_mapping.clear ();
+        weight_mapping.resize (n_fine_dofs, numbers::invalid_dof_index);
+
+        if (true)
+          {
+            std::vector<types::global_dof_index> local_dof_indices(fine_fe.dofs_per_cell);
+            unsigned int next_free_index=0;
+            for (typename dealii::DoFHandler<dim,spacedim>::active_cell_iterator
+                 cell=fine_grid.begin_active();
+                 cell != fine_grid.end(); ++cell)
+              {
+                cell->get_dof_indices (local_dof_indices);
+                for (unsigned int i=0; i<fine_fe.dofs_per_cell; ++i)
+                  // if this DoF is a parameter dof and has not yet been
+                  // numbered, then do so
+                  if ((fine_fe.system_to_component_index(i).first == fine_component) &&
+                      (weight_mapping[local_dof_indices[i]] == numbers::invalid_dof_index))
+                    {
+                      weight_mapping[local_dof_indices[i]] = next_free_index;
+                      ++next_free_index;
+                    };
+              };
+
+            Assert (next_free_index == n_parameters_on_fine_grid,
+                    ExcInternalError());
+          };
+
+
+        // for each cell on the parameter grid: find out which degrees of
+        // freedom on the fine grid correspond in which way to the degrees
+        // of freedom on the parameter grid
+        //
+        // do this in a separate function to allow for multithreading
+        // there. see this function also if you want to read more
+        // information on the algorithm used.
+        compute_intergrid_weights_2 (coarse_grid, coarse_component,
+                                     coarse_to_fine_grid_map, parameter_dofs,
+                                     weight_mapping, weights);
+
+
+        // ok, now we have all weights for each dof on the fine grid. if in
+        // debug mode lets see if everything went smooth, i.e. each dof has
+        // sum of weights one
+        //
+        // in other words this means that if the sum of all shape functions
+        // on the parameter grid is one (which is always the case), then
+        // the representation on the state grid should be as well (division
+        // of unity)
+        //
+        // if the parameter grid has more than one component, then the
+        // respective dofs of the other components have sum of weights
+        // zero, of course. we do not explicitly ask which component a dof
+        // belongs to, but this at least tests some errors
+#ifdef DEBUG
+        for (unsigned int col=0; col<n_parameters_on_fine_grid; ++col)
+          {
+            double sum=0;
+            for (types::global_dof_index row=0; row<n_coarse_dofs; ++row)
+              if (weights[row].find(col) != weights[row].end())
+                sum += weights[row][col];
+            Assert ((std::fabs(sum-1) < 1.e-12) ||
+                    ((coarse_fe.n_components()>1) && (sum==0)), ExcInternalError());
+          };
+#endif
+
+
+        return n_parameters_on_fine_grid;
+      }
+
+
+    }
+  }
+
+
+
+  template <int dim, int spacedim>
+  void
+  compute_intergrid_constraints (
+    const DoFHandler<dim,spacedim>              &coarse_grid,
+    const unsigned int                  coarse_component,
+    const DoFHandler<dim,spacedim>              &fine_grid,
+    const unsigned int                  fine_component,
+    const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
+    ConstraintMatrix                   &constraints)
+  {
+    // store the weights with which a dof on the parameter grid contributes
+    // to a dof on the fine grid. see the long doc below for more info
+    //
+    // allocate as many rows as there are parameter dofs on the coarse grid
+    // and as many columns as there are parameter dofs on the fine grid.
+    //
+    // weight_mapping is used to map the global (fine grid) parameter dof
+    // indices to the columns
+    //
+    // in the original implementation, the weights array was actually of
+    // FullMatrix<double> type. this wasted huge amounts of memory, but was
+    // fast. nonetheless, since the memory consumption was quadratic in the
+    // number of degrees of freedom, this was not very practical, so we now
+    // use a vector of rows of the matrix, and in each row a vector of
+    // pairs (colnum,value). this seems like the best tradeoff between
+    // memory and speed, as it is now linear in memory and still fast
+    // enough.
+    //
+    // to save some memory and since the weights are usually (negative)
+    // powers of 2, we choose the value type of the matrix to be @p{float}
+    // rather than @p{double}.
+    std::vector<std::map<types::global_dof_index, float> > weights;
+
+    // this is this mapping. there is one entry for each dof on the fine
+    // grid; if it is a parameter dof, then its value is the column in
+    // weights for that parameter dof, if it is any other dof, then its
+    // value is -1, indicating an error
+    std::vector<types::global_dof_index> weight_mapping;
+
+    const unsigned int n_parameters_on_fine_grid
+      = internal::compute_intergrid_weights_1 (coarse_grid, coarse_component,
+                                               fine_grid, fine_component,
+                                               coarse_to_fine_grid_map,
+                                               weights, weight_mapping);
+
+    // global numbers of dofs
+    const types::global_dof_index n_coarse_dofs = coarse_grid.n_dofs(),
+                                  n_fine_dofs   = fine_grid.n_dofs();
+
+
+    // get an array in which we store which dof on the coarse grid is a
+    // parameter and which is not
+    std::vector<bool> coarse_dof_is_parameter (coarse_grid.n_dofs());
+    if (true)
+      {
+        std::vector<bool> mask (coarse_grid.get_fe().n_components(),
+                                false);
+        mask[coarse_component] = true;
+        extract_dofs (coarse_grid, ComponentMask(mask), coarse_dof_is_parameter);
+      }
+
+    // now we know that the weights in each row constitute a constraint.
+    // enter this into the constraints object
+    //
+    // first task: for each parameter dof on the parameter grid, find a
+    // representant on the fine, global grid. this is possible since we use
+    // conforming finite element. we take this representant to be the first
+    // element in this row with weight identical to one. the representant
+    // will become an unconstrained degree of freedom, while all others
+    // will be constrained to this dof (and possibly others)
+    std::vector<types::global_dof_index> representants(n_coarse_dofs, numbers::invalid_dof_index);
+    for (types::global_dof_index parameter_dof=0; parameter_dof<n_coarse_dofs;
+         ++parameter_dof)
+      if (coarse_dof_is_parameter[parameter_dof] == true)
+        {
+          // if this is the line of a parameter dof on the coarse grid,
+          // then it should have at least one dependent node on the fine
+          // grid
+          Assert (weights[parameter_dof].size() > 0, ExcInternalError());
+
+          // find the column where the representant is mentioned
+          std::map<types::global_dof_index,float>::const_iterator i = weights[parameter_dof].begin();
+          for (; i!=weights[parameter_dof].end(); ++i)
+            if (i->second == 1)
+              break;
+          Assert (i!=weights[parameter_dof].end(), ExcInternalError());
+          const types::global_dof_index column = i->first;
+
+          // now we know in which column of weights the representant is,
+          // but we don't know its global index. get it using the inverse
+          // operation of the weight_mapping
+          types::global_dof_index global_dof=0;
+          for (; global_dof<weight_mapping.size(); ++global_dof)
+            if (weight_mapping[global_dof] == static_cast<types::global_dof_index>(column))
+              break;
+          Assert (global_dof < weight_mapping.size(), ExcInternalError());
+
+          // now enter the representants global index into our list
+          representants[parameter_dof] = global_dof;
+        }
+      else
+        {
+          // consistency check: if this is no parameter dof on the coarse
+          // grid, then the respective row must be empty!
+          Assert (weights[parameter_dof].size() == 0, ExcInternalError());
+        };
+
+
+
+    // note for people that want to optimize this function: the largest
+    // part of the computing time is spent in the following, rather
+    // innocent block of code. basically, it must be the
+    // ConstraintMatrix::add_entry call which takes the bulk of the time,
+    // but it is not known to the author how to make it faster...
+    std::vector<std::pair<types::global_dof_index,double> > constraint_line;
+    for (types::global_dof_index global_dof=0; global_dof<n_fine_dofs; ++global_dof)
+      if (weight_mapping[global_dof] != numbers::invalid_dof_index)
+        // this global dof is a parameter dof, so it may carry a constraint
+        // note that for each global dof, the sum of weights shall be one,
+        // so we can find out whether this dof is constrained in the
+        // following way: if the only weight in this row is a one, and the
+        // representant for the parameter dof of the line in which this one
+        // is is the present dof, then we consider this dof to be
+        // unconstrained. otherwise, all other dofs are constrained
+        {
+          const types::global_dof_index col = weight_mapping[global_dof];
+          Assert (col < n_parameters_on_fine_grid, ExcInternalError());
+
+          types::global_dof_index first_used_row=0;
+
+          {
+            Assert (weights.size() > 0, ExcInternalError());
+            std::map<types::global_dof_index,float>::const_iterator
+            col_entry = weights[0].end();
+            for (; first_used_row<n_coarse_dofs; ++first_used_row)
+              {
+                col_entry = weights[first_used_row].find(col);
+                if (col_entry != weights[first_used_row].end())
+                  break;
+              }
+
+            Assert (col_entry != weights[first_used_row].end(), ExcInternalError());
+
+            if ((col_entry->second == 1) &&
+                (representants[first_used_row] == global_dof))
+              // dof unconstrained or constrained to itself (in case this
+              // cell is mapped to itself, rather than to children of
+              // itself)
+              continue;
+          }
+
+
+          // otherwise enter all constraints
+          constraints.add_line (global_dof);
+
+          constraint_line.clear ();
+          for (types::global_dof_index row=first_used_row; row<n_coarse_dofs; ++row)
+            {
+              const std::map<types::global_dof_index,float>::const_iterator
+              j = weights[row].find(col);
+              if ((j != weights[row].end()) && (j->second != 0))
+                constraint_line.push_back (std::pair<types::global_dof_index,double>(representants[row],
+                                           j->second));
+            };
+
+          constraints.add_entries (global_dof, constraint_line);
+        };
+  }
+
+
+
+  template <int dim, int spacedim>
+  void
+  compute_intergrid_transfer_representation (
+    const DoFHandler<dim,spacedim>              &coarse_grid,
+    const unsigned int                  coarse_component,
+    const DoFHandler<dim,spacedim>              &fine_grid,
+    const unsigned int                  fine_component,
+    const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
+    std::vector<std::map<types::global_dof_index, float> > &transfer_representation)
+  {
+    // store the weights with which a dof on the parameter grid contributes
+    // to a dof on the fine grid. see the long doc below for more info
+    //
+    // allocate as many rows as there are parameter dofs on the coarse grid
+    // and as many columns as there are parameter dofs on the fine grid.
+    //
+    // weight_mapping is used to map the global (fine grid) parameter dof
+    // indices to the columns
+    //
+    // in the original implementation, the weights array was actually of
+    // FullMatrix<double> type. this wasted huge amounts of memory, but was
+    // fast. nonetheless, since the memory consumption was quadratic in the
+    // number of degrees of freedom, this was not very practical, so we now
+    // use a vector of rows of the matrix, and in each row a vector of
+    // pairs (colnum,value). this seems like the best tradeoff between
+    // memory and speed, as it is now linear in memory and still fast
+    // enough.
+    //
+    // to save some memory and since the weights are usually (negative)
+    // powers of 2, we choose the value type of the matrix to be @p{float}
+    // rather than @p{double}.
+    std::vector<std::map<types::global_dof_index, float> > weights;
+
+    // this is this mapping. there is one entry for each dof on the fine
+    // grid; if it is a parameter dof, then its value is the column in
+    // weights for that parameter dof, if it is any other dof, then its
+    // value is -1, indicating an error
+    std::vector<types::global_dof_index> weight_mapping;
+
+    internal::compute_intergrid_weights_1 (coarse_grid, coarse_component,
+                                           fine_grid, fine_component,
+                                           coarse_to_fine_grid_map,
+                                           weights, weight_mapping);
+
+    // now compute the requested representation
+    const types::global_dof_index n_global_parm_dofs
+      = std::count_if (weight_mapping.begin(), weight_mapping.end(),
+                       std::bind2nd (std::not_equal_to<types::global_dof_index> (), numbers::invalid_dof_index));
+
+    // first construct the inverse mapping of weight_mapping
+    std::vector<types::global_dof_index> inverse_weight_mapping (n_global_parm_dofs,
+        DoFHandler<dim,spacedim>::invalid_dof_index);
+    for (types::global_dof_index i=0; i<weight_mapping.size(); ++i)
+      {
+        const types::global_dof_index parameter_dof = weight_mapping[i];
+        // if this global dof is a parameter
+        if (parameter_dof != numbers::invalid_dof_index)
+          {
+            Assert (parameter_dof < n_global_parm_dofs, ExcInternalError());
+            Assert ((inverse_weight_mapping[parameter_dof] == DoFHandler<dim,spacedim>::invalid_dof_index),
+                    ExcInternalError());
+
+            inverse_weight_mapping[parameter_dof] = i;
+          };
+      };
+
+    // next copy over weights array and replace respective numbers
+    const types::global_dof_index n_rows = weight_mapping.size();
+
+    transfer_representation.clear ();
+    transfer_representation.resize (n_rows);
+
+    const types::global_dof_index n_coarse_dofs = coarse_grid.n_dofs();
+    for (types::global_dof_index i=0; i<n_coarse_dofs; ++i)
+      {
+        std::map<types::global_dof_index, float>::const_iterator j = weights[i].begin();
+        for (; j!=weights[i].end(); ++j)
+          {
+            const types::global_dof_index p = inverse_weight_mapping[j->first];
+            Assert (p<n_rows, ExcInternalError());
+
+            transfer_representation[p][i] = j->second;
+          };
+      };
+  }
+
+
+
+  template <int dim, int spacedim, template <int,int> class DH>
+  void
+  make_zero_boundary_constraints (const DH<dim, spacedim> &dof,
+                                  const types::boundary_id boundary_indicator,
+                                  ConstraintMatrix        &zero_boundary_constraints,
+                                  const ComponentMask     &component_mask)
+  {
+    Assert (component_mask.represents_n_components(dof.get_fe().n_components()),
+            ExcMessage ("The number of components in the mask has to be either "
+                        "zero or equal to the number of components in the finite "
+                        "element."));
+
+    const unsigned int n_components = DoFTools::n_components (dof);
+
+    Assert (component_mask.n_selected_components(n_components) > 0,
+            ComponentMask::ExcNoComponentSelected());
+
+    // a field to store the indices
+    std::vector<types::global_dof_index> face_dofs;
+    face_dofs.reserve (max_dofs_per_face(dof));
+
+    typename DH<dim,spacedim>::active_cell_iterator
+    cell = dof.begin_active(),
+    endc = dof.end();
+    for (; cell!=endc; ++cell)
+      if (!cell->is_artificial())
+        for (unsigned int face_no = 0; face_no < GeometryInfo<dim>::faces_per_cell;
+             ++face_no)
+          {
+            const FiniteElement<dim,spacedim> &fe = cell->get_fe();
+
+            const typename DH<dim,spacedim>::face_iterator face = cell->face(face_no);
+
+            // if face is on the boundary and satisfies the correct
+            // boundary id property
+            if (face->at_boundary ()
+                &&
+                ((boundary_indicator == numbers::invalid_boundary_id)
+                 ||
+                 (face->boundary_indicator() == boundary_indicator)))
+              {
+                // get indices and physical location on this face
+                face_dofs.resize (fe.dofs_per_face);
+                face->get_dof_indices (face_dofs, cell->active_fe_index());
+
+                // enter those dofs into the list that match the component
+                // signature.
+                for (unsigned int i=0; i<face_dofs.size(); ++i)
+                  {
+                    // Find out if a dof has a contribution in this
+                    // component, and if so, add it to the list
+                    const ComponentMask &nonzero_component_array
+                      = cell->get_fe().get_nonzero_components (i);
+                    bool nonzero = false;
+                    for (unsigned int c=0; c<n_components; ++c)
+                      if (nonzero_component_array[c] && component_mask[c])
+                        {
+                          nonzero = true;
+                          break;
+                        }
+
+                    if (nonzero)
+                      zero_boundary_constraints.add_line (face_dofs[i]);
+                  }
+              }
+          }
+  }
+
+
+
+  template <int dim, int spacedim, template <int,int> class DH>
+  void
+  make_zero_boundary_constraints (const DH<dim, spacedim> &dof,
+                                  ConstraintMatrix        &zero_boundary_constraints,
+                                  const ComponentMask     &component_mask)
+  {
+    make_zero_boundary_constraints(dof, numbers::invalid_boundary_id,
+                                   zero_boundary_constraints, component_mask);
+  }
+
+
+} // end of namespace DoFTools
+
+
+
+// explicit instantiations
+
+#include "dof_tools_constraints.inst"
+
+
+
+DEAL_II_NAMESPACE_CLOSE
diff --git a/deal.II/source/dofs/dof_tools_constraints.inst.in b/deal.II/source/dofs/dof_tools_constraints.inst.in
new file mode 100644 (file)
index 0000000..28b9fc8
--- /dev/null
@@ -0,0 +1,134 @@
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2009 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+
+for (DH : DOFHANDLERS; deal_II_dimension : DIMENSIONS)
+{
+  template
+  void
+  DoFTools::make_hanging_node_constraints (const DH &dof_handler,
+                                           ConstraintMatrix &constraints);
+
+#if deal_II_dimension != 1
+  template
+  void
+  DoFTools::make_periodicity_constraints (const DH::face_iterator &,
+                                          const DH::face_iterator &,
+                                          dealii::ConstraintMatrix &,
+                                          const ComponentMask &,
+                                          bool, bool, bool);
+
+  template
+  void
+  DoFTools::make_periodicity_constraints(const DH &,
+                                         const types::boundary_id,
+                                         const types::boundary_id,
+                                         const int,
+                                         dealii::ConstraintMatrix &,
+                                         const ComponentMask &);
+
+  template
+  void
+  DoFTools::make_periodicity_constraints(const DH &,
+                                         const types::boundary_id,
+                                         const types::boundary_id,
+                                         const int,
+                                         dealii::Tensor<1,DH::space_dimension> &,
+                                         dealii::ConstraintMatrix &,
+                                         const ComponentMask &);
+
+  template
+  void
+  DoFTools::make_periodicity_constraints(const DH &,
+                                         const types::boundary_id,
+                                         const int,
+                                         dealii::ConstraintMatrix &,
+                                         const ComponentMask &);
+
+  template
+  void
+  DoFTools::make_periodicity_constraints(const DH &,
+                                         const types::boundary_id,
+                                         const int,
+                                         dealii::Tensor<1,DH::space_dimension> &,
+                                         dealii::ConstraintMatrix &,
+                                         const ComponentMask &);
+#endif
+}
+
+for (deal_II_dimension : DIMENSIONS)
+{
+#if deal_II_dimension != 1
+  template
+  void
+  DoFTools::make_hanging_node_constraints (const MGDoFHandler<deal_II_dimension> &dof_handler,
+                                           ConstraintMatrix &constraints);
+
+#endif
+ }
+
+
+for (deal_II_dimension : DIMENSIONS)
+{
+#if deal_II_dimension < 3
+template
+void
+DoFTools::
+make_hanging_node_constraints (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_handler,
+                               ConstraintMatrix &constraints);
+#endif
+
+#if deal_II_dimension == 3
+template
+void
+DoFTools::
+make_hanging_node_constraints (const DoFHandler<1,3> &dof_handler,
+                               ConstraintMatrix &constraints);
+#endif
+
+template
+void
+DoFTools::make_zero_boundary_constraints
+(const DoFHandler<deal_II_dimension> &,
+ ConstraintMatrix                    &,
+ const ComponentMask             &);
+
+template
+void
+DoFTools::make_zero_boundary_constraints
+(const DoFHandler<deal_II_dimension> &,
+ const types::boundary_id          ,
+ ConstraintMatrix                    &,
+ const ComponentMask             &);
+
+template
+void
+DoFTools::make_zero_boundary_constraints
+(const hp::DoFHandler<deal_II_dimension> &,
+ ConstraintMatrix                        &,
+ const ComponentMask                 &);
+
+template
+void
+DoFTools::make_zero_boundary_constraints
+(const hp::DoFHandler<deal_II_dimension> &,
+ const types::boundary_id          ,
+ ConstraintMatrix                        &,
+ const ComponentMask                 &);
+
+}
diff --git a/deal.II/source/dofs/dof_tools_sparsity.cc b/deal.II/source/dofs/dof_tools_sparsity.cc
new file mode 100644 (file)
index 0000000..c48bf2f
--- /dev/null
@@ -0,0 +1,1179 @@
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 1999 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/base/multithread_info.h>
+#include <deal.II/base/thread_management.h>
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/table.h>
+#include <deal.II/base/template_constraints.h>
+#include <deal.II/base/utilities.h>
+#include <deal.II/lac/sparsity_pattern.h>
+#include <deal.II/lac/compressed_sparsity_pattern.h>
+#include <deal.II/lac/compressed_set_sparsity_pattern.h>
+#include <deal.II/lac/compressed_simple_sparsity_pattern.h>
+#include <deal.II/lac/trilinos_sparsity_pattern.h>
+#include <deal.II/lac/block_sparsity_pattern.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/intergrid_map.h>
+#include <deal.II/grid/grid_tools.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/fe/fe.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/fe/fe_tools.h>
+#include <deal.II/hp/fe_collection.h>
+#include <deal.II/hp/q_collection.h>
+#include <deal.II/hp/fe_values.h>
+#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/numerics/vector_tools.h>
+
+#include <deal.II/multigrid/mg_dof_handler.h>
+
+#include <algorithm>
+#include <numeric>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+
+namespace DoFTools
+{
+
+  template <class DH, class SparsityPattern>
+  void
+  make_sparsity_pattern (const DH               &dof,
+                         SparsityPattern        &sparsity,
+                         const ConstraintMatrix &constraints,
+                         const bool              keep_constrained_dofs,
+                         const types::subdomain_id subdomain_id)
+  {
+    const types::global_dof_index n_dofs = dof.n_dofs();
+
+    Assert (sparsity.n_rows() == n_dofs,
+            ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
+    Assert (sparsity.n_cols() == n_dofs,
+            ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
+
+    // If we have a distributed::Triangulation only allow locally_owned
+    // subdomain. Not setting a subdomain is also okay, because we skip
+    // ghost cells in the loop below.
+    Assert (
+      (dof.get_tria().locally_owned_subdomain() == numbers::invalid_subdomain_id)
+      ||
+      (subdomain_id == numbers::invalid_subdomain_id)
+      ||
+      (subdomain_id == dof.get_tria().locally_owned_subdomain()),
+      ExcMessage ("For parallel::distributed::Triangulation objects and "
+                  "associated DoF handler objects, asking for any subdomain other "
+                  "than the locally owned one does not make sense."));
+
+    std::vector<types::global_dof_index> dofs_on_this_cell;
+    dofs_on_this_cell.reserve (max_dofs_per_cell(dof));
+    typename DH::active_cell_iterator cell = dof.begin_active(),
+                                      endc = dof.end();
+
+    // In case we work with a distributed sparsity pattern of Trilinos
+    // type, we only have to do the work if the current cell is owned by
+    // the calling processor. Otherwise, just continue.
+    for (; cell!=endc; ++cell)
+      if (((subdomain_id == numbers::invalid_subdomain_id)
+           ||
+           (subdomain_id == cell->subdomain_id()))
+          &&
+          cell->is_locally_owned())
+        {
+          const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
+          dofs_on_this_cell.resize (dofs_per_cell);
+          cell->get_dof_indices (dofs_on_this_cell);
+
+          // make sparsity pattern for this cell. if no constraints pattern
+          // was given, then the following call acts as if simply no
+          // constraints existed
+          constraints.add_entries_local_to_global (dofs_on_this_cell,
+                                                   sparsity,
+                                                   keep_constrained_dofs);
+        }
+  }
+
+
+
+  template <class DH, class SparsityPattern>
+  void
+  make_sparsity_pattern (const DH                &dof,
+                         const Table<2,Coupling> &couplings,
+                         SparsityPattern         &sparsity,
+                         const ConstraintMatrix  &constraints,
+                         const bool               keep_constrained_dofs,
+                         const types::subdomain_id subdomain_id)
+  {
+    const types::global_dof_index n_dofs = dof.n_dofs();
+
+    Assert (sparsity.n_rows() == n_dofs,
+            ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
+    Assert (sparsity.n_cols() == n_dofs,
+            ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
+    Assert (couplings.n_rows() == dof.get_fe().n_components(),
+            ExcDimensionMismatch(couplings.n_rows(), dof.get_fe().n_components()));
+    Assert (couplings.n_cols() == dof.get_fe().n_components(),
+            ExcDimensionMismatch(couplings.n_cols(), dof.get_fe().n_components()));
+
+    // If we have a distributed::Triangulation only allow locally_owned
+    // subdomain. Not setting a subdomain is also okay, because we skip
+    // ghost cells in the loop below.
+    Assert (
+      (dof.get_tria().locally_owned_subdomain() == numbers::invalid_subdomain_id)
+      ||
+      (subdomain_id == numbers::invalid_subdomain_id)
+      ||
+      (subdomain_id == dof.get_tria().locally_owned_subdomain()),
+      ExcMessage ("For parallel::distributed::Triangulation objects and "
+                  "associated DoF handler objects, asking for any subdomain other "
+                  "than the locally owned one does not make sense."));
+
+    const hp::FECollection<DH::dimension,DH::space_dimension> fe_collection (dof.get_fe());
+
+    // first, for each finite element, build a mask for each dof, not like
+    // the one given which represents components. make sure we do the right
+    // thing also with respect to non-primitive shape functions, which
+    // takes some additional thought
+    std::vector<Table<2,bool> > dof_mask(fe_collection.size());
+
+    // check whether the table of couplings contains only true arguments,
+    // i.e., we do not exclude any index. that is the easy case, since we
+    // don't have to set up the tables
+    bool need_dof_mask = false;
+    for (unsigned int i=0; i<couplings.n_rows(); ++i)
+      for (unsigned int j=0; j<couplings.n_cols(); ++j)
+        if (couplings(i,j) == none)
+          need_dof_mask = true;
+
+    if (need_dof_mask == true)
+      for (unsigned int f=0; f<fe_collection.size(); ++f)
+        {
+          const unsigned int dofs_per_cell = fe_collection[f].dofs_per_cell;
+
+          dof_mask[f].reinit (dofs_per_cell, dofs_per_cell);
+
+          for (unsigned int i=0; i<dofs_per_cell; ++i)
+            for (unsigned int j=0; j<dofs_per_cell; ++j)
+              if (fe_collection[f].is_primitive(i) &&
+                  fe_collection[f].is_primitive(j))
+                dof_mask[f](i,j)
+                  = (couplings(fe_collection[f].system_to_component_index(i).first,
+                               fe_collection[f].system_to_component_index(j).first) != none);
+              else
+                {
+                  const unsigned int first_nonzero_comp_i
+                    = fe_collection[f].get_nonzero_components(i).first_selected_component();
+                  const unsigned int first_nonzero_comp_j
+                    = fe_collection[f].get_nonzero_components(j).first_selected_component();
+                  Assert (first_nonzero_comp_i < fe_collection[f].n_components(),
+                          ExcInternalError());
+                  Assert (first_nonzero_comp_j < fe_collection[f].n_components(),
+                          ExcInternalError());
+
+                  dof_mask[f](i,j)
+                    = (couplings(first_nonzero_comp_i,first_nonzero_comp_j) != none);
+                }
+        }
+
+
+    std::vector<types::global_dof_index> dofs_on_this_cell(fe_collection.max_dofs_per_cell());
+    typename DH::active_cell_iterator cell = dof.begin_active(),
+                                      endc = dof.end();
+
+    // In case we work with a distributed sparsity pattern of Trilinos
+    // type, we only have to do the work if the current cell is owned by
+    // the calling processor. Otherwise, just continue.
+    for (; cell!=endc; ++cell)
+      if (((subdomain_id == numbers::invalid_subdomain_id)
+           ||
+           (subdomain_id == cell->subdomain_id()))
+          &&
+          cell->is_locally_owned())
+        {
+          const unsigned int fe_index = cell->active_fe_index();
+          const unsigned int dofs_per_cell =fe_collection[fe_index].dofs_per_cell;
+
+          dofs_on_this_cell.resize (dofs_per_cell);
+          cell->get_dof_indices (dofs_on_this_cell);
+
+
+          // make sparsity pattern for this cell. if no constraints pattern
+          // was given, then the following call acts as if simply no
+          // constraints existed
+          constraints.add_entries_local_to_global (dofs_on_this_cell,
+                                                   sparsity,
+                                                   keep_constrained_dofs,
+                                                   dof_mask[fe_index]);
+        }
+  }
+
+
+
+  template <class DH, class SparsityPattern>
+  void
+  make_sparsity_pattern (
+    const DH        &dof_row,
+    const DH        &dof_col,
+    SparsityPattern &sparsity)
+  {
+    const types::global_dof_index n_dofs_row = dof_row.n_dofs();
+    const types::global_dof_index n_dofs_col = dof_col.n_dofs();
+
+    Assert (sparsity.n_rows() == n_dofs_row,
+            ExcDimensionMismatch (sparsity.n_rows(), n_dofs_row));
+    Assert (sparsity.n_cols() == n_dofs_col,
+            ExcDimensionMismatch (sparsity.n_cols(), n_dofs_col));
+
+//TODO: Looks like wasteful memory management here
+
+    const std::list<std::pair<typename DH::cell_iterator,
+          typename DH::cell_iterator> >
+          cell_list
+          = GridTools::get_finest_common_cells (dof_row, dof_col);
+
+
+    typename std::list<std::pair<typename DH::cell_iterator,
+             typename DH::cell_iterator> >::const_iterator
+             cell_iter = cell_list.begin();
+
+    for (; cell_iter!=cell_list.end(); ++cell_iter)
+      {
+        const typename DH::cell_iterator cell_row = cell_iter->first;
+        const typename DH::cell_iterator cell_col = cell_iter->second;
+
+        if (!cell_row->has_children() && !cell_col->has_children())
+          {
+            const unsigned int dofs_per_cell_row =
+              cell_row->get_fe().dofs_per_cell;
+            const unsigned int dofs_per_cell_col =
+              cell_col->get_fe().dofs_per_cell;
+            std::vector<types::global_dof_index>
+            local_dof_indices_row(dofs_per_cell_row);
+            std::vector<types::global_dof_index>
+            local_dof_indices_col(dofs_per_cell_col);
+            cell_row->get_dof_indices (local_dof_indices_row);
+            cell_col->get_dof_indices (local_dof_indices_col);
+            for (unsigned int i=0; i<dofs_per_cell_row; ++i)
+              sparsity.add_entries (local_dof_indices_row[i],
+                                    local_dof_indices_col.begin(),
+                                    local_dof_indices_col.end());
+          }
+        else if (cell_row->has_children())
+          {
+            const std::vector<typename DH::active_cell_iterator >
+            child_cells = GridTools::get_active_child_cells<DH> (cell_row);
+            for (unsigned int i=0; i<child_cells.size(); i++)
+              {
+                const typename DH::cell_iterator
+                cell_row_child = child_cells[i];
+                const unsigned int dofs_per_cell_row =
+                  cell_row_child->get_fe().dofs_per_cell;
+                const unsigned int dofs_per_cell_col =
+                  cell_col->get_fe().dofs_per_cell;
+                std::vector<types::global_dof_index>
+                local_dof_indices_row(dofs_per_cell_row);
+                std::vector<types::global_dof_index>
+                local_dof_indices_col(dofs_per_cell_col);
+                cell_row_child->get_dof_indices (local_dof_indices_row);
+                cell_col->get_dof_indices (local_dof_indices_col);
+                for (unsigned int i=0; i<dofs_per_cell_row; ++i)
+                  sparsity.add_entries (local_dof_indices_row[i],
+                                        local_dof_indices_col.begin(),
+                                        local_dof_indices_col.end());
+              }
+          }
+        else
+          {
+            std::vector<typename DH::active_cell_iterator>
+            child_cells = GridTools::get_active_child_cells<DH> (cell_col);
+            for (unsigned int i=0; i<child_cells.size(); i++)
+              {
+                const typename DH::active_cell_iterator
+                cell_col_child = child_cells[i];
+                const unsigned int dofs_per_cell_row =
+                  cell_row->get_fe().dofs_per_cell;
+                const unsigned int dofs_per_cell_col =
+                  cell_col_child->get_fe().dofs_per_cell;
+                std::vector<types::global_dof_index>
+                local_dof_indices_row(dofs_per_cell_row);
+                std::vector<types::global_dof_index>
+                local_dof_indices_col(dofs_per_cell_col);
+                cell_row->get_dof_indices (local_dof_indices_row);
+                cell_col_child->get_dof_indices (local_dof_indices_col);
+                for (unsigned int i=0; i<dofs_per_cell_row; ++i)
+                  sparsity.add_entries (local_dof_indices_row[i],
+                                        local_dof_indices_col.begin(),
+                                        local_dof_indices_col.end());
+              }
+          }
+      }
+  }
+
+
+
+  template <class DH, class SparsityPattern>
+  void
+  make_boundary_sparsity_pattern (
+    const DH                        &dof,
+    const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
+    SparsityPattern                 &sparsity)
+  {
+    if (DH::dimension == 1)
+      {
+        // there are only 2 boundary indicators in 1d, so it is no
+        // performance problem to call the other function
+        typename DH::FunctionMap boundary_indicators;
+        boundary_indicators[0] = 0;
+        boundary_indicators[1] = 0;
+        make_boundary_sparsity_pattern<DH, SparsityPattern> (dof,
+                                                             boundary_indicators,
+                                                             dof_to_boundary_mapping,
+                                                             sparsity);
+        return;
+      }
+
+    const types::global_dof_index n_dofs = dof.n_dofs();
+
+    AssertDimension (dof_to_boundary_mapping.size(), n_dofs);
+    AssertDimension (sparsity.n_rows(), dof.n_boundary_dofs());
+    AssertDimension (sparsity.n_cols(), dof.n_boundary_dofs());
+#ifdef DEBUG
+    if (sparsity.n_rows() != 0)
+      {
+        types::global_dof_index max_element = 0;
+        for (std::vector<types::global_dof_index>::const_iterator i=dof_to_boundary_mapping.begin();
+             i!=dof_to_boundary_mapping.end(); ++i)
+          if ((*i != DH::invalid_dof_index) &&
+              (*i > max_element))
+            max_element = *i;
+        AssertDimension (max_element, sparsity.n_rows()-1);
+      };
+#endif
+
+    std::vector<types::global_dof_index> dofs_on_this_face;
+    dofs_on_this_face.reserve (max_dofs_per_face(dof));
+
+    // loop over all faces to check whether they are at a boundary. note
+    // that we need not take special care of single lines (using
+    // @p{cell->has_boundary_lines}), since we do not support boundaries of
+    // dimension dim-2, and so every boundary line is also part of a
+    // boundary face.
+    typename DH::active_cell_iterator cell = dof.begin_active(),
+                                      endc = dof.end();
+    for (; cell!=endc; ++cell)
+      for (unsigned int f=0; f<GeometryInfo<DH::dimension>::faces_per_cell; ++f)
+        if (cell->at_boundary(f))
+          {
+            const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
+            dofs_on_this_face.resize (dofs_per_face);
+            cell->face(f)->get_dof_indices (dofs_on_this_face,
+                                            cell->active_fe_index());
+
+            // make sparsity pattern for this cell
+            for (unsigned int i=0; i<dofs_per_face; ++i)
+              for (unsigned int j=0; j<dofs_per_face; ++j)
+                sparsity.add (dof_to_boundary_mapping[dofs_on_this_face[i]],
+                              dof_to_boundary_mapping[dofs_on_this_face[j]]);
+          }
+  }
+
+
+
+  template <class DH, class SparsityPattern>
+  void make_boundary_sparsity_pattern (
+    const DH                                        &dof,
+    const typename FunctionMap<DH::space_dimension>::type &boundary_indicators,
+    const std::vector<types::global_dof_index>                 &dof_to_boundary_mapping,
+    SparsityPattern                                 &sparsity)
+  {
+    if (DH::dimension == 1)
+      {
+        // first check left, then right boundary point
+        for (unsigned int direction=0; direction<2; ++direction)
+          {
+            // if this boundary is not requested, then go on with next one
+            if (boundary_indicators.find(direction) ==
+                boundary_indicators.end())
+              continue;
+
+            // find active cell at that boundary: first go to left/right,
+            // then to children
+            typename DH::level_cell_iterator cell = dof.begin(0);
+            while (!cell->at_boundary(direction))
+              cell = cell->neighbor(direction);
+            while (!cell->active())
+              cell = cell->child(direction);
+
+            const unsigned int dofs_per_vertex = cell->get_fe().dofs_per_vertex;
+            std::vector<types::global_dof_index> boundary_dof_boundary_indices (dofs_per_vertex);
+
+            // next get boundary mapped dof indices of boundary dofs
+            for (unsigned int i=0; i<dofs_per_vertex; ++i)
+              boundary_dof_boundary_indices[i]
+                = dof_to_boundary_mapping[cell->vertex_dof_index(direction,i)];
+
+            for (unsigned int i=0; i<dofs_per_vertex; ++i)
+              sparsity.add_entries (boundary_dof_boundary_indices[i],
+                                    boundary_dof_boundary_indices.begin(),
+                                    boundary_dof_boundary_indices.end());
+          };
+        return;
+      }
+
+    const types::global_dof_index n_dofs = dof.n_dofs();
+
+    AssertDimension (dof_to_boundary_mapping.size(), n_dofs);
+    Assert (boundary_indicators.find(numbers::internal_face_boundary_id) == boundary_indicators.end(),
+            typename DH::ExcInvalidBoundaryIndicator());
+    Assert (sparsity.n_rows() == dof.n_boundary_dofs (boundary_indicators),
+            ExcDimensionMismatch (sparsity.n_rows(), dof.n_boundary_dofs (boundary_indicators)));
+    Assert (sparsity.n_cols() == dof.n_boundary_dofs (boundary_indicators),
+            ExcDimensionMismatch (sparsity.n_cols(), dof.n_boundary_dofs (boundary_indicators)));
+#ifdef DEBUG
+    if (sparsity.n_rows() != 0)
+      {
+        types::global_dof_index max_element = 0;
+        for (std::vector<types::global_dof_index>::const_iterator i=dof_to_boundary_mapping.begin();
+             i!=dof_to_boundary_mapping.end(); ++i)
+          if ((*i != DH::invalid_dof_index) &&
+              (*i > max_element))
+            max_element = *i;
+        AssertDimension (max_element, sparsity.n_rows()-1);
+      };
+#endif
+
+    std::vector<types::global_dof_index> dofs_on_this_face;
+    dofs_on_this_face.reserve (max_dofs_per_face(dof));
+    typename DH::active_cell_iterator cell = dof.begin_active(),
+                                      endc = dof.end();
+    for (; cell!=endc; ++cell)
+      for (unsigned int f=0; f<GeometryInfo<DH::dimension>::faces_per_cell; ++f)
+        if (boundary_indicators.find(cell->face(f)->boundary_indicator()) !=
+            boundary_indicators.end())
+          {
+            const unsigned int dofs_per_face = cell->get_fe().dofs_per_face;
+            dofs_on_this_face.resize (dofs_per_face);
+            cell->face(f)->get_dof_indices (dofs_on_this_face,
+                                            cell->active_fe_index());
+
+            // make sparsity pattern for this cell
+            for (unsigned int i=0; i<dofs_per_face; ++i)
+              for (unsigned int j=0; j<dofs_per_face; ++j)
+                sparsity.add (dof_to_boundary_mapping[dofs_on_this_face[i]],
+                              dof_to_boundary_mapping[dofs_on_this_face[j]]);
+          }
+  }
+
+
+
+  template <class DH, class SparsityPattern>
+  void
+  make_flux_sparsity_pattern (const DH                  &dof,
+                              SparsityPattern           &sparsity,
+                              const ConstraintMatrix    &constraints,
+                              const bool                keep_constrained_dofs,
+                              const types::subdomain_id subdomain_id)
+
+  // TODO: QA: reduce the indentation level of this method..., Maier 2012
+
+  {
+    const types::global_dof_index n_dofs = dof.n_dofs();
+
+    AssertDimension (sparsity.n_rows(), n_dofs);
+    AssertDimension (sparsity.n_cols(), n_dofs);
+
+    // If we have a distributed::Triangulation only allow locally_owned
+    // subdomain. Not setting a subdomain is also okay, because we skip
+    // ghost cells in the loop below.
+    Assert (
+      (dof.get_tria().locally_owned_subdomain() == numbers::invalid_subdomain_id)
+      ||
+      (subdomain_id == numbers::invalid_subdomain_id)
+      ||
+      (subdomain_id == dof.get_tria().locally_owned_subdomain()),
+      ExcMessage ("For parallel::distributed::Triangulation objects and "
+                  "associated DoF handler objects, asking for any subdomain other "
+                  "than the locally owned one does not make sense."));
+
+    std::vector<types::global_dof_index> dofs_on_this_cell;
+    std::vector<types::global_dof_index> dofs_on_other_cell;
+    dofs_on_this_cell.reserve (max_dofs_per_cell(dof));
+    dofs_on_other_cell.reserve (max_dofs_per_cell(dof));
+    typename DH::active_cell_iterator cell = dof.begin_active(),
+                                      endc = dof.end();
+
+    // TODO: in an old implementation, we used user flags before to tag
+    // faces that were already touched. this way, we could reduce the work
+    // a little bit. now, we instead add only data from one side. this
+    // should be OK, but we need to actually verify it.
+
+    // In case we work with a distributed sparsity pattern of Trilinos
+    // type, we only have to do the work if the current cell is owned by
+    // the calling processor. Otherwise, just continue.
+    for (; cell!=endc; ++cell)
+      if (((subdomain_id == numbers::invalid_subdomain_id)
+           ||
+           (subdomain_id == cell->subdomain_id()))
+          &&
+          cell->is_locally_owned())
+        {
+          const unsigned int n_dofs_on_this_cell = cell->get_fe().dofs_per_cell;
+          dofs_on_this_cell.resize (n_dofs_on_this_cell);
+          cell->get_dof_indices (dofs_on_this_cell);
+
+          // make sparsity pattern for this cell. if no constraints pattern
+          // was given, then the following call acts as if simply no
+          // constraints existed
+          constraints.add_entries_local_to_global (dofs_on_this_cell,
+                                                   sparsity,
+                                                   keep_constrained_dofs);
+
+          for (unsigned int face = 0;
+               face < GeometryInfo<DH::dimension>::faces_per_cell;
+               ++face)
+            {
+              typename DH::face_iterator cell_face = cell->face(face);
+              if (! cell->at_boundary(face) )
+                {
+                  typename DH::level_cell_iterator neighbor = cell->neighbor(face);
+
+                  // in 1d, we do not need to worry whether the neighbor
+                  // might have children and then loop over those children.
+                  // rather, we may as well go straight to to cell behind
+                  // this particular cell's most terminal child
+                  if (DH::dimension==1)
+                    while (neighbor->has_children())
+                      neighbor = neighbor->child(face==0 ? 1 : 0);
+
+                  if (neighbor->has_children())
+                    {
+                      for (unsigned int sub_nr = 0;
+                           sub_nr != cell_face->number_of_children();
+                           ++sub_nr)
+                        {
+                          const typename DH::level_cell_iterator
+                          sub_neighbor
+                            = cell->neighbor_child_on_subface (face, sub_nr);
+
+                          const unsigned int n_dofs_on_neighbor
+                            = sub_neighbor->get_fe().dofs_per_cell;
+                          dofs_on_other_cell.resize (n_dofs_on_neighbor);
+                          sub_neighbor->get_dof_indices (dofs_on_other_cell);
+
+                          constraints.add_entries_local_to_global
+                          (dofs_on_this_cell, dofs_on_other_cell,
+                           sparsity, keep_constrained_dofs);
+                          constraints.add_entries_local_to_global
+                          (dofs_on_other_cell, dofs_on_this_cell,
+                           sparsity, keep_constrained_dofs);
+                        }
+                    }
+                  else
+                    {
+                      // Refinement edges are taken care of by coarser
+                      // cells
+
+                      // TODO: in the distributed case, we miss out the
+                      // constraints when the neighbor cell is coarser, but
+                      // only the current cell is owned locally!
+                      if (cell->neighbor_is_coarser(face))
+                        continue;
+
+                      const unsigned int n_dofs_on_neighbor
+                        = neighbor->get_fe().dofs_per_cell;
+                      dofs_on_other_cell.resize (n_dofs_on_neighbor);
+
+                      neighbor->get_dof_indices (dofs_on_other_cell);
+
+                      constraints.add_entries_local_to_global
+                      (dofs_on_this_cell, dofs_on_other_cell,
+                       sparsity, keep_constrained_dofs);
+
+                      // only need to add these in case the neighbor cell
+                      // is not locally owned - otherwise, we touch each
+                      // face twice and hence put the indices the other way
+                      // around
+                      if (!cell->neighbor(face)->active()
+                          ||
+                          (cell->neighbor(face)->subdomain_id() !=
+                           cell->subdomain_id()))
+                        constraints.add_entries_local_to_global
+                        (dofs_on_other_cell, dofs_on_this_cell,
+                         sparsity, keep_constrained_dofs);
+                    }
+                }
+            }
+        }
+  }
+
+
+
+  template <class DH, class SparsityPattern>
+  void
+  make_flux_sparsity_pattern (const DH        &dof,
+                              SparsityPattern &sparsity)
+  {
+    ConstraintMatrix constraints;
+    make_flux_sparsity_pattern (dof, sparsity, constraints);
+  }
+
+  template <int dim, int spacedim>
+  Table<2,Coupling>
+  dof_couplings_from_component_couplings (const FiniteElement<dim,spacedim> &fe,
+                                          const Table<2,Coupling> &component_couplings)
+  {
+    Assert(component_couplings.n_rows() == fe.n_components(),
+           ExcDimensionMismatch(component_couplings.n_rows(),
+                                fe.n_components()));
+    Assert(component_couplings.n_cols() == fe.n_components(),
+           ExcDimensionMismatch(component_couplings.n_cols(),
+                                fe.n_components()));
+
+    const unsigned int n_dofs = fe.dofs_per_cell;
+
+    Table<2,Coupling> dof_couplings (n_dofs, n_dofs);
+
+    for (unsigned int i=0; i<n_dofs; ++i)
+      {
+        const unsigned int ii
+          = (fe.is_primitive(i) ?
+             fe.system_to_component_index(i).first
+             :
+             fe.get_nonzero_components(i).first_selected_component()
+            );
+        Assert (ii < fe.n_components(), ExcInternalError());
+
+        for (unsigned int j=0; j<n_dofs; ++j)
+          {
+            const unsigned int jj
+              = (fe.is_primitive(j) ?
+                 fe.system_to_component_index(j).first
+                 :
+                 fe.get_nonzero_components(j).first_selected_component()
+                );
+            Assert (jj < fe.n_components(), ExcInternalError());
+
+            dof_couplings(i,j) = component_couplings(ii,jj);
+          }
+      }
+    return dof_couplings;
+  }
+
+
+
+  template <int dim, int spacedim>
+  std::vector<Table<2,Coupling> >
+  dof_couplings_from_component_couplings
+  (const hp::FECollection<dim,spacedim> &fe,
+   const Table<2,Coupling> &component_couplings)
+  {
+    std::vector<Table<2,Coupling> > return_value (fe.size());
+    for (unsigned int i=0; i<fe.size(); ++i)
+      return_value[i]
+        = dof_couplings_from_component_couplings(fe[i], component_couplings);
+
+    return return_value;
+  }
+
+
+
+  namespace internal
+  {
+    namespace
+    {
+
+      // implementation of the same function in namespace DoFTools for
+      // non-hp DoFHandlers
+      template <class DH, class SparsityPattern>
+      void
+      make_flux_sparsity_pattern (const DH                &dof,
+                                  SparsityPattern         &sparsity,
+                                  const Table<2,Coupling> &int_mask,
+                                  const Table<2,Coupling> &flux_mask)
+      {
+        const FiniteElement<DH::dimension,DH::space_dimension> &fe = dof.get_fe();
+
+        std::vector<types::global_dof_index> dofs_on_this_cell(fe.dofs_per_cell);
+        std::vector<types::global_dof_index> dofs_on_other_cell(fe.dofs_per_cell);
+
+        const Table<2,Coupling>
+        int_dof_mask  = dof_couplings_from_component_couplings(fe, int_mask),
+        flux_dof_mask = dof_couplings_from_component_couplings(fe, flux_mask);
+
+        Table<2,bool> support_on_face(fe.dofs_per_cell,
+                                      GeometryInfo<DH::dimension>::faces_per_cell);
+        for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
+          for (unsigned int f=0; f<GeometryInfo<DH::dimension>::faces_per_cell; ++f)
+            support_on_face(i,f) = fe.has_support_on_face(i,f);
+
+        typename DH::active_cell_iterator cell = dof.begin_active(),
+                                          endc = dof.end();
+        for (; cell!=endc; ++cell)
+          if (cell->is_locally_owned())
+            {
+              cell->get_dof_indices (dofs_on_this_cell);
+              // make sparsity pattern for this cell
+              for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
+                for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
+                  if (int_dof_mask(i,j) != none)
+                    sparsity.add (dofs_on_this_cell[i],
+                                  dofs_on_this_cell[j]);
+
+              // Loop over all interior neighbors
+              for (unsigned int face = 0;
+                   face < GeometryInfo<DH::dimension>::faces_per_cell;
+                   ++face)
+                {
+                  const typename DH::face_iterator
+                  cell_face = cell->face(face);
+                  if (cell_face->user_flag_set ())
+                    continue;
+
+                  if (cell->at_boundary (face) )
+                    {
+                      for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
+                        {
+                          const bool i_non_zero_i = support_on_face (i, face);
+                          for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
+                            {
+                              const bool j_non_zero_i = support_on_face (j, face);
+
+                              if ((flux_dof_mask(i,j) == always)
+                                  ||
+                                  (flux_dof_mask(i,j) == nonzero
+                                   &&
+                                   i_non_zero_i
+                                   &&
+                                   j_non_zero_i))
+                                sparsity.add (dofs_on_this_cell[i],
+                                              dofs_on_this_cell[j]);
+                            }
+                        }
+                    }
+                  else
+                    {
+                      typename DH::level_cell_iterator
+                      neighbor = cell->neighbor(face);
+                      // Refinement edges are taken care of by coarser
+                      // cells
+                      if (cell->neighbor_is_coarser(face))
+                        continue;
+
+                      typename DH::face_iterator cell_face = cell->face(face);
+                      const unsigned int
+                      neighbor_face = cell->neighbor_of_neighbor(face);
+
+                      if (cell_face->has_children())
+                        {
+                          for (unsigned int sub_nr = 0;
+                               sub_nr != cell_face->n_children();
+                               ++sub_nr)
+                            {
+                              const typename DH::level_cell_iterator
+                              sub_neighbor
+                                = cell->neighbor_child_on_subface (face, sub_nr);
+
+                              sub_neighbor->get_dof_indices (dofs_on_other_cell);
+                              for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
+                                {
+                                  const bool i_non_zero_i = support_on_face (i, face);
+                                  const bool i_non_zero_e = support_on_face (i, neighbor_face);
+                                  for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
+                                    {
+                                      const bool j_non_zero_i = support_on_face (j, face);
+                                      const bool j_non_zero_e = support_on_face (j, neighbor_face);
+
+                                      if (flux_dof_mask(i,j) == always)
+                                        {
+                                          sparsity.add (dofs_on_this_cell[i],
+                                                        dofs_on_other_cell[j]);
+                                          sparsity.add (dofs_on_other_cell[i],
+                                                        dofs_on_this_cell[j]);
+                                          sparsity.add (dofs_on_this_cell[i],
+                                                        dofs_on_this_cell[j]);
+                                          sparsity.add (dofs_on_other_cell[i],
+                                                        dofs_on_other_cell[j]);
+                                        }
+                                      else if (flux_dof_mask(i,j) == nonzero)
+                                        {
+                                          if (i_non_zero_i && j_non_zero_e)
+                                            sparsity.add (dofs_on_this_cell[i],
+                                                          dofs_on_other_cell[j]);
+                                          if (i_non_zero_e && j_non_zero_i)
+                                            sparsity.add (dofs_on_other_cell[i],
+                                                          dofs_on_this_cell[j]);
+                                          if (i_non_zero_i && j_non_zero_i)
+                                            sparsity.add (dofs_on_this_cell[i],
+                                                          dofs_on_this_cell[j]);
+                                          if (i_non_zero_e && j_non_zero_e)
+                                            sparsity.add (dofs_on_other_cell[i],
+                                                          dofs_on_other_cell[j]);
+                                        }
+
+                                      if (flux_dof_mask(j,i) == always)
+                                        {
+                                          sparsity.add (dofs_on_this_cell[j],
+                                                        dofs_on_other_cell[i]);
+                                          sparsity.add (dofs_on_other_cell[j],
+                                                        dofs_on_this_cell[i]);
+                                          sparsity.add (dofs_on_this_cell[j],
+                                                        dofs_on_this_cell[i]);
+                                          sparsity.add (dofs_on_other_cell[j],
+                                                        dofs_on_other_cell[i]);
+                                        }
+                                      else if (flux_dof_mask(j,i) == nonzero)
+                                        {
+                                          if (j_non_zero_i && i_non_zero_e)
+                                            sparsity.add (dofs_on_this_cell[j],
+                                                          dofs_on_other_cell[i]);
+                                          if (j_non_zero_e && i_non_zero_i)
+                                            sparsity.add (dofs_on_other_cell[j],
+                                                          dofs_on_this_cell[i]);
+                                          if (j_non_zero_i && i_non_zero_i)
+                                            sparsity.add (dofs_on_this_cell[j],
+                                                          dofs_on_this_cell[i]);
+                                          if (j_non_zero_e && i_non_zero_e)
+                                            sparsity.add (dofs_on_other_cell[j],
+                                                          dofs_on_other_cell[i]);
+                                        }
+                                    }
+                                }
+                              sub_neighbor->face(neighbor_face)->set_user_flag ();
+                            }
+                        }
+                      else
+                        {
+                          neighbor->get_dof_indices (dofs_on_other_cell);
+                          for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
+                            {
+                              const bool i_non_zero_i = support_on_face (i, face);
+                              const bool i_non_zero_e = support_on_face (i, neighbor_face);
+                              for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
+                                {
+                                  const bool j_non_zero_i = support_on_face (j, face);
+                                  const bool j_non_zero_e = support_on_face (j, neighbor_face);
+                                  if (flux_dof_mask(i,j) == always)
+                                    {
+                                      sparsity.add (dofs_on_this_cell[i],
+                                                    dofs_on_other_cell[j]);
+                                      sparsity.add (dofs_on_other_cell[i],
+                                                    dofs_on_this_cell[j]);
+                                      sparsity.add (dofs_on_this_cell[i],
+                                                    dofs_on_this_cell[j]);
+                                      sparsity.add (dofs_on_other_cell[i],
+                                                    dofs_on_other_cell[j]);
+                                    }
+                                  if (flux_dof_mask(i,j) == nonzero)
+                                    {
+                                      if (i_non_zero_i && j_non_zero_e)
+                                        sparsity.add (dofs_on_this_cell[i],
+                                                      dofs_on_other_cell[j]);
+                                      if (i_non_zero_e && j_non_zero_i)
+                                        sparsity.add (dofs_on_other_cell[i],
+                                                      dofs_on_this_cell[j]);
+                                      if (i_non_zero_i && j_non_zero_i)
+                                        sparsity.add (dofs_on_this_cell[i],
+                                                      dofs_on_this_cell[j]);
+                                      if (i_non_zero_e && j_non_zero_e)
+                                        sparsity.add (dofs_on_other_cell[i],
+                                                      dofs_on_other_cell[j]);
+                                    }
+
+                                  if (flux_dof_mask(j,i) == always)
+                                    {
+                                      sparsity.add (dofs_on_this_cell[j],
+                                                    dofs_on_other_cell[i]);
+                                      sparsity.add (dofs_on_other_cell[j],
+                                                    dofs_on_this_cell[i]);
+                                      sparsity.add (dofs_on_this_cell[j],
+                                                    dofs_on_this_cell[i]);
+                                      sparsity.add (dofs_on_other_cell[j],
+                                                    dofs_on_other_cell[i]);
+                                    }
+                                  if (flux_dof_mask(j,i) == nonzero)
+                                    {
+                                      if (j_non_zero_i && i_non_zero_e)
+                                        sparsity.add (dofs_on_this_cell[j],
+                                                      dofs_on_other_cell[i]);
+                                      if (j_non_zero_e && i_non_zero_i)
+                                        sparsity.add (dofs_on_other_cell[j],
+                                                      dofs_on_this_cell[i]);
+                                      if (j_non_zero_i && i_non_zero_i)
+                                        sparsity.add (dofs_on_this_cell[j],
+                                                      dofs_on_this_cell[i]);
+                                      if (j_non_zero_e && i_non_zero_e)
+                                        sparsity.add (dofs_on_other_cell[j],
+                                                      dofs_on_other_cell[i]);
+                                    }
+                                }
+                            }
+                          neighbor->face(neighbor_face)->set_user_flag ();
+                        }
+                    }
+                }
+            }
+      }
+
+
+      // implementation of the same function in namespace DoFTools for
+      // non-hp DoFHandlers
+      template <int dim, int spacedim, class SparsityPattern>
+      void
+      make_flux_sparsity_pattern (const dealii::hp::DoFHandler<dim,spacedim> &dof,
+                                  SparsityPattern                           &sparsity,
+                                  const Table<2,Coupling> &int_mask,
+                                  const Table<2,Coupling> &flux_mask)
+      {
+        // while the implementation above is quite optimized and caches a
+        // lot of data (see e.g. the int/flux_dof_mask tables), this is no
+        // longer practical for the hp version since we would have to have
+        // it for all combinations of elements in the hp::FECollection.
+        // consequently, the implementation here is simpler and probably
+        // less efficient but at least readable...
+
+        const dealii::hp::FECollection<dim,spacedim> &fe = dof.get_fe();
+
+        std::vector<types::global_dof_index> dofs_on_this_cell(DoFTools::max_dofs_per_cell(dof));
+        std::vector<types::global_dof_index> dofs_on_other_cell(DoFTools::max_dofs_per_cell(dof));
+
+        const std::vector<Table<2,Coupling> >
+        int_dof_mask
+          = dof_couplings_from_component_couplings(fe, int_mask);
+
+        typename dealii::hp::DoFHandler<dim,spacedim>::active_cell_iterator
+        cell = dof.begin_active(),
+        endc = dof.end();
+        for (; cell!=endc; ++cell)
+          {
+            dofs_on_this_cell.resize (cell->get_fe().dofs_per_cell);
+            cell->get_dof_indices (dofs_on_this_cell);
+
+            // make sparsity pattern for this cell
+            for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
+              for (unsigned int j=0; j<cell->get_fe().dofs_per_cell; ++j)
+                if (int_dof_mask[cell->active_fe_index()](i,j) != none)
+                  sparsity.add (dofs_on_this_cell[i],
+                                dofs_on_this_cell[j]);
+
+            // Loop over all interior neighbors
+            for (unsigned int face = 0;
+                 face < GeometryInfo<dim>::faces_per_cell;
+                 ++face)
+              {
+                const typename dealii::hp::DoFHandler<dim,spacedim>::face_iterator
+                cell_face = cell->face(face);
+                if (cell_face->user_flag_set ())
+                  continue;
+
+                if (cell->at_boundary (face) )
+                  {
+                    for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
+                      for (unsigned int j=0; j<cell->get_fe().dofs_per_cell; ++j)
+                        if ((flux_mask(cell->get_fe().system_to_component_index(i).first,
+                                       cell->get_fe().system_to_component_index(j).first)
+                             == always)
+                            ||
+                            (flux_mask(cell->get_fe().system_to_component_index(i).first,
+                                       cell->get_fe().system_to_component_index(j).first)
+                             == nonzero))
+                          sparsity.add (dofs_on_this_cell[i],
+                                        dofs_on_this_cell[j]);
+                  }
+                else
+                  {
+                    typename dealii::hp::DoFHandler<dim,spacedim>::level_cell_iterator
+                    neighbor = cell->neighbor(face);
+
+                    // Refinement edges are taken care of by coarser cells
+                    if (cell->neighbor_is_coarser(face))
+                      continue;
+
+                    typename dealii::hp::DoFHandler<dim,spacedim>::face_iterator
+                    cell_face = cell->face(face);
+                    const unsigned int
+                    neighbor_face = cell->neighbor_of_neighbor(face);
+
+                    if (cell_face->has_children())
+                      {
+                        for (unsigned int sub_nr = 0;
+                             sub_nr != cell_face->n_children();
+                             ++sub_nr)
+                          {
+                            const typename dealii::hp::DoFHandler<dim,spacedim>::level_cell_iterator
+                            sub_neighbor
+                              = cell->neighbor_child_on_subface (face, sub_nr);
+
+                            dofs_on_other_cell.resize (sub_neighbor->get_fe().dofs_per_cell);
+                            sub_neighbor->get_dof_indices (dofs_on_other_cell);
+                            for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
+                              {
+                                for (unsigned int j=0; j<sub_neighbor->get_fe().dofs_per_cell;
+                                     ++j)
+                                  {
+                                    if ((flux_mask(cell->get_fe().system_to_component_index(i).first,
+                                                   sub_neighbor->get_fe().system_to_component_index(j).first)
+                                         == always)
+                                        ||
+                                        (flux_mask(cell->get_fe().system_to_component_index(i).first,
+                                                   sub_neighbor->get_fe().system_to_component_index(j).first)
+                                         == nonzero))
+                                      {
+                                        sparsity.add (dofs_on_this_cell[i],
+                                                      dofs_on_other_cell[j]);
+                                        sparsity.add (dofs_on_other_cell[i],
+                                                      dofs_on_this_cell[j]);
+                                        sparsity.add (dofs_on_this_cell[i],
+                                                      dofs_on_this_cell[j]);
+                                        sparsity.add (dofs_on_other_cell[i],
+                                                      dofs_on_other_cell[j]);
+                                      }
+
+                                    if ((flux_mask(sub_neighbor->get_fe().system_to_component_index(j).first,
+                                                   cell->get_fe().system_to_component_index(i).first)
+                                         == always)
+                                        ||
+                                        (flux_mask(sub_neighbor->get_fe().system_to_component_index(j).first,
+                                                   cell->get_fe().system_to_component_index(i).first)
+                                         == nonzero))
+                                      {
+                                        sparsity.add (dofs_on_this_cell[j],
+                                                      dofs_on_other_cell[i]);
+                                        sparsity.add (dofs_on_other_cell[j],
+                                                      dofs_on_this_cell[i]);
+                                        sparsity.add (dofs_on_this_cell[j],
+                                                      dofs_on_this_cell[i]);
+                                        sparsity.add (dofs_on_other_cell[j],
+                                                      dofs_on_other_cell[i]);
+                                      }
+                                  }
+                              }
+                            sub_neighbor->face(neighbor_face)->set_user_flag ();
+                          }
+                      }
+                    else
+                      {
+                        dofs_on_other_cell.resize (neighbor->get_fe().dofs_per_cell);
+                        neighbor->get_dof_indices (dofs_on_other_cell);
+                        for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
+                          {
+                            for (unsigned int j=0; j<neighbor->get_fe().dofs_per_cell; ++j)
+                              {
+                                if ((flux_mask(cell->get_fe().system_to_component_index(i).first,
+                                               neighbor->get_fe().system_to_component_index(j).first)
+                                     == always)
+                                    ||
+                                    (flux_mask(cell->get_fe().system_to_component_index(i).first,
+                                               neighbor->get_fe().system_to_component_index(j).first)
+                                     == nonzero))
+                                  {
+                                    sparsity.add (dofs_on_this_cell[i],
+                                                  dofs_on_other_cell[j]);
+                                    sparsity.add (dofs_on_other_cell[i],
+                                                  dofs_on_this_cell[j]);
+                                    sparsity.add (dofs_on_this_cell[i],
+                                                  dofs_on_this_cell[j]);
+                                    sparsity.add (dofs_on_other_cell[i],
+                                                  dofs_on_other_cell[j]);
+                                  }
+
+                                if ((flux_mask(neighbor->get_fe().system_to_component_index(j).first,
+                                               cell->get_fe().system_to_component_index(i).first)
+                                     == always)
+                                    ||
+                                    (flux_mask(neighbor->get_fe().system_to_component_index(j).first,
+                                               cell->get_fe().system_to_component_index(i).first)
+                                     == nonzero))
+                                  {
+                                    sparsity.add (dofs_on_this_cell[j],
+                                                  dofs_on_other_cell[i]);
+                                    sparsity.add (dofs_on_other_cell[j],
+                                                  dofs_on_this_cell[i]);
+                                    sparsity.add (dofs_on_this_cell[j],
+                                                  dofs_on_this_cell[i]);
+                                    sparsity.add (dofs_on_other_cell[j],
+                                                  dofs_on_other_cell[i]);
+                                  }
+                              }
+                          }
+                        neighbor->face(neighbor_face)->set_user_flag ();
+                      }
+                  }
+              }
+          }
+      }
+    }
+
+  }
+
+
+
+
+  template <class DH, class SparsityPattern>
+  void
+  make_flux_sparsity_pattern (const DH                &dof,
+                              SparsityPattern         &sparsity,
+                              const Table<2,Coupling> &int_mask,
+                              const Table<2,Coupling> &flux_mask)
+  {
+    // do the error checking and frame code here, and then pass on to more
+    // specialized functions in the internal namespace
+    const types::global_dof_index n_dofs = dof.n_dofs();
+    const unsigned int n_comp = dof.get_fe().n_components();
+
+    Assert (sparsity.n_rows() == n_dofs,
+            ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
+    Assert (sparsity.n_cols() == n_dofs,
+            ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
+    Assert (int_mask.n_rows() == n_comp,
+            ExcDimensionMismatch (int_mask.n_rows(), n_comp));
+    Assert (int_mask.n_cols() == n_comp,
+            ExcDimensionMismatch (int_mask.n_cols(), n_comp));
+    Assert (flux_mask.n_rows() == n_comp,
+            ExcDimensionMismatch (flux_mask.n_rows(), n_comp));
+    Assert (flux_mask.n_cols() == n_comp,
+            ExcDimensionMismatch (flux_mask.n_cols(), n_comp));
+
+    // Clear user flags because we will need them. But first we save them
+    // and make sure that we restore them later such that at the end of
+    // this function the Triangulation will be in the same state as it was
+    // at the beginning of this function.
+    std::vector<bool> user_flags;
+    dof.get_tria().save_user_flags(user_flags);
+    const_cast<Triangulation<DH::dimension,DH::space_dimension> &>(dof.get_tria()).clear_user_flags ();
+
+    internal::make_flux_sparsity_pattern (dof, sparsity,
+                                          int_mask, flux_mask);
+
+    // finally restore the user flags
+    const_cast<Triangulation<DH::dimension,DH::space_dimension> &>(dof.get_tria()).load_user_flags(user_flags);
+  }
+
+
+} // end of namespace DoFTools
+
+
+// --------------------------------------------------- explicit instantiations
+
+#include "dof_tools_sparsity.inst"
+
+
+
+DEAL_II_NAMESPACE_CLOSE
diff --git a/deal.II/source/dofs/dof_tools_sparsity.inst.in b/deal.II/source/dofs/dof_tools_sparsity.inst.in
new file mode 100644 (file)
index 0000000..6781dbe
--- /dev/null
@@ -0,0 +1,323 @@
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2009 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+for (SP : SPARSITY_PATTERNS; deal_II_dimension : DIMENSIONS)
+  {
+    template void
+    DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+    (const DoFHandler<deal_II_dimension,deal_II_dimension> &dof,
+     SP    &sparsity,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension> &dof,
+     SP    &sparsity,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<MGDoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+    (const MGDoFHandler<deal_II_dimension,deal_II_dimension> &dof,
+     SP    &sparsity,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+    (const DoFHandler<deal_II_dimension,deal_II_dimension>&,
+     const Table<2,Coupling>&,
+     SP &,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension>&,
+     const Table<2,Coupling>&,
+     SP &,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<MGDoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+    (const MGDoFHandler<deal_II_dimension,deal_II_dimension>&,
+     const Table<2,Coupling>&,
+     SP &,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+    (const DoFHandler<deal_II_dimension,deal_II_dimension> &dof_row,
+     const DoFHandler<deal_II_dimension,deal_II_dimension> &dof_col,
+     SP    &sparsity);
+
+    template void
+    DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension>, SP>
+    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension> &dof_row,
+     const hp::DoFHandler<deal_II_dimension,deal_II_dimension> &dof_col,
+     SP    &sparsity);
+
+    template void
+    DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
+    (const DoFHandler<deal_II_dimension>& dof,
+     const std::vector<types::global_dof_index>  &,
+     SP    &);
+
+    template void
+    DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
+    (const hp::DoFHandler<deal_II_dimension>& dof,
+     const std::vector<types::global_dof_index>  &,
+     SP    &);
+
+    template void
+    DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
+    (const DoFHandler<deal_II_dimension>& dof,
+     const FunctionMap<deal_II_dimension>::type  &boundary_indicators,
+     const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
+     SP    &sparsity);
+
+    template void
+    DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
+    (const hp::DoFHandler<deal_II_dimension>& dof,
+     const FunctionMap<deal_II_dimension>::type  &boundary_indicators,
+     const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
+     SP    &sparsity);
+
+#if deal_II_dimension < 3
+    template void
+    DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
+    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
+     const FunctionMap<deal_II_dimension+1>::type  &boundary_indicators,
+     const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
+     SP    &sparsity);
+ #endif
+
+    template void
+    DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
+    (const DoFHandler<deal_II_dimension> &dof,
+     SP    &sparsity);
+
+    template void
+    DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
+    (const hp::DoFHandler<deal_II_dimension> &dof,
+     SP    &sparsity);
+
+#if deal_II_dimension > 1
+
+    template void
+    DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
+    (const DoFHandler<deal_II_dimension> &dof,
+     SP    &,
+     const Table<2,Coupling>&,
+     const Table<2,Coupling>&);
+
+    template void
+    DoFTools::make_flux_sparsity_pattern<DoFHandler<deal_II_dimension>,SP>
+    (const DoFHandler<deal_II_dimension> &dof,
+     SP    &sparsity,
+     const ConstraintMatrix &constraints,
+     const bool, const unsigned int);
+
+    template void
+    DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
+    (const hp::DoFHandler<deal_II_dimension> &dof,
+     SP    &sparsity,
+     const ConstraintMatrix &constraints,
+     const bool, const unsigned int);
+
+    template void
+    DoFTools::make_flux_sparsity_pattern<hp::DoFHandler<deal_II_dimension>,SP>
+    (const hp::DoFHandler<deal_II_dimension> &dof,
+     SP    &,
+     const Table<2,Coupling>&,
+     const Table<2,Coupling>&);
+#endif
+
+#if deal_II_dimension < 3
+
+    template void
+    DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
+    (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof,
+     SP    &sparsity,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
+    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof,
+     SP    &sparsity,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
+    (const DoFHandler<deal_II_dimension,deal_II_dimension+1>&,
+     const Table<2,Coupling>&,
+     SP &,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
+    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>&,
+     const Table<2,Coupling>&,
+     SP &,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
+    (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_row,
+     const DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_col,
+     SP    &sparsity);
+
+    template void
+    DoFTools::make_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>, SP>
+    (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_row,
+     const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &dof_col,
+     SP    &sparsity);
+
+    template void
+    DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
+    (const DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
+     const std::vector<types::global_dof_index>  &,
+     SP    &);
+
+    //template void
+    //DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
+    //(const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
+    // const std::vector<types::global_dof_index>  &,
+    // SP    &);
+
+    template void
+    DoFTools::make_boundary_sparsity_pattern<DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
+    (const DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
+     const FunctionMap<deal_II_dimension+1>::type  &boundary_indicators,
+     const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
+     SP    &sparsity);
+
+    //template void
+    //DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>,SP>
+    //(const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>& dof,
+    // const FunctionMap<deal_II_dimension+1>::type  &boundary_indicators,
+    // const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
+    // SP    &sparsity);
+
+#endif
+
+
+#if deal_II_dimension == 3
+
+    template void
+    DoFTools::make_sparsity_pattern<DoFHandler<1,3>, SP>
+    (const DoFHandler<1,3> &dof,
+     SP    &sparsity,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<hp::DoFHandler<1,3>, SP>
+    (const hp::DoFHandler<1,3> &dof,
+     SP    &sparsity,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<DoFHandler<1,3>, SP>
+    (const DoFHandler<1,3>&,
+     const Table<2,Coupling>&,
+     SP &,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<hp::DoFHandler<1,3>, SP>
+    (const hp::DoFHandler<1,3>&,
+     const Table<2,Coupling>&,
+     SP &,
+     const ConstraintMatrix &,
+     const bool,
+     const unsigned int);
+
+    template void
+    DoFTools::make_sparsity_pattern<DoFHandler<1,3>, SP>
+    (const DoFHandler<1,3> &dof_row,
+     const DoFHandler<1,3> &dof_col,
+     SP    &sparsity);
+
+    template void
+    DoFTools::make_sparsity_pattern<hp::DoFHandler<1,3>, SP>
+    (const hp::DoFHandler<1,3> &dof_row,
+     const hp::DoFHandler<1,3> &dof_col,
+     SP    &sparsity);
+
+    template void
+    DoFTools::make_boundary_sparsity_pattern<DoFHandler<1,3>,SP>
+    (const DoFHandler<1,3>& dof,
+     const std::vector<types::global_dof_index>  &,
+     SP    &);
+
+    template void
+    DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<1,3>,SP>
+    (const hp::DoFHandler<1,3>& dof,
+     const std::vector<types::global_dof_index>  &,
+     SP    &);
+
+    template void
+    DoFTools::make_boundary_sparsity_pattern<DoFHandler<1,3>,SP>
+    (const DoFHandler<1,3>& dof,
+     const FunctionMap<3>::type  &boundary_indicators,
+     const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
+     SP    &sparsity);
+
+    template void
+    DoFTools::make_boundary_sparsity_pattern<hp::DoFHandler<1,3>,SP>
+    (const hp::DoFHandler<1,3>& dof,
+     const FunctionMap<3>::type  &boundary_indicators,
+     const std::vector<types::global_dof_index>  &dof_to_boundary_mapping,
+     SP    &sparsity);
+
+#endif
+
+  }
+
+
+for (deal_II_dimension : DIMENSIONS)
+{
+  template
+  Table<2,DoFTools::Coupling>
+  DoFTools::dof_couplings_from_component_couplings
+  (const FiniteElement<deal_II_dimension> &fe,
+   const Table<2,DoFTools::Coupling> &component_couplings);
+}

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.