]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Split DataOut_DoFData instantiations.
authorDavid Wells <wellsd2@rpi.edu>
Sat, 13 May 2017 19:56:26 +0000 (15:56 -0400)
committerDavid Wells <wellsd2@rpi.edu>
Fri, 2 Jun 2017 13:41:29 +0000 (09:41 -0400)
Before this commit GCC needed 2.3 GB, 65s in release mode and 3.6 GB, 79s in
debug mode to compile this file. After splitting the file we need 43s/32s and
1.6 GB/1.3 GB in release mode and 52s/34s and 2.1 GB/2.0 GB in debug mode. This
is substantial because this was (previously) the most expensive file to
compile.

This also adds a few missing instantiations to the nonzero codimension case.

include/deal.II/numerics/data_out_dof_data.templates.h [new file with mode: 0644]
source/numerics/CMakeLists.txt
source/numerics/data_out_dof_data.cc
source/numerics/data_out_dof_data.inst.in
source/numerics/data_out_dof_data_codim.cc [new file with mode: 0644]
source/numerics/data_out_dof_data_codim.inst.in [new file with mode: 0644]

diff --git a/include/deal.II/numerics/data_out_dof_data.templates.h b/include/deal.II/numerics/data_out_dof_data.templates.h
new file mode 100644 (file)
index 0000000..18ff0a6
--- /dev/null
@@ -0,0 +1,1281 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 1999 - 2016 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.
+//
+// ---------------------------------------------------------------------
+
+#ifndef dealii__data_out_dof_data_templates_h
+#define dealii__data_out_dof_data_templates_h
+
+
+#include <deal.II/base/quadrature_lib.h>
+#include <deal.II/base/work_stream.h>
+#include <deal.II/base/memory_consumption.h>
+#include <deal.II/base/std_cxx14/memory.h>
+#include <deal.II/base/utilities.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/lac/la_vector.h>
+#include <deal.II/lac/la_parallel_vector.h>
+#include <deal.II/lac/la_parallel_block_vector.h>
+#include <deal.II/lac/petsc_parallel_vector.h>
+#include <deal.II/lac/petsc_parallel_block_vector.h>
+#include <deal.II/lac/trilinos_vector.h>
+#include <deal.II/lac/trilinos_parallel_block_vector.h>
+#include <deal.II/lac/vector_element_access.h>
+#include <deal.II/numerics/data_out.h>
+#include <deal.II/numerics/data_out_dof_data.h>
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/fe/fe.h>
+#include <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/hp/dof_handler.h>
+#include <deal.II/hp/fe_values.h>
+#include <deal.II/fe/mapping_q1.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+namespace internal
+{
+  namespace DataOut
+  {
+    template <int dim, int spacedim>
+    ParallelDataBase<dim,spacedim>::
+    ParallelDataBase (const unsigned int n_datasets,
+                      const unsigned int n_subdivisions,
+                      const std::vector<unsigned int> &n_postprocessor_outputs,
+                      const Mapping<dim,spacedim> &mapping,
+                      const std::vector<std::shared_ptr<dealii::hp::FECollection<dim,spacedim> > > &finite_elements,
+                      const UpdateFlags update_flags,
+                      const bool        use_face_values)
+      :
+      n_datasets (n_datasets),
+      n_subdivisions (n_subdivisions),
+      postprocessed_values (n_postprocessor_outputs.size()),
+      mapping_collection (mapping),
+      finite_elements (finite_elements),
+      update_flags (update_flags)
+    {
+      unsigned int n_q_points = 0;
+      if (use_face_values == false)
+        {
+          dealii::hp::QCollection<dim>
+          quadrature(QIterated<dim>(QTrapez<1>(), n_subdivisions));
+          n_q_points = quadrature[0].size();
+          x_fe_values.resize(this->finite_elements.size());
+          for (unsigned int i=0; i<this->finite_elements.size(); ++i)
+            {
+              // check if there is a finite element that is equal to the
+              // present one, then we can re-use the FEValues object
+              for (unsigned int j=0; j<i; ++j)
+                if (this->finite_elements[i].get() ==
+                    this->finite_elements[j].get())
+                  {
+                    x_fe_values[i] = x_fe_values[j];
+                    break;
+                  }
+              if (x_fe_values[i].get() == nullptr)
+                x_fe_values[i].reset(new dealii::hp::FEValues<dim,spacedim>
+                                     (this->mapping_collection,
+                                      *this->finite_elements[i],
+                                      quadrature,
+                                      this->update_flags));
+            }
+        }
+      else
+        {
+          dealii::hp::QCollection<dim-1>
+          quadrature(QIterated<dim-1>(QTrapez<1>(), n_subdivisions));
+          n_q_points = quadrature[0].size();
+          x_fe_face_values.resize(this->finite_elements.size());
+          for (unsigned int i=0; i<this->finite_elements.size(); ++i)
+            {
+              // check if there is a finite element that is equal to the
+              // present one, then we can re-use the FEValues object
+              for (unsigned int j=0; j<i; ++j)
+                if (this->finite_elements[i].get() ==
+                    this->finite_elements[j].get())
+                  {
+                    x_fe_face_values[i] = x_fe_face_values[j];
+                    break;
+                  }
+              if (x_fe_face_values[i].get() == nullptr)
+                x_fe_face_values[i].reset(new dealii::hp::FEFaceValues<dim,spacedim>
+                                          (this->mapping_collection,
+                                           *this->finite_elements[i],
+                                           quadrature,
+                                           this->update_flags));
+            }
+        }
+
+      patch_values_scalar.solution_values.resize (n_q_points);
+      patch_values_scalar.solution_gradients.resize (n_q_points);
+      patch_values_scalar.solution_hessians.resize (n_q_points);
+      patch_values_system.solution_values.resize (n_q_points);
+      patch_values_system.solution_gradients.resize (n_q_points);
+      patch_values_system.solution_hessians.resize (n_q_points);
+
+      for (unsigned int dataset=0; dataset<n_postprocessor_outputs.size(); ++dataset)
+        if (n_postprocessor_outputs[dataset] != 0)
+          postprocessed_values[dataset]
+          .resize(n_q_points,
+                  dealii::Vector<double>(n_postprocessor_outputs[dataset]));
+    }
+
+
+
+
+
+    // implement copy constructor to create a thread's own version of
+    // x_fe_values
+    template <int dim, int spacedim>
+    ParallelDataBase<dim,spacedim>::
+    ParallelDataBase (const ParallelDataBase<dim,spacedim> &data)
+      :
+      n_datasets (data.n_datasets),
+      n_subdivisions (data.n_subdivisions),
+      patch_values_scalar (data.patch_values_scalar),
+      patch_values_system (data.patch_values_system),
+      postprocessed_values (data.postprocessed_values),
+      mapping_collection (data.mapping_collection),
+      finite_elements (data.finite_elements),
+      update_flags (data.update_flags)
+    {
+      if (data.x_fe_values.empty() == false)
+        {
+          Assert(data.x_fe_face_values.empty() == true, ExcInternalError());
+          dealii::hp::QCollection<dim>
+          quadrature(QIterated<dim>(QTrapez<1>(), n_subdivisions));
+          x_fe_values.resize(this->finite_elements.size());
+          for (unsigned int i=0; i<this->finite_elements.size(); ++i)
+            {
+              // check if there is a finite element that is equal to the
+              // present one, then we can re-use the FEValues object
+              for (unsigned int j=0; j<i; ++j)
+                if (this->finite_elements[i].get() ==
+                    this->finite_elements[j].get())
+                  {
+                    x_fe_values[i] = x_fe_values[j];
+                    break;
+                  }
+              if (x_fe_values[i].get() == nullptr)
+                x_fe_values[i].reset(new dealii::hp::FEValues<dim,spacedim>
+                                     (this->mapping_collection,
+                                      *this->finite_elements[i],
+                                      quadrature,
+                                      this->update_flags));
+            }
+        }
+      else
+        {
+          dealii::hp::QCollection<dim-1>
+          quadrature(QIterated<dim-1>(QTrapez<1>(), n_subdivisions));
+          x_fe_face_values.resize(this->finite_elements.size());
+          for (unsigned int i=0; i<this->finite_elements.size(); ++i)
+            {
+              // check if there is a finite element that is equal to the
+              // present one, then we can re-use the FEValues object
+              for (unsigned int j=0; j<i; ++j)
+                if (this->finite_elements[i].get() ==
+                    this->finite_elements[j].get())
+                  {
+                    x_fe_face_values[i] = x_fe_face_values[j];
+                    break;
+                  }
+              if (x_fe_face_values[i].get() == nullptr)
+                x_fe_face_values[i].reset(new dealii::hp::FEFaceValues<dim,spacedim>
+                                          (this->mapping_collection,
+                                           *this->finite_elements[i],
+                                           quadrature,
+                                           this->update_flags));
+            }
+        }
+    }
+
+
+
+    template <int dim, int spacedim>
+    template <typename DoFHandlerType>
+    void
+    ParallelDataBase<dim,spacedim>::
+    reinit_all_fe_values(std::vector<std::shared_ptr<DataEntryBase<DoFHandlerType> > > &dof_data,
+                         const typename dealii::Triangulation<dim,spacedim>::cell_iterator   &cell,
+                         const unsigned int                                                   face)
+    {
+      for (unsigned int dataset=0; dataset<dof_data.size(); ++dataset)
+        {
+          bool duplicate = false;
+          for (unsigned int j=0; j<dataset; ++j)
+            if (finite_elements[dataset].get() == finite_elements[j].get())
+              duplicate = true;
+          if (duplicate == false)
+            {
+              typename DoFHandlerType::active_cell_iterator dh_cell(&cell->get_triangulation(),
+                                                                    cell->level(),
+                                                                    cell->index(),
+                                                                    dof_data[dataset]->dof_handler);
+              if (x_fe_values.empty())
+                {
+                  AssertIndexRange(face,
+                                   GeometryInfo<dim>::faces_per_cell);
+                  x_fe_face_values[dataset]->reinit(dh_cell, face);
+                }
+              else
+                x_fe_values[dataset]->reinit (dh_cell);
+            }
+        }
+      if (dof_data.empty())
+        {
+          if (x_fe_values.empty())
+            {
+              AssertIndexRange(face,
+                               GeometryInfo<dim>::faces_per_cell);
+              x_fe_face_values[0]->reinit(cell, face);
+            }
+          else
+            x_fe_values[0]->reinit (cell);
+        }
+    }
+
+
+
+    template <int dim, int spacedim>
+    const FEValuesBase<dim,spacedim> &
+    ParallelDataBase<dim,spacedim>::
+    get_present_fe_values(const unsigned int dataset) const
+    {
+      AssertIndexRange(dataset, finite_elements.size());
+      if (x_fe_values.empty())
+        return x_fe_face_values[dataset]->get_present_fe_values();
+      else
+        return x_fe_values[dataset]->get_present_fe_values();
+    }
+
+
+
+    template <int dim, int spacedim>
+    void
+    ParallelDataBase<dim,spacedim>::
+    resize_system_vectors(const unsigned int n_components)
+    {
+      Assert(patch_values_system.solution_values.size() > 0, ExcInternalError());
+      AssertDimension(patch_values_system.solution_values.size(),
+                      patch_values_system.solution_gradients.size());
+      AssertDimension(patch_values_system.solution_values.size(),
+                      patch_values_system.solution_hessians.size());
+      if (patch_values_system.solution_values[0].size() == n_components)
+        return;
+      for (unsigned int k=0; k<patch_values_system.solution_values.size(); ++k)
+        {
+          patch_values_system.solution_values[k].reinit(n_components);
+          patch_values_system.solution_gradients[k].resize(n_components);
+          patch_values_system.solution_hessians[k].resize(n_components);
+        }
+    }
+
+
+
+
+    /**
+     * In a WorkStream context, use this function to append the patch computed
+     * by the parallel stage to the array of patches.
+     */
+    template <int dim, int spacedim>
+    void
+    append_patch_to_list (const DataOutBase::Patch<dim,spacedim> &patch,
+                          std::vector<DataOutBase::Patch<dim,spacedim> > &patches)
+    {
+      patches.push_back (patch);
+      patches.back().patch_index = patches.size()-1;
+    }
+  }
+}
+
+namespace internal
+{
+  namespace DataOut
+  {
+    template <typename DoFHandlerType>
+    DataEntryBase<DoFHandlerType>::DataEntryBase
+    (const DoFHandlerType           *dofs,
+     const std::vector<std::string> &names_in,
+     const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
+      :
+      dof_handler (dofs, typeid(dealii::DataOut_DoFData<DoFHandlerType,DoFHandlerType::dimension,DoFHandlerType::space_dimension>).name()),
+      names(names_in),
+      data_component_interpretation (data_component_interpretation),
+      postprocessor(nullptr, typeid(*this).name()),
+      n_output_variables(names.size())
+    {
+      Assert (names.size() == data_component_interpretation.size(),
+              ExcDimensionMismatch(data_component_interpretation.size(),
+                                   names.size()));
+
+      // check that the names use only allowed characters
+      for (unsigned int i=0; i<names.size(); ++i)
+        Assert (names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
+                                           "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                           "0123456789_<>()") == std::string::npos,
+                Exceptions::DataOut::ExcInvalidCharacter (names[i],
+                                                          names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
+                                                              "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                                              "0123456789_<>()")));
+    }
+
+
+
+    template <typename DoFHandlerType>
+    DataEntryBase<DoFHandlerType>::DataEntryBase
+    (const DoFHandlerType *dofs,
+     const DataPostprocessor<DoFHandlerType::space_dimension> *data_postprocessor)
+      :
+      dof_handler (dofs, typeid(dealii::DataOut_DoFData<DoFHandlerType,DoFHandlerType::dimension,DoFHandlerType::space_dimension>).name()),
+      names(data_postprocessor->get_names()),
+      data_component_interpretation (data_postprocessor->get_data_component_interpretation()),
+      postprocessor(data_postprocessor, typeid(*this).name()),
+      n_output_variables(names.size())
+    {
+      Assert (data_postprocessor->get_names().size()
+              ==
+              data_postprocessor->get_data_component_interpretation().size(),
+              ExcDimensionMismatch (data_postprocessor->get_names().size(),
+                                    data_postprocessor->get_data_component_interpretation().size()));
+
+      // check that the names use only allowed characters
+      for (unsigned int i=0; i<names.size(); ++i)
+        Assert (names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
+                                           "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                           "0123456789_<>()") == std::string::npos,
+                Exceptions::DataOut::ExcInvalidCharacter (names[i],
+                                                          names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
+                                                              "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                                              "0123456789_<>()")));
+    }
+
+
+
+    template <typename DoFHandlerType>
+    DataEntryBase<DoFHandlerType>::~DataEntryBase ()
+    {}
+
+
+
+    /**
+     * Class that stores a pointer to a vector of type equal to the template
+     * argument, and provides the functions to extract data from it.
+     *
+     * @author Wolfgang Bangerth, 2004
+     */
+    template <typename DoFHandlerType, typename VectorType>
+    class DataEntry : public DataEntryBase<DoFHandlerType>
+    {
+    public:
+      /**
+       * Constructor. Give a list of names for the individual components of
+       * the vector and their interpretation as scalar or vector data. This
+       * constructor assumes that no postprocessor is going to be used.
+       */
+      DataEntry
+      (const DoFHandlerType           *dofs,
+       const VectorType               *data,
+       const std::vector<std::string> &names,
+       const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation);
+
+      /**
+       * Constructor when a data postprocessor is going to be used. In that
+       * case, the names and vector declarations are going to be acquired from
+       * the postprocessor.
+       */
+      DataEntry (const DoFHandlerType                                     *dofs,
+                 const VectorType                                         *data,
+                 const DataPostprocessor<DoFHandlerType::space_dimension> *data_postprocessor);
+
+      /**
+       * Assuming that the stored vector is a cell vector, extract the given
+       * element from it.
+       */
+      virtual
+      double
+      get_cell_data_value (const unsigned int cell_number) const;
+
+      /**
+       * Given a FEValuesBase object, extract the values on the present cell
+       * from the vector we actually store.
+       */
+      virtual
+      void
+      get_function_values
+      (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
+       std::vector<double> &patch_values) const;
+
+      /**
+       * Given a FEValuesBase object, extract the values on the present cell
+       * from the vector we actually store. This function does the same as the
+       * one above but for vector-valued finite elements.
+       */
+      virtual
+      void
+      get_function_values
+      (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
+       std::vector<dealii::Vector<double> > &patch_values_system) const;
+
+      /**
+       * Given a FEValuesBase object, extract the gradients on the present
+       * cell from the vector we actually store.
+       */
+      virtual
+      void
+      get_function_gradients
+      (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
+       std::vector<Tensor<1,DoFHandlerType::space_dimension> > &patch_gradients) const;
+
+      /**
+       * Given a FEValuesBase object, extract the gradients on the present
+       * cell from the vector we actually store. This function does the same
+       * as the one above but for vector-valued finite elements.
+       */
+      virtual
+      void
+      get_function_gradients
+      (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
+       std::vector<std::vector<Tensor<1,DoFHandlerType::space_dimension> > > &patch_gradients_system) const;
+
+      /**
+       * Given a FEValuesBase object, extract the second derivatives on the
+       * present cell from the vector we actually store.
+       */
+      virtual
+      void
+      get_function_hessians
+      (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
+       std::vector<Tensor<2,DoFHandlerType::space_dimension> > &patch_hessians) const;
+
+      /**
+       * Given a FEValuesBase object, extract the second derivatives on the
+       * present cell from the vector we actually store. This function does
+       * the same as the one above but for vector-valued finite elements.
+       */
+      virtual
+      void
+      get_function_hessians
+      (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
+       std::vector<std::vector< Tensor<2,DoFHandlerType::space_dimension> > > &patch_hessians_system) const;
+
+      /**
+       * Clear all references to the vectors.
+       */
+      virtual void clear ();
+
+      /**
+       * Determine an estimate for the memory consumption (in bytes) of this
+       * object.
+       */
+      virtual std::size_t memory_consumption () const;
+
+    private:
+      /**
+       * Pointer to the data vector. Note that ownership of the vector pointed
+       * to remains with the caller of this class.
+       */
+      const VectorType *vector;
+    };
+
+
+
+    template <typename DoFHandlerType, typename VectorType>
+    DataEntry<DoFHandlerType,VectorType>::
+    DataEntry (const DoFHandlerType           *dofs,
+               const VectorType               *data,
+               const std::vector<std::string> &names,
+               const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
+      :
+      DataEntryBase<DoFHandlerType> (dofs, names, data_component_interpretation),
+      vector (data)
+    {}
+
+
+
+    template <typename DoFHandlerType, typename VectorType>
+    DataEntry<DoFHandlerType,VectorType>::
+    DataEntry (const DoFHandlerType                                     *dofs,
+               const VectorType                                         *data,
+               const DataPostprocessor<DoFHandlerType::space_dimension> *data_postprocessor)
+      :
+      DataEntryBase<DoFHandlerType> (dofs, data_postprocessor),
+      vector (data)
+    {}
+
+
+    namespace
+    {
+      template <typename VectorType>
+      double
+      get_vector_element (const VectorType   &vector,
+                          const unsigned int  cell_number)
+      {
+        return internal::ElementAccess<VectorType>::get(vector,cell_number);
+      }
+
+
+      inline double
+      get_vector_element (const IndexSet &is,
+                          const unsigned int cell_number)
+      {
+        return (is.is_element(cell_number) ? 1 : 0);
+      }
+    }
+
+
+
+    template <typename DoFHandlerType, typename VectorType>
+    double
+    DataEntry<DoFHandlerType,VectorType>::
+    get_cell_data_value (const unsigned int cell_number) const
+    {
+      return get_vector_element(*vector, cell_number);
+    }
+
+
+
+    template <typename DoFHandlerType, typename VectorType>
+    void
+    DataEntry<DoFHandlerType,VectorType>::get_function_values
+    (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
+     std::vector<dealii::Vector<double> >                  &patch_values_system) const
+    {
+      // FIXME: FEValuesBase gives us data in types that match that of
+      // the solution vector. but this function needs to pass it back
+      // up as 'double' vectors. this requires the use of a temporary
+      // variable here if the data we get is not a 'double' vector.
+      // (of course, in reality, this also means that we may lose
+      // information to begin with.)
+      //
+      // the correct thing would be to also use the correct data type
+      // upstream somewhere, but this is complicated because we hide
+      // the actual data type from upstream. rather, we should at
+      // least make sure we can deal with complex numbers
+      if (typeid(typename VectorType::value_type) == typeid(double))
+        {
+          fe_patch_values.get_function_values (*vector,
+                                               // reinterpret output argument type; because of
+                                               // the 'if' statement above, this is the
+                                               // identity cast whenever the code is
+                                               // executed, but the cast is necessary
+                                               // to allow compilation even if we don't get here
+                                               reinterpret_cast<std::vector<dealii::Vector<typename VectorType::value_type> >&>
+                                               (patch_values_system));
+        }
+      else
+        {
+          std::vector<dealii::Vector<typename VectorType::value_type> > tmp(patch_values_system.size());
+          for (unsigned int i = 0; i < patch_values_system.size(); i++)
+            tmp[i].reinit(patch_values_system[i]);
+
+          fe_patch_values.get_function_values (*vector, tmp);
+
+          for (unsigned int i = 0; i < patch_values_system.size(); i++)
+            patch_values_system[i] = tmp[i];
+        }
+    }
+
+
+
+    template <typename DoFHandlerType, typename VectorType>
+    void
+    DataEntry<DoFHandlerType,VectorType>::get_function_values
+    (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
+     std::vector<double>                                   &patch_values) const
+    {
+      // FIXME: FEValuesBase gives us data in types that match that of
+      // the solution vector. but this function needs to pass it back
+      // up as 'double' vectors. this requires the use of a temporary
+      // variable here if the data we get is not a 'double' vector.
+      // (of course, in reality, this also means that we may lose
+      // information to begin with.)
+      //
+      // the correct thing would be to also use the correct data type
+      // upstream somewhere, but this is complicated because we hide
+      // the actual data type from upstream. rather, we should at
+      // least make sure we can deal with complex numbers
+      if (typeid(typename VectorType::value_type) == typeid(double))
+        {
+          fe_patch_values.get_function_values (*vector,
+                                               // reinterpret output argument type; because of
+                                               // the 'if' statement above, this is the
+                                               // identity cast whenever the code is
+                                               // executed, but the cast is necessary
+                                               // to allow compilation even if we don't get here
+                                               reinterpret_cast<std::vector<typename VectorType::value_type>&>
+                                               (patch_values));
+        }
+      else
+        {
+          std::vector<typename VectorType::value_type> tmp (patch_values.size());
+
+          fe_patch_values.get_function_values (*vector, tmp);
+
+          for (unsigned int i = 0; i < tmp.size(); i++)
+            patch_values[i] = tmp[i];
+        }
+    }
+
+
+
+    template <typename DoFHandlerType, typename VectorType>
+    void
+    DataEntry<DoFHandlerType,VectorType>::get_function_gradients
+    (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension>     &fe_patch_values,
+     std::vector<std::vector<Tensor<1,DoFHandlerType::space_dimension> > > &patch_gradients_system) const
+    {
+      // FIXME: FEValuesBase gives us data in types that match that of
+      // the solution vector. but this function needs to pass it back
+      // up as 'double' vectors. this requires the use of a temporary
+      // variable here if the data we get is not a 'double' vector.
+      // (of course, in reality, this also means that we may lose
+      // information to begin with.)
+      //
+      // the correct thing would be to also use the correct data type
+      // upstream somewhere, but this is complicated because we hide
+      // the actual data type from upstream. rather, we should at
+      // least make sure we can deal with complex numbers
+      if (typeid(typename VectorType::value_type) == typeid(double))
+        {
+          fe_patch_values.get_function_gradients (*vector,
+                                                  // reinterpret output argument type; because of
+                                                  // the 'if' statement above, this is the
+                                                  // identity cast whenever the code is
+                                                  // executed, but the cast is necessary
+                                                  // to allow compilation even if we don't get here
+                                                  reinterpret_cast<std::vector<std::vector<Tensor<1,DoFHandlerType::space_dimension,typename VectorType::value_type> > >&>
+                                                  (patch_gradients_system));
+        }
+      else
+        {
+          std::vector<std::vector<Tensor<1,DoFHandlerType::space_dimension,
+              typename VectorType::value_type> > >
+              tmp(patch_gradients_system.size());
+          for (unsigned int i = 0; i < tmp.size(); i++)
+            tmp[i].resize(patch_gradients_system[i].size());
+
+          fe_patch_values.get_function_gradients (*vector, tmp);
+
+          for (unsigned int i = 0; i < tmp.size(); i++)
+            for (unsigned int j = 0; j < tmp[i].size(); j++)
+              patch_gradients_system[i][j] = tmp[i][j];
+        }
+    }
+
+
+
+    template <typename DoFHandlerType, typename VectorType>
+    void
+    DataEntry<DoFHandlerType,VectorType>::get_function_gradients
+    (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
+     std::vector<Tensor<1,DoFHandlerType::space_dimension> >           &patch_gradients) const
+    {
+      // FIXME: FEValuesBase gives us data in types that match that of
+      // the solution vector. but this function needs to pass it back
+      // up as 'double' vectors. this requires the use of a temporary
+      // variable here if the data we get is not a 'double' vector.
+      // (of course, in reality, this also means that we may lose
+      // information to begin with.)
+      //
+      // the correct thing would be to also use the correct data type
+      // upstream somewhere, but this is complicated because we hide
+      // the actual data type from upstream. rather, we should at
+      // least make sure we can deal with complex numbers
+      if (typeid(typename VectorType::value_type) == typeid(double))
+        {
+          fe_patch_values.get_function_gradients (*vector,
+                                                  // reinterpret output argument type; because of
+                                                  // the 'if' statement above, this is the
+                                                  // identity cast whenever the code is
+                                                  // executed, but the cast is necessary
+                                                  // to allow compilation even if we don't get here
+                                                  reinterpret_cast<std::vector<Tensor<1,DoFHandlerType::space_dimension,typename VectorType::value_type> >&>
+                                                  (patch_gradients));
+        }
+      else
+        {
+          std::vector<Tensor<1,DoFHandlerType::space_dimension,typename VectorType::value_type> >  tmp;
+          tmp.resize(patch_gradients.size());
+
+          fe_patch_values.get_function_gradients (*vector, tmp);
+
+          for (unsigned int i = 0; i < tmp.size(); i++)
+            patch_gradients[i] = tmp[i];
+        }
+    }
+
+
+
+    template <typename DoFHandlerType, typename VectorType>
+    void
+    DataEntry<DoFHandlerType,VectorType>::get_function_hessians
+    (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
+     std::vector<std::vector<Tensor<2,DoFHandlerType::space_dimension> > > &patch_hessians_system) const
+    {
+      // FIXME: FEValuesBase gives us data in types that match that of
+      // the solution vector. but this function needs to pass it back
+      // up as 'double' vectors. this requires the use of a temporary
+      // variable here if the data we get is not a 'double' vector.
+      // (of course, in reality, this also means that we may lose
+      // information to begin with.)
+      //
+      // the correct thing would be to also use the correct data type
+      // upstream somewhere, but this is complicated because we hide
+      // the actual data type from upstream. rather, we should at
+      // least make sure we can deal with complex numbers
+      if (typeid(typename VectorType::value_type) == typeid(double))
+        {
+          fe_patch_values.get_function_hessians (*vector,
+                                                 // reinterpret output argument type; because of
+                                                 // the 'if' statement above, this is the
+                                                 // identity cast whenever the code is
+                                                 // executed, but the cast is necessary
+                                                 // to allow compilation even if we don't get here
+                                                 reinterpret_cast<std::vector<std::vector<Tensor<2,DoFHandlerType::space_dimension,typename VectorType::value_type> > >&>
+                                                 (patch_hessians_system));
+        }
+      else
+        {
+          std::vector<std::vector<Tensor<2,DoFHandlerType::space_dimension,
+              typename VectorType::value_type> > >
+              tmp(patch_hessians_system.size());
+          for (unsigned int i = 0; i < tmp.size(); i++)
+            tmp[i].resize(patch_hessians_system[i].size());
+
+          fe_patch_values.get_function_hessians (*vector, tmp);
+
+          for (unsigned int i = 0; i < tmp.size(); i++)
+            for (unsigned int j = 0; j < tmp[i].size(); j++)
+              patch_hessians_system[i][j] = tmp[i][j];
+        }
+    }
+
+
+
+    template <typename DoFHandlerType, typename VectorType>
+    void
+    DataEntry<DoFHandlerType,VectorType>::get_function_hessians
+    (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
+     std::vector<Tensor<2,DoFHandlerType::space_dimension> >                       &patch_hessians) const
+    {
+      // FIXME: FEValuesBase gives us data in types that match that of
+      // the solution vector. but this function needs to pass it back
+      // up as 'double' vectors. this requires the use of a temporary
+      // variable here if the data we get is not a 'double' vector.
+      // (of course, in reality, this also means that we may lose
+      // information to begin with.)
+      //
+      // the correct thing would be to also use the correct data type
+      // upstream somewhere, but this is complicated because we hide
+      // the actual data type from upstream. rather, we should at
+      // least make sure we can deal with complex numbers
+      if (typeid(typename VectorType::value_type) == typeid(double))
+        {
+          fe_patch_values.get_function_hessians (*vector,
+                                                 // reinterpret output argument type; because of
+                                                 // the 'if' statement above, this is the
+                                                 // identity cast whenever the code is
+                                                 // executed, but the cast is necessary
+                                                 // to allow compilation even if we don't get here
+                                                 reinterpret_cast<std::vector<Tensor<2,DoFHandlerType
+                                                 ::space_dimension,typename VectorType::value_type> >&>
+                                                 (patch_hessians));
+        }
+      else
+        {
+          std::vector<Tensor<2,DoFHandlerType::space_dimension,typename VectorType::value_type> >
+          tmp(patch_hessians.size());
+
+          fe_patch_values.get_function_hessians (*vector, tmp);
+
+          for (unsigned int i = 0; i < tmp.size(); i++)
+            patch_hessians[i] = tmp[i];
+        }
+    }
+
+
+
+    template <typename DoFHandlerType, typename VectorType>
+    std::size_t
+    DataEntry<DoFHandlerType,VectorType>::memory_consumption () const
+    {
+      return (sizeof (vector) +
+              MemoryConsumption::memory_consumption (this->names));
+    }
+
+
+
+    template <typename DoFHandlerType, typename VectorType>
+    void
+    DataEntry<DoFHandlerType,VectorType>::clear ()
+    {
+      vector = nullptr;
+      this->dof_handler = nullptr;
+    }
+  }
+}
+
+
+
+template <typename DoFHandlerType,
+          int patch_dim, int patch_space_dim>
+DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::DataOut_DoFData ()
+  :
+  triangulation(nullptr,typeid(*this).name()),
+  dofs(nullptr,typeid(*this).name())
+{}
+
+
+
+template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
+DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::~DataOut_DoFData ()
+{
+  clear ();
+}
+
+
+
+template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
+void
+DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::
+attach_dof_handler (const DoFHandlerType &d)
+{
+  Assert (dof_data.size() == 0,
+          Exceptions::DataOut::ExcOldDataStillPresent());
+  Assert (cell_data.size() == 0,
+          Exceptions::DataOut::ExcOldDataStillPresent());
+
+  triangulation = SmartPointer<const Triangulation<DoFHandlerType::dimension,
+  DoFHandlerType::space_dimension> >
+  (&d.get_triangulation(), typeid(*this).name());
+  dofs = SmartPointer<const DoFHandlerType>(&d, typeid(*this).name());
+}
+
+
+
+template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
+void
+DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::
+attach_triangulation (const Triangulation<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &tria)
+{
+  Assert (dof_data.size() == 0,
+          Exceptions::DataOut::ExcOldDataStillPresent());
+  Assert (cell_data.size() == 0,
+          Exceptions::DataOut::ExcOldDataStillPresent());
+
+  triangulation = SmartPointer<const Triangulation<DoFHandlerType::dimension,
+  DoFHandlerType::space_dimension> >
+  (&tria, typeid(*this).name());
+}
+
+
+
+template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
+template <typename VectorType>
+void
+DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::
+add_data_vector (const DoFHandlerType                   &dof_handler,
+                 const VectorType                       &vec,
+                 const DataPostprocessor<DoFHandlerType::space_dimension> &data_postprocessor)
+{
+  // this is a specialized version of the other function where we have a
+  // postprocessor. if we do, we know that we have type_dof_data, which makes
+  // things a bit simpler, we also don't need to deal with some of the other
+  // stuff and use a different constructor of DataEntry
+  if (triangulation != nullptr)
+    {
+      Assert (&dof_handler.get_triangulation() == triangulation,
+              ExcMessage("The triangulation attached to the DoFHandler does not "
+                         "match with the one set previously"));
+    }
+  else
+    {
+      triangulation = SmartPointer<const Triangulation<DoFHandlerType::dimension,DoFHandlerType::space_dimension>>
+                      (&dof_handler.get_triangulation(), typeid(*this).name());
+    }
+
+  Assert (vec.size() == dof_handler.n_dofs(),
+          Exceptions::DataOut::ExcInvalidVectorSize (vec.size(),
+                                                     dof_handler.n_dofs(),
+                                                     dof_handler.get_triangulation().n_active_cells()));
+
+
+  auto new_entry = std_cxx14::make_unique<internal::DataOut::DataEntry<DoFHandlerType,VectorType>>
+                   (&dof_handler, &vec, &data_postprocessor);
+  dof_data.emplace_back (std::move(new_entry));
+}
+
+
+
+template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
+template <typename VectorType>
+void
+DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::
+add_data_vector_internal
+(const DoFHandlerType           *dof_handler,
+ const VectorType               &data_vector,
+ const std::vector<std::string> &names,
+ const DataVectorType            type,
+ const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation_,
+ const bool                      deduce_output_names)
+{
+  // Check available mesh information:
+  if (triangulation == nullptr)
+    {
+      Assert(dof_handler != nullptr, ExcInternalError());
+      triangulation = SmartPointer<const Triangulation<DoFHandlerType::dimension,DoFHandlerType::space_dimension>>
+                      (&dof_handler->get_triangulation(), typeid(*this).name());
+    }
+
+  if (dof_handler != nullptr)
+    {
+      Assert (&dof_handler->get_triangulation() == triangulation,
+              ExcMessage("The triangulation attached to the DoFHandler does not "
+                         "match with the one set previously"));
+    }
+
+  // Figure out the data type:
+  DataVectorType actual_type = type;
+  if (type == type_automatic)
+    {
+      Assert((dof_handler == nullptr) || (triangulation->n_active_cells() != dof_handler->n_dofs()),
+             ExcMessage("Unable to determine the type of vector automatically because the number of DoFs "
+                        "is equal to the number of cells. Please specify DataVectorType."));
+
+      if (data_vector.size() == triangulation->n_active_cells())
+        actual_type = type_cell_data;
+      else
+        actual_type = type_dof_data;
+    }
+  Assert(actual_type == type_cell_data || actual_type == type_dof_data,
+         ExcInternalError());
+
+  // If necessary, append '_1', '_2', etc. to component names:
+  std::vector<std::string> deduced_names;
+  if (deduce_output_names && actual_type == type_dof_data)
+    {
+      Assert(names.size() == 1, ExcInternalError());
+      Assert(dof_handler != nullptr, ExcInternalError());
+      Assert(dof_handler->n_dofs() > 0,
+             ExcMessage("The DoF handler attached to the current output vector "
+                        "does not have any degrees of freedom, so it is not "
+                        "possible to output DoF data in this context."));
+      const std::string name = names[0];
+      const unsigned int n_components = dof_handler->get_fe().n_components();
+      deduced_names.resize (n_components);
+      if (n_components > 1)
+        {
+          for (unsigned int i=0; i<n_components; ++i)
+            {
+              deduced_names[i] = name + '_' + Utilities::to_string(i);
+            }
+        }
+      else
+        {
+          deduced_names[0] = name;
+        }
+    }
+  else
+    {
+      deduced_names = names;
+    }
+
+  // Check that things have the right sizes for the data type:
+  switch (actual_type)
+    {
+    case type_cell_data:
+      Assert (data_vector.size() == triangulation->n_active_cells(),
+              ExcDimensionMismatch (data_vector.size(),
+                                    triangulation->n_active_cells()));
+      Assert (deduced_names.size() == 1,
+              Exceptions::DataOut::ExcInvalidNumberOfNames (deduced_names.size(), 1));
+      break;
+    case type_dof_data:
+      Assert (dof_handler != nullptr,
+              Exceptions::DataOut::ExcNoDoFHandlerSelected ());
+      Assert (data_vector.size() == dof_handler->n_dofs(),
+              Exceptions::DataOut::ExcInvalidVectorSize (data_vector.size(),
+                                                         dof_handler->n_dofs(),
+                                                         triangulation->n_active_cells()));
+      Assert (deduced_names.size() == dof_handler->get_fe().n_components(),
+              Exceptions::DataOut::ExcInvalidNumberOfNames (deduced_names.size(),
+                                                            dof_handler->get_fe().n_components()));
+      break;
+    default:
+      Assert (false, ExcInternalError());
+    }
+
+  const auto &data_component_interpretation
+    = (data_component_interpretation_.size() != 0
+       ?
+       data_component_interpretation_
+       :
+       std::vector<DataComponentInterpretation::DataComponentInterpretation>
+       (deduced_names.size(), DataComponentInterpretation::component_is_scalar));
+
+  // finally, add the data vector:
+  auto new_entry = std_cxx14::make_unique<internal::DataOut::DataEntry<DoFHandlerType,VectorType>>
+                   (dof_handler, &data_vector, deduced_names, data_component_interpretation);
+
+  if (actual_type == type_dof_data)
+    dof_data.emplace_back (std::move(new_entry));
+  else
+    cell_data.emplace_back (std::move(new_entry));
+}
+
+
+
+template <typename DoFHandlerType,
+          int patch_dim, int patch_space_dim>
+void DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::clear_data_vectors ()
+{
+  dof_data.erase (dof_data.begin(), dof_data.end());
+  cell_data.erase (cell_data.begin(), cell_data.end());
+
+  // delete patches
+  std::vector<Patch> dummy;
+  patches.swap (dummy);
+}
+
+
+
+template <typename DoFHandlerType,
+          int patch_dim, int patch_space_dim>
+void
+DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::
+clear_input_data_references ()
+{
+  for (unsigned int i=0; i<dof_data.size(); ++i)
+    dof_data[i]->clear ();
+
+  for (unsigned int i=0; i<cell_data.size(); ++i)
+    cell_data[i]->clear ();
+
+  if (dofs != nullptr)
+    dofs = nullptr;
+}
+
+
+
+template <typename DoFHandlerType,
+          int patch_dim, int patch_space_dim>
+void
+DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::clear ()
+{
+  dof_data.erase (dof_data.begin(), dof_data.end());
+  cell_data.erase (cell_data.begin(), cell_data.end());
+
+  if (dofs != nullptr)
+    dofs = nullptr;
+
+  // delete patches
+  std::vector<Patch> dummy;
+  patches.swap (dummy);
+}
+
+
+
+template <typename DoFHandlerType,
+          int patch_dim, int patch_space_dim>
+std::vector<std::string>
+DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::
+get_dataset_names () const
+{
+  std::vector<std::string> names;
+  // collect the names of dof
+  // and cell data
+  typedef
+  typename std::vector<std::shared_ptr<internal::DataOut::DataEntryBase<DoFHandlerType> > >::const_iterator
+  data_iterator;
+
+  for (data_iterator  d=dof_data.begin();
+       d!=dof_data.end(); ++d)
+    for (unsigned int i=0; i<(*d)->names.size(); ++i)
+      names.push_back ((*d)->names[i]);
+  for (data_iterator d=cell_data.begin(); d!=cell_data.end(); ++d)
+    {
+      Assert ((*d)->names.size() == 1, ExcInternalError());
+      names.push_back ((*d)->names[0]);
+    }
+
+  return names;
+}
+
+
+
+template <typename DoFHandlerType,
+          int patch_dim, int patch_space_dim>
+std::vector<std::tuple<unsigned int, unsigned int, std::string> >
+DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::get_vector_data_ranges () const
+{
+  std::vector<std::tuple<unsigned int, unsigned int, std::string> >
+  ranges;
+
+  // collect the ranges of dof
+  // and cell data
+  typedef
+  typename std::vector<std::shared_ptr<internal::DataOut::DataEntryBase<DoFHandlerType> > >::const_iterator
+  data_iterator;
+
+  unsigned int output_component = 0;
+  for (data_iterator  d=dof_data.begin();
+       d!=dof_data.end(); ++d)
+    for (unsigned int i=0; i<(*d)->n_output_variables;
+         ++i, ++output_component)
+      // see what kind of data we have
+      // here. note that for the purpose of
+      // the current function all we care
+      // about is vector data
+      if ((*d)->data_component_interpretation[i] ==
+          DataComponentInterpretation::component_is_part_of_vector)
+        {
+          // ensure that there is a
+          // continuous number of next
+          // space_dim components that all
+          // deal with vectors
+          Assert (i+patch_space_dim <=
+                  (*d)->n_output_variables,
+                  Exceptions::DataOut::ExcInvalidVectorDeclaration (i,
+                                                                    (*d)->names[i]));
+          for (unsigned int dd=1; dd<patch_space_dim; ++dd)
+            Assert ((*d)->data_component_interpretation[i+dd]
+                    ==
+                    DataComponentInterpretation::component_is_part_of_vector,
+                    Exceptions::DataOut::ExcInvalidVectorDeclaration (i,
+                                                                      (*d)->names[i]));
+
+          // all seems alright, so figure out
+          // whether there is a common name
+          // to these components. if not,
+          // leave the name empty and let the
+          // output format writer decide what
+          // to do here
+          std::string name = (*d)->names[i];
+          for (unsigned int dd=1; dd<patch_space_dim; ++dd)
+            if (name != (*d)->names[i+dd])
+              {
+                name = "";
+                break;
+              }
+
+          // finally add a corresponding
+          // range
+          std::tuple<unsigned int, unsigned int, std::string>
+          range (output_component,
+                 output_component+patch_space_dim-1,
+                 name);
+
+          ranges.push_back (range);
+
+          // increase the 'component' counter
+          // by the appropriate amount, same
+          // for 'i', since we have already
+          // dealt with all these components
+          output_component += patch_space_dim-1;
+          i += patch_space_dim-1;
+        }
+
+  // note that we do not have to traverse the
+  // list of cell data here because cell data
+  // is one value per (logical) cell and
+  // therefore cannot be a vector
+
+  // as a final check, the 'component'
+  // counter should be at the total number of
+  // components added up now
+#ifdef DEBUG
+  unsigned int n_output_components = 0;
+  for (data_iterator  d=dof_data.begin();
+       d!=dof_data.end(); ++d)
+    n_output_components += (*d)->n_output_variables;
+  Assert (output_component == n_output_components,
+          ExcInternalError());
+#endif
+
+  return ranges;
+}
+
+
+
+template <typename DoFHandlerType,
+          int patch_dim, int patch_space_dim>
+const std::vector< dealii::DataOutBase::Patch<patch_dim, patch_space_dim> > &
+DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::get_patches () const
+{
+  return patches;
+}
+
+
+
+template <typename DoFHandlerType,
+          int patch_dim, int patch_space_dim>
+std::vector<std::shared_ptr<dealii::hp::FECollection<DoFHandlerType::dimension,
+    DoFHandlerType::space_dimension> > >
+    DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::get_finite_elements() const
+{
+  const unsigned int dhdim = DoFHandlerType::dimension;
+  const unsigned int dhspacedim = DoFHandlerType::space_dimension;
+  std::vector<std::shared_ptr<dealii::hp::FECollection<dhdim,dhspacedim> > >
+  finite_elements(this->dof_data.size());
+  for (unsigned int i=0; i<this->dof_data.size(); ++i)
+    {
+      Assert (dof_data[i]->dof_handler != nullptr,
+              Exceptions::DataOut::ExcNoDoFHandlerSelected ());
+
+      // avoid creating too many finite elements and doing a lot of work on
+      // initializing FEValues downstream: if two DoFHandlers are the same
+      // (checked by pointer comparison), we can re-use the shared_ptr object
+      // for the second one. We cannot check for finite element equalities
+      // because we need different FEValues objects for different dof
+      // handlers.
+      bool duplicate = false;
+      for (unsigned int j=0; j<i; ++j)
+        if (dof_data[i]->dof_handler == dof_data[j]->dof_handler)
+          {
+            finite_elements[i] = finite_elements[j];
+            duplicate = true;
+          }
+      if (duplicate == false)
+        finite_elements[i].reset(new dealii::hp::FECollection<dhdim,dhspacedim>
+                                 (this->dof_data[i]->dof_handler->get_fe()));
+    }
+  if (this->dof_data.empty())
+    {
+      finite_elements.resize(1);
+      finite_elements[0].reset(new dealii::hp::FECollection<dhdim,dhspacedim>
+                               (FE_DGQ<dhdim,dhspacedim>(0)));
+    }
+  return finite_elements;
+}
+
+
+
+template <typename DoFHandlerType,
+          int patch_dim, int patch_space_dim>
+std::size_t
+DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::memory_consumption () const
+{
+  return (DataOutInterface<patch_dim,patch_space_dim>::memory_consumption () +
+          MemoryConsumption::memory_consumption (dofs) +
+          MemoryConsumption::memory_consumption (patches));
+}
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
index 9f1fb1f340bbf00bfa1a6740ab6540c6c9b0af6b..85bbf2fabcfd8f3458783053d42a2807a82d863e 100644 (file)
@@ -18,6 +18,7 @@ INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
 SET(_src
   data_out.cc
   data_out_dof_data.cc
+  data_out_dof_data_codim.cc
   data_out_faces.cc
   data_out_rotation.cc
   data_out_stack.cc
@@ -59,6 +60,7 @@ SET(_src
 
 SET(_inst
   data_out_dof_data.inst.in
+  data_out_dof_data_codim.inst.in
   data_out_faces.inst.in
   data_out.inst.in
   data_out_rotation.inst.in
index 00d89adee2734a69c9a592f97a6d3b8d6808616a..5ec70d1eec91783cc77fa3f103324d444e377ffd 100644 (file)
@@ -1,6 +1,6 @@
 // ---------------------------------------------------------------------
 //
-// Copyright (C) 1999 - 2016 by the deal.II authors
+// Copyright (C) 2017 by the deal.II authors
 //
 // This file is part of the deal.II library.
 //
 //
 // ---------------------------------------------------------------------
 
-#include <deal.II/base/quadrature_lib.h>
-#include <deal.II/base/work_stream.h>
-#include <deal.II/base/memory_consumption.h>
-#include <deal.II/base/std_cxx14/memory.h>
-#include <deal.II/lac/vector.h>
-#include <deal.II/lac/block_vector.h>
-#include <deal.II/lac/la_vector.h>
-#include <deal.II/lac/la_parallel_vector.h>
-#include <deal.II/lac/la_parallel_block_vector.h>
-#include <deal.II/lac/petsc_parallel_vector.h>
-#include <deal.II/lac/petsc_parallel_block_vector.h>
-#include <deal.II/lac/trilinos_vector.h>
-#include <deal.II/lac/trilinos_parallel_block_vector.h>
-#include <deal.II/lac/vector_element_access.h>
-#include <deal.II/numerics/data_out.h>
-#include <deal.II/numerics/data_out_dof_data.h>
-#include <deal.II/dofs/dof_handler.h>
-#include <deal.II/dofs/dof_accessor.h>
-#include <deal.II/grid/tria.h>
-#include <deal.II/grid/tria_iterator.h>
-#include <deal.II/fe/fe.h>
-#include <deal.II/fe/fe_dgq.h>
-#include <deal.II/fe/fe_values.h>
-#include <deal.II/hp/dof_handler.h>
-#include <deal.II/hp/fe_values.h>
-#include <deal.II/fe/mapping_q1.h>
-
-#include <sstream>
+#include <deal.II/numerics/data_out_dof_data.templates.h>
 
 DEAL_II_NAMESPACE_OPEN
 
-
-namespace internal
-{
-  namespace DataOut
-  {
-    template <int dim, int spacedim>
-    ParallelDataBase<dim,spacedim>::
-    ParallelDataBase (const unsigned int n_datasets,
-                      const unsigned int n_subdivisions,
-                      const std::vector<unsigned int> &n_postprocessor_outputs,
-                      const Mapping<dim,spacedim> &mapping,
-                      const std::vector<std::shared_ptr<dealii::hp::FECollection<dim,spacedim> > > &finite_elements,
-                      const UpdateFlags update_flags,
-                      const bool        use_face_values)
-      :
-      n_datasets (n_datasets),
-      n_subdivisions (n_subdivisions),
-      postprocessed_values (n_postprocessor_outputs.size()),
-      mapping_collection (mapping),
-      finite_elements (finite_elements),
-      update_flags (update_flags)
-    {
-      unsigned int n_q_points = 0;
-      if (use_face_values == false)
-        {
-          dealii::hp::QCollection<dim>
-          quadrature(QIterated<dim>(QTrapez<1>(), n_subdivisions));
-          n_q_points = quadrature[0].size();
-          x_fe_values.resize(this->finite_elements.size());
-          for (unsigned int i=0; i<this->finite_elements.size(); ++i)
-            {
-              // check if there is a finite element that is equal to the
-              // present one, then we can re-use the FEValues object
-              for (unsigned int j=0; j<i; ++j)
-                if (this->finite_elements[i].get() ==
-                    this->finite_elements[j].get())
-                  {
-                    x_fe_values[i] = x_fe_values[j];
-                    break;
-                  }
-              if (x_fe_values[i].get() == nullptr)
-                x_fe_values[i].reset(new dealii::hp::FEValues<dim,spacedim>
-                                     (this->mapping_collection,
-                                      *this->finite_elements[i],
-                                      quadrature,
-                                      this->update_flags));
-            }
-        }
-      else
-        {
-          dealii::hp::QCollection<dim-1>
-          quadrature(QIterated<dim-1>(QTrapez<1>(), n_subdivisions));
-          n_q_points = quadrature[0].size();
-          x_fe_face_values.resize(this->finite_elements.size());
-          for (unsigned int i=0; i<this->finite_elements.size(); ++i)
-            {
-              // check if there is a finite element that is equal to the
-              // present one, then we can re-use the FEValues object
-              for (unsigned int j=0; j<i; ++j)
-                if (this->finite_elements[i].get() ==
-                    this->finite_elements[j].get())
-                  {
-                    x_fe_face_values[i] = x_fe_face_values[j];
-                    break;
-                  }
-              if (x_fe_face_values[i].get() == nullptr)
-                x_fe_face_values[i].reset(new dealii::hp::FEFaceValues<dim,spacedim>
-                                          (this->mapping_collection,
-                                           *this->finite_elements[i],
-                                           quadrature,
-                                           this->update_flags));
-            }
-        }
-
-      patch_values_scalar.solution_values.resize (n_q_points);
-      patch_values_scalar.solution_gradients.resize (n_q_points);
-      patch_values_scalar.solution_hessians.resize (n_q_points);
-      patch_values_system.solution_values.resize (n_q_points);
-      patch_values_system.solution_gradients.resize (n_q_points);
-      patch_values_system.solution_hessians.resize (n_q_points);
-
-      for (unsigned int dataset=0; dataset<n_postprocessor_outputs.size(); ++dataset)
-        if (n_postprocessor_outputs[dataset] != 0)
-          postprocessed_values[dataset]
-          .resize(n_q_points,
-                  dealii::Vector<double>(n_postprocessor_outputs[dataset]));
-    }
-
-
-
-
-
-    // implement copy constructor to create a thread's own version of
-    // x_fe_values
-    template <int dim, int spacedim>
-    ParallelDataBase<dim,spacedim>::
-    ParallelDataBase (const ParallelDataBase<dim,spacedim> &data)
-      :
-      n_datasets (data.n_datasets),
-      n_subdivisions (data.n_subdivisions),
-      patch_values_scalar (data.patch_values_scalar),
-      patch_values_system (data.patch_values_system),
-      postprocessed_values (data.postprocessed_values),
-      mapping_collection (data.mapping_collection),
-      finite_elements (data.finite_elements),
-      update_flags (data.update_flags)
-    {
-      if (data.x_fe_values.empty() == false)
-        {
-          Assert(data.x_fe_face_values.empty() == true, ExcInternalError());
-          dealii::hp::QCollection<dim>
-          quadrature(QIterated<dim>(QTrapez<1>(), n_subdivisions));
-          x_fe_values.resize(this->finite_elements.size());
-          for (unsigned int i=0; i<this->finite_elements.size(); ++i)
-            {
-              // check if there is a finite element that is equal to the
-              // present one, then we can re-use the FEValues object
-              for (unsigned int j=0; j<i; ++j)
-                if (this->finite_elements[i].get() ==
-                    this->finite_elements[j].get())
-                  {
-                    x_fe_values[i] = x_fe_values[j];
-                    break;
-                  }
-              if (x_fe_values[i].get() == nullptr)
-                x_fe_values[i].reset(new dealii::hp::FEValues<dim,spacedim>
-                                     (this->mapping_collection,
-                                      *this->finite_elements[i],
-                                      quadrature,
-                                      this->update_flags));
-            }
-        }
-      else
-        {
-          dealii::hp::QCollection<dim-1>
-          quadrature(QIterated<dim-1>(QTrapez<1>(), n_subdivisions));
-          x_fe_face_values.resize(this->finite_elements.size());
-          for (unsigned int i=0; i<this->finite_elements.size(); ++i)
-            {
-              // check if there is a finite element that is equal to the
-              // present one, then we can re-use the FEValues object
-              for (unsigned int j=0; j<i; ++j)
-                if (this->finite_elements[i].get() ==
-                    this->finite_elements[j].get())
-                  {
-                    x_fe_face_values[i] = x_fe_face_values[j];
-                    break;
-                  }
-              if (x_fe_face_values[i].get() == nullptr)
-                x_fe_face_values[i].reset(new dealii::hp::FEFaceValues<dim,spacedim>
-                                          (this->mapping_collection,
-                                           *this->finite_elements[i],
-                                           quadrature,
-                                           this->update_flags));
-            }
-        }
-    }
-
-
-
-    template <int dim, int spacedim>
-    template <typename DoFHandlerType>
-    void
-    ParallelDataBase<dim,spacedim>::
-    reinit_all_fe_values(std::vector<std::shared_ptr<DataEntryBase<DoFHandlerType> > > &dof_data,
-                         const typename dealii::Triangulation<dim,spacedim>::cell_iterator   &cell,
-                         const unsigned int                                                   face)
-    {
-      for (unsigned int dataset=0; dataset<dof_data.size(); ++dataset)
-        {
-          bool duplicate = false;
-          for (unsigned int j=0; j<dataset; ++j)
-            if (finite_elements[dataset].get() == finite_elements[j].get())
-              duplicate = true;
-          if (duplicate == false)
-            {
-              typename DoFHandlerType::active_cell_iterator dh_cell(&cell->get_triangulation(),
-                                                                    cell->level(),
-                                                                    cell->index(),
-                                                                    dof_data[dataset]->dof_handler);
-              if (x_fe_values.empty())
-                {
-                  AssertIndexRange(face,
-                                   GeometryInfo<dim>::faces_per_cell);
-                  x_fe_face_values[dataset]->reinit(dh_cell, face);
-                }
-              else
-                x_fe_values[dataset]->reinit (dh_cell);
-            }
-        }
-      if (dof_data.empty())
-        {
-          if (x_fe_values.empty())
-            {
-              AssertIndexRange(face,
-                               GeometryInfo<dim>::faces_per_cell);
-              x_fe_face_values[0]->reinit(cell, face);
-            }
-          else
-            x_fe_values[0]->reinit (cell);
-        }
-    }
-
-
-
-    template <int dim, int spacedim>
-    const FEValuesBase<dim,spacedim> &
-    ParallelDataBase<dim,spacedim>::
-    get_present_fe_values(const unsigned int dataset) const
-    {
-      AssertIndexRange(dataset, finite_elements.size());
-      if (x_fe_values.empty())
-        return x_fe_face_values[dataset]->get_present_fe_values();
-      else
-        return x_fe_values[dataset]->get_present_fe_values();
-    }
-
-
-
-    template <int dim, int spacedim>
-    void
-    ParallelDataBase<dim,spacedim>::
-    resize_system_vectors(const unsigned int n_components)
-    {
-      Assert(patch_values_system.solution_values.size() > 0, ExcInternalError());
-      AssertDimension(patch_values_system.solution_values.size(),
-                      patch_values_system.solution_gradients.size());
-      AssertDimension(patch_values_system.solution_values.size(),
-                      patch_values_system.solution_hessians.size());
-      if (patch_values_system.solution_values[0].size() == n_components)
-        return;
-      for (unsigned int k=0; k<patch_values_system.solution_values.size(); ++k)
-        {
-          patch_values_system.solution_values[k].reinit(n_components);
-          patch_values_system.solution_gradients[k].resize(n_components);
-          patch_values_system.solution_hessians[k].resize(n_components);
-        }
-    }
-
-
-
-
-    /**
-     * In a WorkStream context, use this function to append the patch computed
-     * by the parallel stage to the array of patches.
-     */
-    template <int dim, int spacedim>
-    void
-    append_patch_to_list (const DataOutBase::Patch<dim,spacedim> &patch,
-                          std::vector<DataOutBase::Patch<dim,spacedim> > &patches)
-    {
-      patches.push_back (patch);
-      patches.back().patch_index = patches.size()-1;
-    }
-  }
-}
-
-namespace internal
-{
-  namespace DataOut
-  {
-    template <typename DoFHandlerType>
-    DataEntryBase<DoFHandlerType>::DataEntryBase
-    (const DoFHandlerType           *dofs,
-     const std::vector<std::string> &names_in,
-     const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
-      :
-      dof_handler (dofs, typeid(dealii::DataOut_DoFData<DoFHandlerType,DoFHandlerType::dimension,DoFHandlerType::space_dimension>).name()),
-      names(names_in),
-      data_component_interpretation (data_component_interpretation),
-      postprocessor(nullptr, typeid(*this).name()),
-      n_output_variables(names.size())
-    {
-      Assert (names.size() == data_component_interpretation.size(),
-              ExcDimensionMismatch(data_component_interpretation.size(),
-                                   names.size()));
-
-      // check that the names use only allowed characters
-      for (unsigned int i=0; i<names.size(); ++i)
-        Assert (names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
-                                           "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                                           "0123456789_<>()") == std::string::npos,
-                Exceptions::DataOut::ExcInvalidCharacter (names[i],
-                                                          names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
-                                                              "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                                                              "0123456789_<>()")));
-    }
-
-
-
-    template <typename DoFHandlerType>
-    DataEntryBase<DoFHandlerType>::DataEntryBase
-    (const DoFHandlerType *dofs,
-     const DataPostprocessor<DoFHandlerType::space_dimension> *data_postprocessor)
-      :
-      dof_handler (dofs, typeid(dealii::DataOut_DoFData<DoFHandlerType,DoFHandlerType::dimension,DoFHandlerType::space_dimension>).name()),
-      names(data_postprocessor->get_names()),
-      data_component_interpretation (data_postprocessor->get_data_component_interpretation()),
-      postprocessor(data_postprocessor, typeid(*this).name()),
-      n_output_variables(names.size())
-    {
-      Assert (data_postprocessor->get_names().size()
-              ==
-              data_postprocessor->get_data_component_interpretation().size(),
-              ExcDimensionMismatch (data_postprocessor->get_names().size(),
-                                    data_postprocessor->get_data_component_interpretation().size()));
-
-      // check that the names use only allowed characters
-      for (unsigned int i=0; i<names.size(); ++i)
-        Assert (names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
-                                           "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                                           "0123456789_<>()") == std::string::npos,
-                Exceptions::DataOut::ExcInvalidCharacter (names[i],
-                                                          names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
-                                                              "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                                                              "0123456789_<>()")));
-    }
-
-
-
-    template <typename DoFHandlerType>
-    DataEntryBase<DoFHandlerType>::~DataEntryBase ()
-    {}
-
-
-
-    /**
-     * Class that stores a pointer to a vector of type equal to the template
-     * argument, and provides the functions to extract data from it.
-     *
-     * @author Wolfgang Bangerth, 2004
-     */
-    template <typename DoFHandlerType, typename VectorType>
-    class DataEntry : public DataEntryBase<DoFHandlerType>
-    {
-    public:
-      /**
-       * Constructor. Give a list of names for the individual components of
-       * the vector and their interpretation as scalar or vector data. This
-       * constructor assumes that no postprocessor is going to be used.
-       */
-      DataEntry
-      (const DoFHandlerType           *dofs,
-       const VectorType               *data,
-       const std::vector<std::string> &names,
-       const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation);
-
-      /**
-       * Constructor when a data postprocessor is going to be used. In that
-       * case, the names and vector declarations are going to be acquired from
-       * the postprocessor.
-       */
-      DataEntry (const DoFHandlerType                                     *dofs,
-                 const VectorType                                         *data,
-                 const DataPostprocessor<DoFHandlerType::space_dimension> *data_postprocessor);
-
-      /**
-       * Assuming that the stored vector is a cell vector, extract the given
-       * element from it.
-       */
-      virtual
-      double
-      get_cell_data_value (const unsigned int cell_number) const;
-
-      /**
-       * Given a FEValuesBase object, extract the values on the present cell
-       * from the vector we actually store.
-       */
-      virtual
-      void
-      get_function_values
-      (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
-       std::vector<double> &patch_values) const;
-
-      /**
-       * Given a FEValuesBase object, extract the values on the present cell
-       * from the vector we actually store. This function does the same as the
-       * one above but for vector-valued finite elements.
-       */
-      virtual
-      void
-      get_function_values
-      (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
-       std::vector<dealii::Vector<double> > &patch_values_system) const;
-
-      /**
-       * Given a FEValuesBase object, extract the gradients on the present
-       * cell from the vector we actually store.
-       */
-      virtual
-      void
-      get_function_gradients
-      (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
-       std::vector<Tensor<1,DoFHandlerType::space_dimension> > &patch_gradients) const;
-
-      /**
-       * Given a FEValuesBase object, extract the gradients on the present
-       * cell from the vector we actually store. This function does the same
-       * as the one above but for vector-valued finite elements.
-       */
-      virtual
-      void
-      get_function_gradients
-      (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
-       std::vector<std::vector<Tensor<1,DoFHandlerType::space_dimension> > > &patch_gradients_system) const;
-
-      /**
-       * Given a FEValuesBase object, extract the second derivatives on the
-       * present cell from the vector we actually store.
-       */
-      virtual
-      void
-      get_function_hessians
-      (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
-       std::vector<Tensor<2,DoFHandlerType::space_dimension> > &patch_hessians) const;
-
-      /**
-       * Given a FEValuesBase object, extract the second derivatives on the
-       * present cell from the vector we actually store. This function does
-       * the same as the one above but for vector-valued finite elements.
-       */
-      virtual
-      void
-      get_function_hessians
-      (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
-       std::vector<std::vector< Tensor<2,DoFHandlerType::space_dimension> > > &patch_hessians_system) const;
-
-      /**
-       * Clear all references to the vectors.
-       */
-      virtual void clear ();
-
-      /**
-       * Determine an estimate for the memory consumption (in bytes) of this
-       * object.
-       */
-      virtual std::size_t memory_consumption () const;
-
-    private:
-      /**
-       * Pointer to the data vector. Note that ownership of the vector pointed
-       * to remains with the caller of this class.
-       */
-      const VectorType *vector;
-    };
-
-
-
-    template <typename DoFHandlerType, typename VectorType>
-    DataEntry<DoFHandlerType,VectorType>::
-    DataEntry (const DoFHandlerType           *dofs,
-               const VectorType               *data,
-               const std::vector<std::string> &names,
-               const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
-      :
-      DataEntryBase<DoFHandlerType> (dofs, names, data_component_interpretation),
-      vector (data)
-    {}
-
-
-
-    template <typename DoFHandlerType, typename VectorType>
-    DataEntry<DoFHandlerType,VectorType>::
-    DataEntry (const DoFHandlerType                                     *dofs,
-               const VectorType                                         *data,
-               const DataPostprocessor<DoFHandlerType::space_dimension> *data_postprocessor)
-      :
-      DataEntryBase<DoFHandlerType> (dofs, data_postprocessor),
-      vector (data)
-    {}
-
-
-    namespace
-    {
-      template <typename VectorType>
-      double
-      get_vector_element (const VectorType   &vector,
-                          const unsigned int  cell_number)
-      {
-        return internal::ElementAccess<VectorType>::get(vector,cell_number);
-      }
-
-
-      double
-      get_vector_element (const IndexSet &is,
-                          const unsigned int cell_number)
-      {
-        return (is.is_element(cell_number) ? 1 : 0);
-      }
-    }
-
-
-
-    template <typename DoFHandlerType, typename VectorType>
-    double
-    DataEntry<DoFHandlerType,VectorType>::
-    get_cell_data_value (const unsigned int cell_number) const
-    {
-      return get_vector_element(*vector, cell_number);
-    }
-
-
-
-    template <typename DoFHandlerType, typename VectorType>
-    void
-    DataEntry<DoFHandlerType,VectorType>::get_function_values
-    (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
-     std::vector<dealii::Vector<double> >                  &patch_values_system) const
-    {
-      // FIXME: FEValuesBase gives us data in types that match that of
-      // the solution vector. but this function needs to pass it back
-      // up as 'double' vectors. this requires the use of a temporary
-      // variable here if the data we get is not a 'double' vector.
-      // (of course, in reality, this also means that we may lose
-      // information to begin with.)
-      //
-      // the correct thing would be to also use the correct data type
-      // upstream somewhere, but this is complicated because we hide
-      // the actual data type from upstream. rather, we should at
-      // least make sure we can deal with complex numbers
-      if (typeid(typename VectorType::value_type) == typeid(double))
-        {
-          fe_patch_values.get_function_values (*vector,
-                                               // reinterpret output argument type; because of
-                                               // the 'if' statement above, this is the
-                                               // identity cast whenever the code is
-                                               // executed, but the cast is necessary
-                                               // to allow compilation even if we don't get here
-                                               reinterpret_cast<std::vector<dealii::Vector<typename VectorType::value_type> >&>
-                                               (patch_values_system));
-        }
-      else
-        {
-          std::vector<dealii::Vector<typename VectorType::value_type> > tmp(patch_values_system.size());
-          for (unsigned int i = 0; i < patch_values_system.size(); i++)
-            tmp[i].reinit(patch_values_system[i]);
-
-          fe_patch_values.get_function_values (*vector, tmp);
-
-          for (unsigned int i = 0; i < patch_values_system.size(); i++)
-            patch_values_system[i] = tmp[i];
-        }
-    }
-
-
-
-    template <typename DoFHandlerType, typename VectorType>
-    void
-    DataEntry<DoFHandlerType,VectorType>::get_function_values
-    (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
-     std::vector<double>                                   &patch_values) const
-    {
-      // FIXME: FEValuesBase gives us data in types that match that of
-      // the solution vector. but this function needs to pass it back
-      // up as 'double' vectors. this requires the use of a temporary
-      // variable here if the data we get is not a 'double' vector.
-      // (of course, in reality, this also means that we may lose
-      // information to begin with.)
-      //
-      // the correct thing would be to also use the correct data type
-      // upstream somewhere, but this is complicated because we hide
-      // the actual data type from upstream. rather, we should at
-      // least make sure we can deal with complex numbers
-      if (typeid(typename VectorType::value_type) == typeid(double))
-        {
-          fe_patch_values.get_function_values (*vector,
-                                               // reinterpret output argument type; because of
-                                               // the 'if' statement above, this is the
-                                               // identity cast whenever the code is
-                                               // executed, but the cast is necessary
-                                               // to allow compilation even if we don't get here
-                                               reinterpret_cast<std::vector<typename VectorType::value_type>&>
-                                               (patch_values));
-        }
-      else
-        {
-          std::vector<typename VectorType::value_type> tmp (patch_values.size());
-
-          fe_patch_values.get_function_values (*vector, tmp);
-
-          for (unsigned int i = 0; i < tmp.size(); i++)
-            patch_values[i] = tmp[i];
-        }
-    }
-
-
-
-    template <typename DoFHandlerType, typename VectorType>
-    void
-    DataEntry<DoFHandlerType,VectorType>::get_function_gradients
-    (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension>     &fe_patch_values,
-     std::vector<std::vector<Tensor<1,DoFHandlerType::space_dimension> > > &patch_gradients_system) const
-    {
-      // FIXME: FEValuesBase gives us data in types that match that of
-      // the solution vector. but this function needs to pass it back
-      // up as 'double' vectors. this requires the use of a temporary
-      // variable here if the data we get is not a 'double' vector.
-      // (of course, in reality, this also means that we may lose
-      // information to begin with.)
-      //
-      // the correct thing would be to also use the correct data type
-      // upstream somewhere, but this is complicated because we hide
-      // the actual data type from upstream. rather, we should at
-      // least make sure we can deal with complex numbers
-      if (typeid(typename VectorType::value_type) == typeid(double))
-        {
-          fe_patch_values.get_function_gradients (*vector,
-                                                  // reinterpret output argument type; because of
-                                                  // the 'if' statement above, this is the
-                                                  // identity cast whenever the code is
-                                                  // executed, but the cast is necessary
-                                                  // to allow compilation even if we don't get here
-                                                  reinterpret_cast<std::vector<std::vector<Tensor<1,DoFHandlerType::space_dimension,typename VectorType::value_type> > >&>
-                                                  (patch_gradients_system));
-        }
-      else
-        {
-          std::vector<std::vector<Tensor<1,DoFHandlerType::space_dimension,
-              typename VectorType::value_type> > >
-              tmp(patch_gradients_system.size());
-          for (unsigned int i = 0; i < tmp.size(); i++)
-            tmp[i].resize(patch_gradients_system[i].size());
-
-          fe_patch_values.get_function_gradients (*vector, tmp);
-
-          for (unsigned int i = 0; i < tmp.size(); i++)
-            for (unsigned int j = 0; j < tmp[i].size(); j++)
-              patch_gradients_system[i][j] = tmp[i][j];
-        }
-    }
-
-
-
-    template <typename DoFHandlerType, typename VectorType>
-    void
-    DataEntry<DoFHandlerType,VectorType>::get_function_gradients
-    (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
-     std::vector<Tensor<1,DoFHandlerType::space_dimension> >           &patch_gradients) const
-    {
-      // FIXME: FEValuesBase gives us data in types that match that of
-      // the solution vector. but this function needs to pass it back
-      // up as 'double' vectors. this requires the use of a temporary
-      // variable here if the data we get is not a 'double' vector.
-      // (of course, in reality, this also means that we may lose
-      // information to begin with.)
-      //
-      // the correct thing would be to also use the correct data type
-      // upstream somewhere, but this is complicated because we hide
-      // the actual data type from upstream. rather, we should at
-      // least make sure we can deal with complex numbers
-      if (typeid(typename VectorType::value_type) == typeid(double))
-        {
-          fe_patch_values.get_function_gradients (*vector,
-                                                  // reinterpret output argument type; because of
-                                                  // the 'if' statement above, this is the
-                                                  // identity cast whenever the code is
-                                                  // executed, but the cast is necessary
-                                                  // to allow compilation even if we don't get here
-                                                  reinterpret_cast<std::vector<Tensor<1,DoFHandlerType::space_dimension,typename VectorType::value_type> >&>
-                                                  (patch_gradients));
-        }
-      else
-        {
-          std::vector<Tensor<1,DoFHandlerType::space_dimension,typename VectorType::value_type> >  tmp;
-          tmp.resize(patch_gradients.size());
-
-          fe_patch_values.get_function_gradients (*vector, tmp);
-
-          for (unsigned int i = 0; i < tmp.size(); i++)
-            patch_gradients[i] = tmp[i];
-        }
-    }
-
-
-
-    template <typename DoFHandlerType, typename VectorType>
-    void
-    DataEntry<DoFHandlerType,VectorType>::get_function_hessians
-    (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
-     std::vector<std::vector<Tensor<2,DoFHandlerType::space_dimension> > > &patch_hessians_system) const
-    {
-      // FIXME: FEValuesBase gives us data in types that match that of
-      // the solution vector. but this function needs to pass it back
-      // up as 'double' vectors. this requires the use of a temporary
-      // variable here if the data we get is not a 'double' vector.
-      // (of course, in reality, this also means that we may lose
-      // information to begin with.)
-      //
-      // the correct thing would be to also use the correct data type
-      // upstream somewhere, but this is complicated because we hide
-      // the actual data type from upstream. rather, we should at
-      // least make sure we can deal with complex numbers
-      if (typeid(typename VectorType::value_type) == typeid(double))
-        {
-          fe_patch_values.get_function_hessians (*vector,
-                                                 // reinterpret output argument type; because of
-                                                 // the 'if' statement above, this is the
-                                                 // identity cast whenever the code is
-                                                 // executed, but the cast is necessary
-                                                 // to allow compilation even if we don't get here
-                                                 reinterpret_cast<std::vector<std::vector<Tensor<2,DoFHandlerType::space_dimension,typename VectorType::value_type> > >&>
-                                                 (patch_hessians_system));
-        }
-      else
-        {
-          std::vector<std::vector<Tensor<2,DoFHandlerType::space_dimension,
-              typename VectorType::value_type> > >
-              tmp(patch_hessians_system.size());
-          for (unsigned int i = 0; i < tmp.size(); i++)
-            tmp[i].resize(patch_hessians_system[i].size());
-
-          fe_patch_values.get_function_hessians (*vector, tmp);
-
-          for (unsigned int i = 0; i < tmp.size(); i++)
-            for (unsigned int j = 0; j < tmp[i].size(); j++)
-              patch_hessians_system[i][j] = tmp[i][j];
-        }
-    }
-
-
-
-    template <typename DoFHandlerType, typename VectorType>
-    void
-    DataEntry<DoFHandlerType,VectorType>::get_function_hessians
-    (const FEValuesBase<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &fe_patch_values,
-     std::vector<Tensor<2,DoFHandlerType::space_dimension> >                       &patch_hessians) const
-    {
-      // FIXME: FEValuesBase gives us data in types that match that of
-      // the solution vector. but this function needs to pass it back
-      // up as 'double' vectors. this requires the use of a temporary
-      // variable here if the data we get is not a 'double' vector.
-      // (of course, in reality, this also means that we may lose
-      // information to begin with.)
-      //
-      // the correct thing would be to also use the correct data type
-      // upstream somewhere, but this is complicated because we hide
-      // the actual data type from upstream. rather, we should at
-      // least make sure we can deal with complex numbers
-      if (typeid(typename VectorType::value_type) == typeid(double))
-        {
-          fe_patch_values.get_function_hessians (*vector,
-                                                 // reinterpret output argument type; because of
-                                                 // the 'if' statement above, this is the
-                                                 // identity cast whenever the code is
-                                                 // executed, but the cast is necessary
-                                                 // to allow compilation even if we don't get here
-                                                 reinterpret_cast<std::vector<Tensor<2,DoFHandlerType
-                                                 ::space_dimension,typename VectorType::value_type> >&>
-                                                 (patch_hessians));
-        }
-      else
-        {
-          std::vector<Tensor<2,DoFHandlerType::space_dimension,typename VectorType::value_type> >
-          tmp(patch_hessians.size());
-
-          fe_patch_values.get_function_hessians (*vector, tmp);
-
-          for (unsigned int i = 0; i < tmp.size(); i++)
-            patch_hessians[i] = tmp[i];
-        }
-    }
-
-
-
-    template <typename DoFHandlerType, typename VectorType>
-    std::size_t
-    DataEntry<DoFHandlerType,VectorType>::memory_consumption () const
-    {
-      return (sizeof (vector) +
-              MemoryConsumption::memory_consumption (this->names));
-    }
-
-
-
-    template <typename DoFHandlerType, typename VectorType>
-    void
-    DataEntry<DoFHandlerType,VectorType>::clear ()
-    {
-      vector = nullptr;
-      this->dof_handler = nullptr;
-    }
-  }
-}
-
-
-
-template <typename DoFHandlerType,
-          int patch_dim, int patch_space_dim>
-DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::DataOut_DoFData ()
-  :
-  triangulation(nullptr,typeid(*this).name()),
-  dofs(nullptr,typeid(*this).name())
-{}
-
-
-
-template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
-DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::~DataOut_DoFData ()
-{
-  clear ();
-}
-
-
-
-template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
-void
-DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::
-attach_dof_handler (const DoFHandlerType &d)
-{
-  Assert (dof_data.size() == 0,
-          Exceptions::DataOut::ExcOldDataStillPresent());
-  Assert (cell_data.size() == 0,
-          Exceptions::DataOut::ExcOldDataStillPresent());
-
-  triangulation = SmartPointer<const Triangulation<DoFHandlerType::dimension,
-  DoFHandlerType::space_dimension> >
-  (&d.get_triangulation(), typeid(*this).name());
-  dofs = SmartPointer<const DoFHandlerType>(&d, typeid(*this).name());
-}
-
-
-
-template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
-void
-DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::
-attach_triangulation (const Triangulation<DoFHandlerType::dimension,DoFHandlerType::space_dimension> &tria)
-{
-  Assert (dof_data.size() == 0,
-          Exceptions::DataOut::ExcOldDataStillPresent());
-  Assert (cell_data.size() == 0,
-          Exceptions::DataOut::ExcOldDataStillPresent());
-
-  triangulation = SmartPointer<const Triangulation<DoFHandlerType::dimension,
-  DoFHandlerType::space_dimension> >
-  (&tria, typeid(*this).name());
-}
-
-
-
-template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
-template <typename VectorType>
-void
-DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::
-add_data_vector (const DoFHandlerType                   &dof_handler,
-                 const VectorType                       &vec,
-                 const DataPostprocessor<DoFHandlerType::space_dimension> &data_postprocessor)
-{
-  // this is a specialized version of the other function where we have a
-  // postprocessor. if we do, we know that we have type_dof_data, which makes
-  // things a bit simpler, we also don't need to deal with some of the other
-  // stuff and use a different constructor of DataEntry
-  if (triangulation != nullptr)
-    {
-      Assert (&dof_handler.get_triangulation() == triangulation,
-              ExcMessage("The triangulation attached to the DoFHandler does not "
-                         "match with the one set previously"));
-    }
-  else
-    {
-      triangulation = SmartPointer<const Triangulation<DoFHandlerType::dimension,DoFHandlerType::space_dimension>>
-        (&dof_handler.get_triangulation(), typeid(*this).name());
-    }
-
-  Assert (vec.size() == dof_handler.n_dofs(),
-          Exceptions::DataOut::ExcInvalidVectorSize (vec.size(),
-                                                     dof_handler.n_dofs(),
-                                                     dof_handler.get_triangulation().n_active_cells()));
-
-
-  auto new_entry = std_cxx14::make_unique<internal::DataOut::DataEntry<DoFHandlerType,VectorType>>
-                   (&dof_handler, &vec, &data_postprocessor);
-  dof_data.emplace_back (std::move(new_entry));
-}
-
-
-
-template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
-template <typename VectorType>
-void
-DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::
-add_data_vector_internal
-(const DoFHandlerType           *dof_handler,
- const VectorType               &data_vector,
- const std::vector<std::string> &names,
- const DataVectorType            type,
- const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation_,
- const bool                      deduce_output_names)
-{
-  // Check available mesh information:
-  if (triangulation == nullptr)
-    {
-      Assert(dof_handler != nullptr, ExcInternalError());
-      triangulation = SmartPointer<const Triangulation<DoFHandlerType::dimension,DoFHandlerType::space_dimension>>
-                      (&dof_handler->get_triangulation(), typeid(*this).name());
-    }
-
-  if (dof_handler != nullptr)
-    {
-      Assert (&dof_handler->get_triangulation() == triangulation,
-              ExcMessage("The triangulation attached to the DoFHandler does not "
-                         "match with the one set previously"));
-    }
-
-  // Figure out the data type:
-  DataVectorType actual_type = type;
-  if (type == type_automatic)
-    {
-      Assert((dof_handler == nullptr) || (triangulation->n_active_cells() != dof_handler->n_dofs()),
-             ExcMessage("Unable to determine the type of vector automatically because the number of DoFs "
-                        "is equal to the number of cells. Please specify DataVectorType."));
-
-      if (data_vector.size() == triangulation->n_active_cells())
-        actual_type = type_cell_data;
-      else
-        actual_type = type_dof_data;
-    }
-  Assert(actual_type == type_cell_data || actual_type == type_dof_data,
-         ExcInternalError());
-
-  // If necessary, append '_1', '_2', etc. to component names:
-  std::vector<std::string> deduced_names;
-  if (deduce_output_names && actual_type == type_dof_data)
-    {
-      Assert(names.size() == 1, ExcInternalError());
-      Assert(dof_handler != nullptr, ExcInternalError());
-      Assert(dof_handler->n_dofs() > 0,
-             ExcMessage("The DoF handler attached to the current output vector "
-                        "does not have any degrees of freedom, so it is not "
-                        "possible to output DoF data in this context."));
-      const std::string name = names[0];
-      const unsigned int n_components = dof_handler->get_fe().n_components();
-      deduced_names.resize (n_components);
-      if (n_components > 1)
-        {
-          for (unsigned int i=0; i<n_components; ++i)
-            {
-              deduced_names[i] = name + '_' + Utilities::to_string(i);
-            }
-        }
-      else
-        {
-          deduced_names[0] = name;
-        }
-    }
-  else
-    {
-      deduced_names = names;
-    }
-
-  // Check that things have the right sizes for the data type:
-  switch (actual_type)
-    {
-    case type_cell_data:
-      Assert (data_vector.size() == triangulation->n_active_cells(),
-              ExcDimensionMismatch (data_vector.size(),
-                                    triangulation->n_active_cells()));
-      Assert (deduced_names.size() == 1,
-              Exceptions::DataOut::ExcInvalidNumberOfNames (deduced_names.size(), 1));
-      break;
-    case type_dof_data:
-      Assert (dof_handler != nullptr,
-              Exceptions::DataOut::ExcNoDoFHandlerSelected ());
-      Assert (data_vector.size() == dof_handler->n_dofs(),
-              Exceptions::DataOut::ExcInvalidVectorSize (data_vector.size(),
-                                                         dof_handler->n_dofs(),
-                                                         triangulation->n_active_cells()));
-      Assert (deduced_names.size() == dof_handler->get_fe().n_components(),
-              Exceptions::DataOut::ExcInvalidNumberOfNames (deduced_names.size(),
-                                                            dof_handler->get_fe().n_components()));
-      break;
-    default:
-      Assert (false, ExcInternalError());
-    }
-
-  const auto &data_component_interpretation
-    = (data_component_interpretation_.size() != 0
-       ?
-       data_component_interpretation_
-       :
-       std::vector<DataComponentInterpretation::DataComponentInterpretation>
-       (deduced_names.size(), DataComponentInterpretation::component_is_scalar));
-
-  // finally, add the data vector:
-  auto new_entry = std_cxx14::make_unique<internal::DataOut::DataEntry<DoFHandlerType,VectorType>>
-                   (dof_handler, &data_vector, deduced_names, data_component_interpretation);
-
-  if (actual_type == type_dof_data)
-    dof_data.emplace_back (std::move(new_entry));
-  else
-    cell_data.emplace_back (std::move(new_entry));
-}
-
-
-
-template <typename DoFHandlerType,
-          int patch_dim, int patch_space_dim>
-void DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::clear_data_vectors ()
-{
-  dof_data.erase (dof_data.begin(), dof_data.end());
-  cell_data.erase (cell_data.begin(), cell_data.end());
-
-  // delete patches
-  std::vector<Patch> dummy;
-  patches.swap (dummy);
-}
-
-
-
-template <typename DoFHandlerType,
-          int patch_dim, int patch_space_dim>
-void
-DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::
-clear_input_data_references ()
-{
-  for (unsigned int i=0; i<dof_data.size(); ++i)
-    dof_data[i]->clear ();
-
-  for (unsigned int i=0; i<cell_data.size(); ++i)
-    cell_data[i]->clear ();
-
-  if (dofs != nullptr)
-    dofs = nullptr;
-}
-
-
-
-template <typename DoFHandlerType,
-          int patch_dim, int patch_space_dim>
-void
-DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::clear ()
-{
-  dof_data.erase (dof_data.begin(), dof_data.end());
-  cell_data.erase (cell_data.begin(), cell_data.end());
-
-  if (dofs != nullptr)
-    dofs = nullptr;
-
-  // delete patches
-  std::vector<Patch> dummy;
-  patches.swap (dummy);
-}
-
-
-
-template <typename DoFHandlerType,
-          int patch_dim, int patch_space_dim>
-std::vector<std::string>
-DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::
-get_dataset_names () const
-{
-  std::vector<std::string> names;
-  // collect the names of dof
-  // and cell data
-  typedef
-  typename std::vector<std::shared_ptr<internal::DataOut::DataEntryBase<DoFHandlerType> > >::const_iterator
-  data_iterator;
-
-  for (data_iterator  d=dof_data.begin();
-       d!=dof_data.end(); ++d)
-    for (unsigned int i=0; i<(*d)->names.size(); ++i)
-      names.push_back ((*d)->names[i]);
-  for (data_iterator d=cell_data.begin(); d!=cell_data.end(); ++d)
-    {
-      Assert ((*d)->names.size() == 1, ExcInternalError());
-      names.push_back ((*d)->names[0]);
-    }
-
-  return names;
-}
-
-
-
-template <typename DoFHandlerType,
-          int patch_dim, int patch_space_dim>
-std::vector<std::tuple<unsigned int, unsigned int, std::string> >
-DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::get_vector_data_ranges () const
-{
-  std::vector<std::tuple<unsigned int, unsigned int, std::string> >
-  ranges;
-
-  // collect the ranges of dof
-  // and cell data
-  typedef
-  typename std::vector<std::shared_ptr<internal::DataOut::DataEntryBase<DoFHandlerType> > >::const_iterator
-  data_iterator;
-
-  unsigned int output_component = 0;
-  for (data_iterator  d=dof_data.begin();
-       d!=dof_data.end(); ++d)
-    for (unsigned int i=0; i<(*d)->n_output_variables;
-         ++i, ++output_component)
-      // see what kind of data we have
-      // here. note that for the purpose of
-      // the current function all we care
-      // about is vector data
-      if ((*d)->data_component_interpretation[i] ==
-          DataComponentInterpretation::component_is_part_of_vector)
-        {
-          // ensure that there is a
-          // continuous number of next
-          // space_dim components that all
-          // deal with vectors
-          Assert (i+patch_space_dim <=
-                  (*d)->n_output_variables,
-                  Exceptions::DataOut::ExcInvalidVectorDeclaration (i,
-                                                                    (*d)->names[i]));
-          for (unsigned int dd=1; dd<patch_space_dim; ++dd)
-            Assert ((*d)->data_component_interpretation[i+dd]
-                    ==
-                    DataComponentInterpretation::component_is_part_of_vector,
-                    Exceptions::DataOut::ExcInvalidVectorDeclaration (i,
-                                                                      (*d)->names[i]));
-
-          // all seems alright, so figure out
-          // whether there is a common name
-          // to these components. if not,
-          // leave the name empty and let the
-          // output format writer decide what
-          // to do here
-          std::string name = (*d)->names[i];
-          for (unsigned int dd=1; dd<patch_space_dim; ++dd)
-            if (name != (*d)->names[i+dd])
-              {
-                name = "";
-                break;
-              }
-
-          // finally add a corresponding
-          // range
-          std::tuple<unsigned int, unsigned int, std::string>
-          range (output_component,
-                 output_component+patch_space_dim-1,
-                 name);
-
-          ranges.push_back (range);
-
-          // increase the 'component' counter
-          // by the appropriate amount, same
-          // for 'i', since we have already
-          // dealt with all these components
-          output_component += patch_space_dim-1;
-          i += patch_space_dim-1;
-        }
-
-  // note that we do not have to traverse the
-  // list of cell data here because cell data
-  // is one value per (logical) cell and
-  // therefore cannot be a vector
-
-  // as a final check, the 'component'
-  // counter should be at the total number of
-  // components added up now
-#ifdef DEBUG
-  unsigned int n_output_components = 0;
-  for (data_iterator  d=dof_data.begin();
-       d!=dof_data.end(); ++d)
-    n_output_components += (*d)->n_output_variables;
-  Assert (output_component == n_output_components,
-          ExcInternalError());
-#endif
-
-  return ranges;
-}
-
-
-
-template <typename DoFHandlerType,
-          int patch_dim, int patch_space_dim>
-const std::vector< dealii::DataOutBase::Patch<patch_dim, patch_space_dim> > &
-DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::get_patches () const
-{
-  return patches;
-}
-
-
-
-template <typename DoFHandlerType,
-          int patch_dim, int patch_space_dim>
-std::vector<std::shared_ptr<dealii::hp::FECollection<DoFHandlerType::dimension,
-    DoFHandlerType::space_dimension> > >
-    DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::get_finite_elements() const
-{
-  const unsigned int dhdim = DoFHandlerType::dimension;
-  const unsigned int dhspacedim = DoFHandlerType::space_dimension;
-  std::vector<std::shared_ptr<dealii::hp::FECollection<dhdim,dhspacedim> > >
-  finite_elements(this->dof_data.size());
-  for (unsigned int i=0; i<this->dof_data.size(); ++i)
-    {
-      Assert (dof_data[i]->dof_handler != nullptr,
-              Exceptions::DataOut::ExcNoDoFHandlerSelected ());
-
-      // avoid creating too many finite elements and doing a lot of work on
-      // initializing FEValues downstream: if two DoFHandlers are the same
-      // (checked by pointer comparison), we can re-use the shared_ptr object
-      // for the second one. We cannot check for finite element equalities
-      // because we need different FEValues objects for different dof
-      // handlers.
-      bool duplicate = false;
-      for (unsigned int j=0; j<i; ++j)
-        if (dof_data[i]->dof_handler == dof_data[j]->dof_handler)
-          {
-            finite_elements[i] = finite_elements[j];
-            duplicate = true;
-          }
-      if (duplicate == false)
-        finite_elements[i].reset(new dealii::hp::FECollection<dhdim,dhspacedim>
-                                 (this->dof_data[i]->dof_handler->get_fe()));
-    }
-  if (this->dof_data.empty())
-    {
-      finite_elements.resize(1);
-      finite_elements[0].reset(new dealii::hp::FECollection<dhdim,dhspacedim>
-                               (FE_DGQ<dhdim,dhspacedim>(0)));
-    }
-  return finite_elements;
-}
-
-
-
-template <typename DoFHandlerType,
-          int patch_dim, int patch_space_dim>
-std::size_t
-DataOut_DoFData<DoFHandlerType,patch_dim,patch_space_dim>::memory_consumption () const
-{
-  return (DataOutInterface<patch_dim,patch_space_dim>::memory_consumption () +
-          MemoryConsumption::memory_consumption (dofs) +
-          MemoryConsumption::memory_consumption (patches));
-}
-
-
-// explicit instantiations
 #include "data_out_dof_data.inst"
 
 DEAL_II_NAMESPACE_CLOSE
index 32bf5f57fd6fc9e45251c04d66d372b70b4641b4..8ceb65aacb4cc66e81b048092f74b2362026e1d2 100644 (file)
@@ -1,6 +1,6 @@
 // ---------------------------------------------------------------------
 //
-// Copyright (C) 2010 - 2016 by the deal.II authors
+// Copyright (C) 2010 - 2017 by the deal.II authors
 //
 // This file is part of the deal.II library.
 //
@@ -16,8 +16,6 @@
 
 for (VEC : REAL_SERIAL_VECTORS; DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
 {
-// codim=0
-
     template void
     DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
     add_data_vector_internal<VEC> (const DH<deal_II_dimension,deal_II_dimension> *,
@@ -72,56 +70,12 @@ for (VEC : REAL_SERIAL_VECTORS; DH : DOFHANDLER_TEMPLATES; deal_II_dimension : D
                           const VEC                 &,
                           const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
 #endif
-
-
-// codim 1
-
-#if deal_II_dimension < 3
-    template void
-    DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
-    add_data_vector_internal<VEC> (const DH<deal_II_dimension,deal_II_dimension+1> *,
-                                   const VEC                       &,
-                                   const std::vector<std::string> &,
-                                   const DataVectorType,
-                                   const std::vector<DataComponentInterpretation::DataComponentInterpretation> &,
-                                   const bool);
-
-    template void
-    DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
-    add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_dimension+1> &,
-                          const VEC                 &,
-                          const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension+1>::space_dimension> &);
-#endif
-
-
-
-// codim 2
-
-#if deal_II_dimension == 3
-    template void
-    DataOut_DoFData<DH<1,3>,1,3>::
-      add_data_vector_internal<VEC> (const DH<1, 3> *,
-                                     const VEC                       &,
-                                     const std::vector<std::string> &,
-                                     const DataVectorType,
-                                     const std::vector<DataComponentInterpretation::DataComponentInterpretation> &,
-                                     const bool);
-
-    template void
-    DataOut_DoFData<DH<1,3>,1,3>::
-    add_data_vector<VEC> (const DH<1,3> &,
-                          const VEC                 &,
-                          const DataPostprocessor<DH<1,3>::space_dimension> &);
-#endif
-
 }
 
 
 
 for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
 {
-// codim=0
-
     template void
     DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
     add_data_vector_internal<IndexSet> (const DH<deal_II_dimension,deal_II_dimension> *,
@@ -133,9 +87,9 @@ for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
 
     template void
     DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension>,deal_II_dimension,deal_II_dimension>::
-      add_data_vector<IndexSet> (const DH<deal_II_dimension, deal_II_dimension> &,
-                                 const IndexSet                 &,
-                                 const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
+    add_data_vector<IndexSet> (const DH<deal_II_dimension, deal_II_dimension> &,
+                               const IndexSet                 &,
+                               const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
 
 
 
@@ -174,26 +128,6 @@ for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
                                const IndexSet                 &,
                                const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension>::space_dimension> &);
 #endif
-
-// codim 1
-
-#if deal_II_dimension < 3
-    template void
-    DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
-    add_data_vector_internal<IndexSet> (const DH<deal_II_dimension,deal_II_dimension+1> *,
-                                        const IndexSet                       &,
-                                        const std::vector<std::string> &,
-                                        const DataVectorType,
-                                        const std::vector<DataComponentInterpretation::DataComponentInterpretation> &,
-                                        const bool);
-
-    template void
-    DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>::
-    add_data_vector<IndexSet> (const DH<deal_II_dimension, deal_II_dimension+1> &,
-                               const IndexSet                 &,
-                               const DataPostprocessor<DH<deal_II_dimension,deal_II_dimension+1>::space_dimension> &);
-#endif
-
 }
 
 
@@ -205,7 +139,6 @@ for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
 #if deal_II_dimension < 3
     template class DataOut_DoFData<DH<deal_II_dimension>,deal_II_dimension+1>;
     template class DataOut_DoFData<DH<deal_II_dimension>,deal_II_dimension,deal_II_dimension+1>;
-    template class DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>;
 #endif
 
 #if deal_II_dimension >= 2
@@ -214,37 +147,32 @@ for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
 
 #if deal_II_dimension == 3
     template class DataOut_DoFData<DH<1>,1,3>;
-    template class DataOut_DoFData<DH<1,3>,1,3>;
 #endif
 
 }
 
 
-for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : DIMENSIONS)
+for (deal_II_dimension : DIMENSIONS)
 {
     namespace internal \{
     namespace DataOut \{
-#if deal_II_dimension <= deal_II_space_dimension
-    template struct ParallelDataBase<deal_II_dimension,deal_II_space_dimension>;
-#endif
+    template struct ParallelDataBase<deal_II_dimension,deal_II_dimension>;
     \}
     \}
 }
 
 
-for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : DIMENSIONS)
+for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
 {
     namespace internal \{
     namespace DataOut \{
-#if deal_II_dimension <= deal_II_space_dimension
     template
     void
-    ParallelDataBase<deal_II_dimension,deal_II_space_dimension>::
-    reinit_all_fe_values<dealii::DH<deal_II_dimension,deal_II_space_dimension> >
-    (std::vector<std::shared_ptr<DataEntryBase<dealii::DH<deal_II_dimension,deal_II_space_dimension> > > > &dof_data,
-     const dealii::Triangulation<deal_II_dimension,deal_II_space_dimension>::cell_iterator &cell,
+    ParallelDataBase<deal_II_dimension,deal_II_dimension>::
+    reinit_all_fe_values<dealii::DH<deal_II_dimension,deal_II_dimension> >
+    (std::vector<std::shared_ptr<DataEntryBase<dealii::DH<deal_II_dimension,deal_II_dimension> > > > &dof_data,
+     const dealii::Triangulation<deal_II_dimension,deal_II_dimension>::cell_iterator &cell,
      const unsigned int face);
-#endif
     \}
     \}
 }
diff --git a/source/numerics/data_out_dof_data_codim.cc b/source/numerics/data_out_dof_data_codim.cc
new file mode 100644 (file)
index 0000000..bbb244d
--- /dev/null
@@ -0,0 +1,22 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2017 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/numerics/data_out_dof_data.templates.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+#include "data_out_dof_data_codim.inst"
+
+DEAL_II_NAMESPACE_CLOSE
diff --git a/source/numerics/data_out_dof_data_codim.inst.in b/source/numerics/data_out_dof_data_codim.inst.in
new file mode 100644 (file)
index 0000000..f7e709b
--- /dev/null
@@ -0,0 +1,106 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2010 - 2017 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 : REAL_SERIAL_VECTORS; DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : DIMENSIONS)
+{
+#if deal_II_dimension < deal_II_space_dimension
+    template void
+    DataOut_DoFData<DH<deal_II_dimension,deal_II_space_dimension>,deal_II_dimension,deal_II_space_dimension>::
+    add_data_vector_internal<VEC> (const DH<deal_II_dimension,deal_II_space_dimension> *,
+                                   const VEC                       &,
+                                   const std::vector<std::string> &,
+                                   const DataVectorType,
+                                   const std::vector<DataComponentInterpretation::DataComponentInterpretation> &,
+                                   const bool);
+
+    template void
+    DataOut_DoFData<DH<deal_II_dimension,deal_II_space_dimension>,deal_II_dimension,deal_II_space_dimension>::
+    add_data_vector<VEC> (const VEC                 &,
+                          const DataPostprocessor<DH<deal_II_dimension,deal_II_space_dimension>::space_dimension> &);
+
+    template void
+    DataOut_DoFData<DH<deal_II_dimension,deal_II_space_dimension>,deal_II_dimension,deal_II_space_dimension>::
+    add_data_vector<VEC> (const DH<deal_II_dimension,deal_II_space_dimension> &,
+                          const VEC                 &,
+                          const DataPostprocessor<DH<deal_II_dimension,deal_II_space_dimension>::space_dimension> &);
+#endif
+}
+
+
+
+for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : DIMENSIONS)
+{
+#if deal_II_dimension < deal_II_space_dimension
+    template void
+    DataOut_DoFData<DH<deal_II_dimension,deal_II_space_dimension>,deal_II_dimension,deal_II_space_dimension>::
+    add_data_vector_internal<IndexSet>
+    (const DH<deal_II_dimension,deal_II_space_dimension> *,
+     const IndexSet                 &,
+     const std::vector<std::string> &,
+     const DataVectorType,
+     const std::vector<DataComponentInterpretation::DataComponentInterpretation> &,
+     const bool);
+
+    template void
+    DataOut_DoFData<DH<deal_II_dimension,deal_II_space_dimension>,deal_II_dimension,deal_II_space_dimension>::
+    add_data_vector<IndexSet> (const IndexSet                 &,
+                               const DataPostprocessor<DH<deal_II_dimension,deal_II_space_dimension>::space_dimension> &);
+#endif
+}
+
+
+
+for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS)
+{
+#if deal_II_dimension < 3
+    template class DataOut_DoFData<DH<deal_II_dimension,deal_II_dimension+1>,deal_II_dimension,deal_II_dimension+1>;
+#endif
+
+#if deal_II_dimension == 3
+    template class DataOut_DoFData<DH<1,3>,1,3>;
+#endif
+
+}
+
+
+for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : DIMENSIONS)
+{
+    namespace internal \{
+    namespace DataOut \{
+#if deal_II_dimension < deal_II_space_dimension
+    template struct ParallelDataBase<deal_II_dimension,deal_II_space_dimension>;
+#endif
+    \}
+    \}
+}
+
+
+for (DH : DOFHANDLER_TEMPLATES; deal_II_dimension : DIMENSIONS; deal_II_space_dimension : DIMENSIONS)
+{
+    namespace internal \{
+    namespace DataOut \{
+#if deal_II_dimension < deal_II_space_dimension
+    template
+    void
+    ParallelDataBase<deal_II_dimension,deal_II_space_dimension>::
+    reinit_all_fe_values<dealii::DH<deal_II_dimension,deal_II_space_dimension> >
+    (std::vector<std::shared_ptr<DataEntryBase<dealii::DH<deal_II_dimension,deal_II_space_dimension> > > > &dof_data,
+     const dealii::Triangulation<deal_II_dimension,deal_II_space_dimension>::cell_iterator &cell,
+     const unsigned int face);
+#endif
+    \}
+    \}
+}

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.