From 955d01cfe5e90af8b4249bc7e37e1193e918c328 Mon Sep 17 00:00:00 2001
From: Jean-Paul Pelteret <jppelteret@gmail.com>
Date: Thu, 10 Aug 2017 17:01:29 -0600
Subject: [PATCH] Added
 SymmetricTensor::get_function_values_from_local_dof_values

---
 include/deal.II/fe/fe_values.h | 45 ++++++++++++++++++++++++++++++++++
 source/fe/fe_values.cc         | 20 +++++++++++++++
 source/fe/fe_values.inst.in    |  7 ++++++
 3 files changed, 72 insertions(+)

diff --git a/include/deal.II/fe/fe_values.h b/include/deal.II/fe/fe_values.h
index 6711ca8a42..060a02dfa0 100644
--- a/include/deal.II/fe/fe_values.h
+++ b/include/deal.II/fe/fe_values.h
@@ -1144,6 +1144,26 @@ namespace FEValuesViews
      */
     typedef dealii::Tensor<1, spacedim> divergence_type;
 
+    /**
+     * A struct that provides the output type for the product of the value
+     * and derivatives of basis functions of the SymmetricTensor view and any @p Number type.
+     */
+    template <typename Number>
+    struct OutputType
+    {
+      /**
+       * A typedef for the data type of the product of a @p Number and the
+       * values of the view the SymmetricTensor class.
+       */
+      typedef typename ProductType<typename std::remove_cv<Number>::type, typename SymmetricTensor<2,dim,spacedim>::value_type>::type value_type;
+
+      /**
+       * A typedef for the data type of the product of a @p Number and the
+       * divergences of the view the SymmetricTensor class.
+       */
+      typedef typename ProductType<typename std::remove_cv<Number>::type, typename SymmetricTensor<2,dim,spacedim>::divergence_type>::type divergence_type;
+    };
+
     /**
      * A structure where for each shape function we pre-compute a bunch of
      * data that will make later accesses much cheaper.
@@ -1266,6 +1286,31 @@ namespace FEValuesViews
     void get_function_values (const InputVector &fe_function,
                               std::vector<typename ProductType<value_type,typename InputVector::value_type>::type> &values) const;
 
+    /**
+     * Same as above, but using a vector of local degree-of-freedom values.
+     *
+     * The @p dof_values vector must have a length equal to number of DoFs on
+     * a cell, and  each entry @p dof_values[i] is the value of the local DoF
+     * @p i. The fundamental prerequisite for the @p InputVector is that it must
+     * be possible to create an ArrayView from it; this is satisfied by the
+     * @p std::vector class.
+     *
+     * The DoF values typically would be obtained in the following way:
+     * @code
+     * Vector<double> local_dof_values(cell->get_fe().dofs_per_cell);
+     * cell->get_dof_values(solution, local_dof_values);
+     * @endcode
+     * or, for a generic @p Number type,
+     * @code
+     * std::vector<Number> local_dof_values(cell->get_fe().dofs_per_cell);
+     * cell->get_dof_values(solution, local_dof_values.begin(), local_dof_values.end());
+     * @endcode
+     */
+    template <class InputVector>
+    void get_function_values_from_local_dof_values (const InputVector &dof_values,
+                                                    std::vector<typename OutputType<typename InputVector::value_type>::value_type> &values) const;
+
+
     /**
      * Return the divergence of the selected vector components of the finite
      * element function characterized by <tt>fe_function</tt> at the
diff --git a/source/fe/fe_values.cc b/source/fe/fe_values.cc
index 1109991033..7a074e468f 100644
--- a/source/fe/fe_values.cc
+++ b/source/fe/fe_values.cc
@@ -1870,6 +1870,26 @@ namespace FEValuesViews
 
 
 
+  template <int dim, int spacedim>
+  template <class InputVector>
+  void
+  SymmetricTensor<2, dim, spacedim>::
+  get_function_values_from_local_dof_values(const InputVector &dof_values,
+                                            std::vector<typename OutputType<typename InputVector::value_type>::value_type> &values) const
+  {
+    Assert(fe_values->update_flags & update_values,
+           (typename FEValuesBase<dim,spacedim>::ExcAccessToUninitializedField("update_values")));
+    Assert(fe_values->present_cell.get() != nullptr,
+           ExcMessage("FEValues object is not reinit'ed to any cell"));
+    AssertDimension (dof_values.size(), fe_values->dofs_per_cell);
+
+    internal::do_function_values<dim,spacedim>
+    (make_array_view(dof_values.begin(), dof_values.end()),
+     fe_values->finite_element_output.shape_values, shape_function_data, values);
+  }
+
+
+
   template <int dim, int spacedim>
   template <class InputVector>
   void
diff --git a/source/fe/fe_values.inst.in b/source/fe/fe_values.inst.in
index 75f90d0c49..4d700e47f1 100644
--- a/source/fe/fe_values.inst.in
+++ b/source/fe/fe_values.inst.in
@@ -211,6 +211,13 @@ for (VEC : GENERAL_CONTAINER_TYPES;
     void FEValuesViews::Vector<deal_II_dimension, deal_II_space_dimension>
     ::get_function_third_derivatives_from_local_dof_values<VEC<Number>>
             (const VEC<Number>&, std::vector<typename OutputType<Number>::third_derivative_type>&) const;
+
+
+
+    template
+    void FEValuesViews::SymmetricTensor<2,deal_II_dimension, deal_II_space_dimension>
+    ::get_function_values_from_local_dof_values<VEC<Number>>
+            (const VEC<Number>&, std::vector<typename OutputType<Number>::value_type>&) const;
 #endif
 }
 
-- 
2.39.5