]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Modify hessian computations from numerical to analytical differentiation
authorMaien Hamed <tomaien@hotmail.com>
Mon, 10 Aug 2015 21:16:06 +0000 (23:16 +0200)
committerMaien Hamed <tomaien@hotmail.com>
Mon, 10 Aug 2015 23:08:53 +0000 (01:08 +0200)
include/deal.II/fe/fe_poly.h
include/deal.II/fe/fe_poly.templates.h
include/deal.II/fe/fe_system.h
source/fe/fe_poly.cc
source/fe/fe_system.cc
source/fe/mapping_cartesian.cc

index cbbb80b7aedef1bd96afa360785e93a402ab2b30..cd962adbdf7c5d00938101bbd5a93fda08b315e6 100644 (file)
@@ -248,7 +248,6 @@ protected:
    */
   virtual UpdateFlags update_each (const UpdateFlags flags) const;
 
-
   /**
    * Fields of cell-independent data.
    *
@@ -279,8 +278,42 @@ protected:
      * multiplication) when visiting an actual cell.
      */
     std::vector<std::vector<Tensor<1,dim> > > shape_gradients;
+
+    /**
+     * Array with shape function hessians in quadrature points. There is one
+     * row for each shape function, containing values for each quadrature
+     * point.
+     *
+     * We store the hessians in the quadrature points on the unit cell. We
+     * then only have to apply the transformation when visiting an actual cell.
+     */
+    std::vector<std::vector<Tensor<2,dim> > > shape_hessians;
+
+    /**
+     * Scratch array to store temporary values during hessian calculations in
+     * actual cells.
+     */
+    mutable std::vector<Tensor<2,dim> > untransformed_shape_hessians;
   };
 
+  /**
+   * Correct the hessian in the reference cell by subtracting the term corresponding
+   * to the Jacobian gradient for one degree of freedom. The result being given by:
+   *
+   * \frac{\partial^2 \phi_i}{\partial\hat{x}_J\partial\hat{x}_K}
+   * - \frac{\partial \phi_i}{\partial {x}_l}
+   * \left( \frac{\partial^2{x}_l}{\partial\hat{x}_J\partial\hat{x}_K} \right)
+   *
+   * After this correction, the shape hessians are simply a mapping_covariant_gradient
+   * transformation.
+   */
+  void
+  correct_untransformed_hessians (VectorSlice< std::vector<Tensor<2, dim> > >                       uncorrected_shape_hessians,
+                                  const internal::FEValues::MappingRelatedData<dim,spacedim>       &mapping_data,
+                                  const internal::FEValues::FiniteElementRelatedData<dim,spacedim> &fevalues_data,
+                                  const unsigned int                                                n_q_points,
+                                  const unsigned int                                                dof) const;
+
   /**
    * The polynomial space. Its type is given by the template parameter POLY.
    */
index cb751ef28d93d0fa203da1a312656fa6b8076dfc..d93c690e5867f1986b4cf0609a87cc40ee747c74 100644 (file)
@@ -150,7 +150,8 @@ FE_Poly<POLY,dim,spacedim>::update_each (const UpdateFlags flags) const
   if (flags & update_gradients)
     out |= update_gradients | update_covariant_transformation;
   if (flags & update_hessians)
-    out |= update_hessians | update_covariant_transformation;
+    out |= update_hessians | update_covariant_transformation
+           | update_gradients | update_jacobian_grads;
   if (flags & update_cell_normal_vectors)
     out |= update_cell_normal_vectors | update_JxW_values;
 
@@ -166,7 +167,7 @@ FE_Poly<POLY,dim,spacedim>::update_each (const UpdateFlags flags) const
 template <class POLY, int dim, int spacedim>
 typename FiniteElement<dim,spacedim>::InternalDataBase *
 FE_Poly<POLY,dim,spacedim>::get_data (const UpdateFlags      update_flags,
-                                      const Mapping<dim,spacedim>    &mapping,
+                                      const Mapping<dim,spacedim> &,
                                       const Quadrature<dim> &quadrature) const
 {
   // generate a new data object and
@@ -211,7 +212,12 @@ FE_Poly<POLY,dim,spacedim>::get_data (const UpdateFlags      update_flags,
   // then initialize some objects for
   // that
   if (flags & update_hessians)
-    data->initialize_2nd (this, mapping, quadrature);
+    {
+      grad_grads.resize (this->dofs_per_cell);
+      data->shape_hessians.resize (this->dofs_per_cell,
+                                   std::vector<Tensor<2,dim> > (n_q_points));
+      data->untransformed_shape_hessians.resize (n_q_points);
+    }
 
   // next already fill those fields
   // of which we have information by
@@ -220,7 +226,7 @@ FE_Poly<POLY,dim,spacedim>::get_data (const UpdateFlags      update_flags,
   // unit cell, and need to be
   // transformed when visiting an
   // actual cell
-  if (flags & (update_values | update_gradients))
+  if (flags & (update_values | update_gradients | update_hessians))
     for (unsigned int i=0; i<n_q_points; ++i)
       {
         poly_space.compute(quadrature.point(i),
@@ -233,6 +239,10 @@ FE_Poly<POLY,dim,spacedim>::get_data (const UpdateFlags      update_flags,
         if (flags & update_gradients)
           for (unsigned int k=0; k<this->dofs_per_cell; ++k)
             data->shape_gradients[k][i] = grads[k];
+
+        if (flags & update_hessians)
+          for (unsigned int k=0; k<this->dofs_per_cell; ++k)
+            data->shape_hessians[k][i] = grad_grads[k];
       }
   return data;
 }
@@ -248,14 +258,14 @@ FE_Poly<POLY,dim,spacedim>::get_data (const UpdateFlags      update_flags,
 template <class POLY, int dim, int spacedim>
 void
 FE_Poly<POLY,dim,spacedim>::
-fill_fe_values (const Mapping<dim,spacedim>                      &mapping,
-                const typename Triangulation<dim,spacedim>::cell_iterator &cell,
-                const Quadrature<dim>                            &quadrature,
-                const typename Mapping<dim,spacedim>::InternalDataBase &mapping_internal,
+fill_fe_values (const Mapping<dim,spacedim>                                  &mapping,
+                const typename Triangulation<dim,spacedim>::cell_iterator &,
+                const Quadrature<dim>                                        &quadrature,
+                const typename Mapping<dim,spacedim>::InternalDataBase       &mapping_internal,
                 const typename FiniteElement<dim,spacedim>::InternalDataBase &fedata,
-                const internal::FEValues::MappingRelatedData<dim,spacedim> &,
-                internal::FEValues::FiniteElementRelatedData<dim,spacedim> &output_data,
-                const CellSimilarity::Similarity                  cell_similarity) const
+                const internal::FEValues::MappingRelatedData<dim,spacedim>   &mapping_data,
+                internal::FEValues::FiniteElementRelatedData<dim,spacedim>   &output_data,
+                const CellSimilarity::Similarity                              cell_similarity) const
 {
   // convert data object to internal
   // data for this class. fails with
@@ -276,12 +286,23 @@ fill_fe_values (const Mapping<dim,spacedim>                      &mapping,
         mapping.transform(fe_data.shape_gradients[k],
                           output_data.shape_gradients[k],
                           mapping_internal, mapping_covariant);
-    }
 
-  if (flags & update_hessians && cell_similarity != CellSimilarity::translation)
-    this->compute_2nd (mapping, cell, QProjector<dim>::DataSetDescriptor::cell(),
-                       mapping_internal, fe_data,
-                       output_data);
+      if (flags & update_hessians && cell_similarity != CellSimilarity::translation)
+        {
+          // compute the hessians in the unit cell (accounting for the Jacobian gradiant)
+          for (unsigned int i=0; i<quadrature.size(); ++i)
+            {
+              fe_data.untransformed_shape_hessians[i] = fe_data.shape_hessians[k][i];
+            }
+
+          correct_untransformed_hessians (fe_data.untransformed_shape_hessians,
+                                          mapping_data, output_data, quadrature.size(), k);
+
+          mapping.transform(fe_data.untransformed_shape_hessians,
+                            output_data.shape_hessians[k],
+                            mapping_internal, mapping_covariant_gradient);
+        }
+    }
 }
 
 
@@ -289,14 +310,14 @@ fill_fe_values (const Mapping<dim,spacedim>                      &mapping,
 template <class POLY, int dim, int spacedim>
 void
 FE_Poly<POLY,dim,spacedim>::
-fill_fe_face_values (const Mapping<dim,spacedim>                   &mapping,
-                     const typename Triangulation<dim,spacedim>::cell_iterator &cell,
-                     const unsigned int                    face,
-                     const Quadrature<dim-1>              &quadrature,
+fill_fe_face_values (const Mapping<dim,spacedim>                                  &mapping,
+                     const typename Triangulation<dim,spacedim>::cell_iterator    &cell,
+                     const unsigned int                                            face,
+                     const Quadrature<dim-1>                                      &quadrature,
                      const typename Mapping<dim,spacedim>::InternalDataBase       &mapping_internal,
-                     const typename FiniteElement<dim,spacedim>::InternalDataBase       &fedata,
-                     const internal::FEValues::MappingRelatedData<dim,spacedim> &,
-                     internal::FEValues::FiniteElementRelatedData<dim,spacedim> &output_data) const
+                     const typename FiniteElement<dim,spacedim>::InternalDataBase &fedata,
+                     const internal::FEValues::MappingRelatedData<dim,spacedim>   &mapping_data,
+                     internal::FEValues::FiniteElementRelatedData<dim,spacedim>   &output_data) const
 {
   // convert data object to internal
   // data for this class. fails with
@@ -328,27 +349,37 @@ fill_fe_face_values (const Mapping<dim,spacedim>                   &mapping,
         mapping.transform(make_slice(fe_data.shape_gradients[k], offset, quadrature.size()),
                           output_data.shape_gradients[k],
                           mapping_internal, mapping_covariant);
-    }
 
-  if (flags & update_hessians)
-    this->compute_2nd (mapping, cell, offset, mapping_internal, fe_data,
-                       output_data);
+      if (flags & update_hessians)
+        {
+          // compute the hessians in the unit cell (accounting for the Jacobian gradiant)
+          for (unsigned int i=0; i<quadrature.size(); ++i)
+            {
+              fe_data.untransformed_shape_hessians[i+offset] = fe_data.shape_hessians[k][i+offset];
+            }
+
+          correct_untransformed_hessians(VectorSlice< std::vector<Tensor<2,dim> > >
+                                         ( fe_data.untransformed_shape_hessians, offset , quadrature.size()),
+                                         mapping_data, output_data, quadrature.size(), k);
+
+          mapping.transform(make_slice(fe_data.untransformed_shape_hessians, offset, quadrature.size()),
+                            output_data.shape_hessians[k], mapping_internal, mapping_covariant_gradient);
+        }
+    }
 }
 
-
-
 template <class POLY, int dim, int spacedim>
 void
 FE_Poly<POLY,dim,spacedim>::
-fill_fe_subface_values (const Mapping<dim,spacedim>                   &mapping,
-                        const typename Triangulation<dim,spacedim>::cell_iterator &cell,
-                        const unsigned int                    face,
-                        const unsigned int                    subface,
-                        const Quadrature<dim-1>              &quadrature,
+fill_fe_subface_values (const Mapping<dim,spacedim>                                  &mapping,
+                        const typename Triangulation<dim,spacedim>::cell_iterator    &cell,
+                        const unsigned int                                            face,
+                        const unsigned int                                            subface,
+                        const Quadrature<dim-1>                                      &quadrature,
                         const typename Mapping<dim,spacedim>::InternalDataBase       &mapping_internal,
-                        const typename FiniteElement<dim,spacedim>::InternalDataBase       &fedata,
-                        const internal::FEValues::MappingRelatedData<dim,spacedim> &,
-                        internal::FEValues::FiniteElementRelatedData<dim,spacedim> &output_data) const
+                        const typename FiniteElement<dim,spacedim>::InternalDataBase &fedata,
+                        const internal::FEValues::MappingRelatedData<dim,spacedim>   &mapping_data,
+                        internal::FEValues::FiniteElementRelatedData<dim,spacedim>   &output_data) const
 {
   // convert data object to internal
   // data for this class. fails with
@@ -381,14 +412,42 @@ fill_fe_subface_values (const Mapping<dim,spacedim>                   &mapping,
         mapping.transform(make_slice(fe_data.shape_gradients[k], offset, quadrature.size()),
                           output_data.shape_gradients[k],
                           mapping_internal, mapping_covariant);
-    }
 
-  if (flags & update_hessians)
-    this->compute_2nd (mapping, cell, offset, mapping_internal, fe_data,
-                       output_data);
+      if (flags & update_hessians)
+        {
+          // compute the hessians in the unit cell (accounting for the Jacobian gradiant)
+          for (unsigned int i=0; i<quadrature.size(); ++i)
+            {
+              fe_data.untransformed_shape_hessians[i+offset] = fe_data.shape_hessians[k][i+offset];
+            }
+
+          correct_untransformed_hessians(VectorSlice< std::vector<Tensor<2,dim> > >
+                                         ( fe_data.untransformed_shape_hessians, offset , quadrature.size()),
+                                         mapping_data, output_data, quadrature.size(), k);
+
+          mapping.transform(make_slice(fe_data.untransformed_shape_hessians, offset, quadrature.size()),
+                            output_data.shape_hessians[k], mapping_internal, mapping_covariant_gradient);
+        }
+    }
 }
 
 
+template <class POLY, int dim, int spacedim>
+void
+FE_Poly<POLY,dim,spacedim>::
+correct_untransformed_hessians (VectorSlice< std::vector<Tensor<2, dim> > >                       uncorrected_shape_hessians,
+                                const internal::FEValues::MappingRelatedData<dim,spacedim>       &mapping_data,
+                                const internal::FEValues::FiniteElementRelatedData<dim,spacedim> &fevalues_data,
+                                const unsigned int                                                n_q_points,
+                                const unsigned int                                                dof) const
+{
+  for (unsigned int i=0; i<n_q_points; ++i)
+    for (unsigned int j=0; j<dim; ++j)
+      for (unsigned int l=0; l<dim; ++l)
+        for (unsigned int n=0; n<spacedim; ++n)
+          uncorrected_shape_hessians[i][j][l] -= fevalues_data.shape_gradients[dof][i][n]
+                                                 * mapping_data.jacobian_grads[i][n][l][j];
+}
 
 namespace internal
 {
index 5daa5fb99e61167a35fba677c4c106f888cb3fde..bec17c437a7d588d8f2d5bcb0f0f9285fbcdfaa0 100644 (file)
@@ -1055,11 +1055,9 @@ private:
   public:
     /**
      * Constructor. Is called by the @p get_data function. Sets the size of
-     * the @p base_fe_datas vector to @p n_base_elements and initializes the
-     * compute_hessians field.
+     * the @p base_fe_datas vector to @p n_base_elements.
      */
-    InternalData (const unsigned int n_base_elements,
-                  const bool         compute_hessians);
+    InternalData (const unsigned int n_base_elements);
 
     /**
      * Destructor. Deletes all @p InternalDatas whose pointers are stored by
@@ -1067,11 +1065,6 @@ private:
      */
     ~InternalData();
 
-    /**
-     * Flag indicating whether second derivatives shall be computed.
-     */
-    const bool compute_hessians;
-
     /**
      * Gives write-access to the pointer to a @p InternalData of the @p
      * base_noth base element.
index adbc06393012d19bb823dcd57f0ed4511d79f1ff..147b4eb984aac45cfcb9c245d9adb65d8332d635 100644 (file)
@@ -21,7 +21,6 @@
 #include <deal.II/base/polynomials_piecewise.h>
 #include <deal.II/fe/fe_poly.h>
 #include <deal.II/fe/fe_values.h>
-
 #include <deal.II/fe/fe_poly.templates.h>
 
 DEAL_II_NAMESPACE_OPEN
@@ -30,14 +29,14 @@ DEAL_II_NAMESPACE_OPEN
 template <>
 void
 FE_Poly<TensorProductPolynomials<1>,1,2>::
-fill_fe_values (const Mapping<1,2>                        &mapping,
-                const Triangulation<1,2>::cell_iterator   &cell,
-                const Quadrature<1>                       &quadrature,
-                const Mapping<1,2>::InternalDataBase            &mapping_internal,
-                const FiniteElement<1,2>::InternalDataBase            &fedata,
-                const internal::FEValues::MappingRelatedData<1,2> &,
+fill_fe_values (const Mapping<1,2>                                &mapping,
+                const Triangulation<1,2>::cell_iterator &,
+                const Quadrature<1>                               &quadrature,
+                const Mapping<1,2>::InternalDataBase              &mapping_internal,
+                const FiniteElement<1,2>::InternalDataBase        &fedata,
+                const internal::FEValues::MappingRelatedData<1,2> &mapping_data,
                 internal::FEValues::FiniteElementRelatedData<1,2> &output_data,
-                const CellSimilarity::Similarity           cell_similarity) const
+                const CellSimilarity::Similarity                  cell_similarity) const
 {
   // convert data object to internal
   // data for this class. fails with
@@ -58,12 +57,23 @@ fill_fe_values (const Mapping<1,2>                        &mapping,
         mapping.transform(fe_data.shape_gradients[k],
                           output_data.shape_gradients[k],
                           mapping_internal, mapping_covariant);
-    }
 
-  if (flags & update_hessians && cell_similarity != CellSimilarity::translation)
-    this->compute_2nd (mapping, cell, QProjector<1>::DataSetDescriptor::cell(),
-                       mapping_internal, fe_data,
-                       output_data);
+      if (flags & update_hessians && cell_similarity != CellSimilarity::translation)
+        {
+          // compute the hessians in the unit cell (accounting for the Jacobian gradiant)
+          for (unsigned int i=0; i<quadrature.size(); ++i)
+            {
+              fe_data.untransformed_shape_hessians[i] = fe_data.shape_hessians[k][i];
+            }
+
+          correct_untransformed_hessians (fe_data.untransformed_shape_hessians,
+                                          mapping_data, output_data, quadrature.size(), k);
+
+          mapping.transform(fe_data.untransformed_shape_hessians,
+                            output_data.shape_hessians[k],
+                            mapping_internal, mapping_covariant_gradient);
+        }
+    }
 }
 
 
@@ -71,14 +81,14 @@ fill_fe_values (const Mapping<1,2>                        &mapping,
 template <>
 void
 FE_Poly<TensorProductPolynomials<2>,2,3>::
-fill_fe_values (const Mapping<2,3>                      &mapping,
-                const Triangulation<2,3>::cell_iterator &cell,
-                const Quadrature<2>                     &quadrature,
-                const Mapping<2,3>::InternalDataBase          &mapping_internal,
-                const FiniteElement<2,3>::InternalDataBase          &fedata,
-                const internal::FEValues::MappingRelatedData<2,3> &,
+fill_fe_values (const Mapping<2,3>                                &mapping,
+                const Triangulation<2,3>::cell_iterator &,
+                const Quadrature<2>                               &quadrature,
+                const Mapping<2,3>::InternalDataBase              &mapping_internal,
+                const FiniteElement<2,3>::InternalDataBase        &fedata,
+                const internal::FEValues::MappingRelatedData<2,3> &mapping_data,
                 internal::FEValues::FiniteElementRelatedData<2,3> &output_data,
-                const CellSimilarity::Similarity         cell_similarity) const
+                const CellSimilarity::Similarity                  cell_similarity) const
 {
 
   // assert that the following dynamics
@@ -98,26 +108,37 @@ fill_fe_values (const Mapping<2,3>                      &mapping,
         mapping.transform(fe_data.shape_gradients[k],
                           output_data.shape_gradients[k],
                           mapping_internal, mapping_covariant);
-    }
 
-  if (flags & update_hessians && cell_similarity != CellSimilarity::translation)
-    this->compute_2nd (mapping, cell, QProjector<2>::DataSetDescriptor::cell(),
-                       mapping_internal, fe_data,
-                       output_data);
+      if (flags & update_hessians && cell_similarity != CellSimilarity::translation)
+        {
+          // compute the hessians in the unit cell (accounting for the Jacobian gradiant)
+          for (unsigned int i=0; i<quadrature.size(); ++i)
+            {
+              fe_data.untransformed_shape_hessians[i] = fe_data.shape_hessians[k][i];
+            }
+
+          correct_untransformed_hessians (fe_data.untransformed_shape_hessians,
+                                          mapping_data, output_data, quadrature.size(), k);
+
+          mapping.transform(fe_data.untransformed_shape_hessians,
+                            output_data.shape_hessians[k],
+                            mapping_internal, mapping_covariant_gradient);
+        }
+    }
 }
 
 
 template <>
 void
 FE_Poly<PolynomialSpace<1>,1,2>::
-fill_fe_values (const Mapping<1,2>                      &mapping,
-                const Triangulation<1,2>::cell_iterator &cell,
-                const Quadrature<1>                     &quadrature,
-                const Mapping<1,2>::InternalDataBase          &mapping_internal,
-                const FiniteElement<1,2>::InternalDataBase          &fedata,
-                const internal::FEValues::MappingRelatedData<1,2> &,
+fill_fe_values (const Mapping<1,2>                                &mapping,
+                const Triangulation<1,2>::cell_iterator &,
+                const Quadrature<1>                               &quadrature,
+                const Mapping<1,2>::InternalDataBase              &mapping_internal,
+                const FiniteElement<1,2>::InternalDataBase        &fedata,
+                const internal::FEValues::MappingRelatedData<1,2> &mapping_data,
                 internal::FEValues::FiniteElementRelatedData<1,2> &output_data,
-                const CellSimilarity::Similarity         cell_similarity) const
+                const CellSimilarity::Similarity                  cell_similarity) const
 {
   // convert data object to internal
   // data for this class. fails with
@@ -139,26 +160,37 @@ fill_fe_values (const Mapping<1,2>                      &mapping,
         mapping.transform(fe_data.shape_gradients[k],
                           output_data.shape_gradients[k],
                           mapping_internal, mapping_covariant);
-    }
 
-  if (flags & update_hessians && cell_similarity != CellSimilarity::translation)
-    this->compute_2nd (mapping, cell, QProjector<1>::DataSetDescriptor::cell(),
-                       mapping_internal, fe_data,
-                       output_data);
+      if (flags & update_hessians && cell_similarity != CellSimilarity::translation)
+        {
+          // compute the hessians in the unit cell (accounting for the Jacobian gradiant)
+          for (unsigned int i=0; i<quadrature.size(); ++i)
+            {
+              fe_data.untransformed_shape_hessians[i] = fe_data.shape_hessians[k][i];
+            }
+
+          correct_untransformed_hessians (fe_data.untransformed_shape_hessians,
+                                          mapping_data, output_data, quadrature.size(), k);
+
+          mapping.transform(fe_data.untransformed_shape_hessians,
+                            output_data.shape_hessians[k],
+                            mapping_internal, mapping_covariant_gradient);
+        }
+    }
 }
 
 
 template <>
 void
 FE_Poly<PolynomialSpace<2>,2,3>::
-fill_fe_values (const Mapping<2,3>                      &mapping,
-                const Triangulation<2,3>::cell_iterator &cell,
-                const Quadrature<2>                     &quadrature,
-                const Mapping<2,3>::InternalDataBase          &mapping_internal,
-                const FiniteElement<2,3>::InternalDataBase          &fedata,
-                const internal::FEValues::MappingRelatedData<2,3> &,
+fill_fe_values (const Mapping<2,3>                                &mapping,
+                const Triangulation<2,3>::cell_iterator &,
+                const Quadrature<2>                               &quadrature,
+                const Mapping<2,3>::InternalDataBase              &mapping_internal,
+                const FiniteElement<2,3>::InternalDataBase        &fedata,
+                const internal::FEValues::MappingRelatedData<2,3> &mapping_data,
                 internal::FEValues::FiniteElementRelatedData<2,3> &output_data,
-                const CellSimilarity::Similarity         cell_similarity) const
+                const CellSimilarity::Similarity                  cell_similarity) const
 {
   Assert (dynamic_cast<const InternalData *> (&fedata) != 0, ExcInternalError());
   const InternalData &fe_data = static_cast<const InternalData &> (fedata);
@@ -176,12 +208,23 @@ fill_fe_values (const Mapping<2,3>                      &mapping,
         mapping.transform(fe_data.shape_gradients[k],
                           output_data.shape_gradients[k],
                           mapping_internal, mapping_covariant);
-    }
 
-  if (flags & update_hessians && cell_similarity != CellSimilarity::translation)
-    this->compute_2nd (mapping, cell, QProjector<2>::DataSetDescriptor::cell(),
-                       mapping_internal, fe_data,
-                       output_data);
+      if (flags & update_hessians && cell_similarity != CellSimilarity::translation)
+        {
+          // compute the hessians in the unit cell (accounting for the Jacobian gradiant)
+          for (unsigned int i=0; i<quadrature.size(); ++i)
+            {
+              fe_data.untransformed_shape_hessians[i] = fe_data.shape_hessians[k][i];
+            }
+
+          correct_untransformed_hessians (fe_data.untransformed_shape_hessians,
+                                          mapping_data, output_data, quadrature.size(), k);
+
+          mapping.transform(fe_data.untransformed_shape_hessians,
+                            output_data.shape_hessians[k],
+                            mapping_internal, mapping_covariant_gradient);
+        }
+    }
 }
 
 
index c9d60cfda3846f626d1028ca084da2a3d912602b..cb0883360d774ec4017ee0ffae68eeb438442df5 100644 (file)
@@ -45,10 +45,8 @@ namespace
 
 
 template <int dim, int spacedim>
-FESystem<dim,spacedim>::InternalData::InternalData(const unsigned int n_base_elements,
-                                                   const bool         compute_hessians)
+FESystem<dim,spacedim>::InternalData::InternalData(const unsigned int n_base_elements)
   :
-  compute_hessians (compute_hessians),
   base_fe_datas(n_base_elements),
   base_fe_output_objects(n_base_elements)
 {}
@@ -792,18 +790,6 @@ FESystem<dim,spacedim>::update_each (const UpdateFlags flags) const
   for (unsigned int base_no=0; base_no<this->n_base_elements(); ++base_no)
     out |= base_element(base_no).update_each(flags);
 
-  // second derivatives are handled
-  // by the top-level finite element,
-  // rather than by the base elements
-  // since it is generated by finite
-  // differencing. if second
-  // derivatives are requested, we
-  // therefore have to set the
-  // respective flag since the base
-  // elements don't have them
-  if (flags & update_hessians)
-    out |= update_hessians | update_covariant_transformation;
-
   return out;
 }
 
@@ -816,27 +802,12 @@ FESystem<dim,spacedim>::get_data (const UpdateFlags      flags_,
                                   const Quadrature<dim> &quadrature) const
 {
   UpdateFlags flags = flags_;
-  InternalData *data = new InternalData(this->n_base_elements(),
-                                        flags & update_hessians);
+  InternalData *data = new InternalData(this->n_base_elements());
 
   data->update_once = update_once (flags);
   data->update_each = update_each (flags);
   flags = data->update_once | data->update_each;
 
-  UpdateFlags sub_flags = flags;
-  // if second derivatives through
-  // finite differencing are required,
-  // then initialize some objects for
-  // that
-  if (data->compute_hessians)
-    {
-      // delete
-      // update_hessians
-      // from flags list
-      sub_flags = UpdateFlags (sub_flags ^ update_hessians);
-      data->initialize_2nd (this, mapping, quadrature);
-    }
-
   // get data objects from each of
   // the base elements and store them
   for (unsigned int base_no=0; base_no<this->n_base_elements(); ++base_no)
@@ -844,7 +815,7 @@ FESystem<dim,spacedim>::get_data (const UpdateFlags      flags_,
       // create internal objects for base elements and initialize their
       // respective output objects
       typename FiniteElement<dim,spacedim>::InternalDataBase *base_fe_data =
-        base_element(base_no).get_data(sub_flags, mapping, quadrature);
+        base_element(base_no).get_data(flags, mapping, quadrature);
 
       internal::FEValues::FiniteElementRelatedData<dim,spacedim> &base_fe_output_object
         = data->get_fe_output_object(base_no);
@@ -853,14 +824,6 @@ FESystem<dim,spacedim>::get_data (const UpdateFlags      flags_,
 
       // then store the pointer to the base internal object
       data->set_fe_data(base_no, base_fe_data);
-
-      // make sure that *we* compute
-      // second derivatives, base
-      // elements should not do it
-      Assert (!(base_fe_data->update_each & update_hessians),
-              ExcInternalError());
-      Assert (!(base_fe_data->update_once & update_hessians),
-              ExcInternalError());
     }
   data->update_flags = data->update_once |
                        data->update_each;
@@ -878,26 +841,18 @@ FESystem<dim,spacedim>::get_face_data (
   const Quadrature<dim-1> &quadrature) const
 {
   UpdateFlags flags = flags_;
-  InternalData *data = new InternalData(this->n_base_elements(),
-                                        flags & update_hessians);
+  InternalData *data = new InternalData(this->n_base_elements());
 
   data->update_once = update_once (flags);
   data->update_each = update_each (flags);
   flags = data->update_once | data->update_each;
 
-  UpdateFlags sub_flags = flags;
-  if (data->compute_hessians)
-    {
-      sub_flags = UpdateFlags (sub_flags ^ update_hessians);
-      data->initialize_2nd (this, mapping, QProjector<dim>::project_to_all_faces(quadrature));
-    }
-
   for (unsigned int base_no=0; base_no<this->n_base_elements(); ++base_no)
     {
       // create internal objects for base elements and initialize their
       // respective output objects
       typename FiniteElement<dim,spacedim>::InternalDataBase *base_fe_data =
-        base_element(base_no).get_face_data(sub_flags, mapping, quadrature);
+        base_element(base_no).get_face_data(flags, mapping, quadrature);
 
       internal::FEValues::FiniteElementRelatedData<dim,spacedim> &base_fe_output_object
         = data->get_fe_output_object(base_no);
@@ -906,11 +861,6 @@ FESystem<dim,spacedim>::get_face_data (
 
       // then store the pointer to the base internal object
       data->set_fe_data(base_no, base_fe_data);
-
-      Assert (!(base_fe_data->update_each & update_hessians),
-              ExcInternalError());
-      Assert (!(base_fe_data->update_once & update_hessians),
-              ExcInternalError());
     }
   data->update_flags = data->update_once |
                        data->update_each;
@@ -930,26 +880,18 @@ FESystem<dim,spacedim>::get_subface_data (
   const Quadrature<dim-1> &quadrature) const
 {
   UpdateFlags flags = flags_;
-  InternalData *data = new InternalData(this->n_base_elements(),
-                                        flags & update_hessians);
+  InternalData *data = new InternalData(this->n_base_elements());
 
   data->update_once = update_once (flags);
   data->update_each = update_each (flags);
   flags = data->update_once | data->update_each;
 
-  UpdateFlags sub_flags = flags;
-  if (data->compute_hessians)
-    {
-      sub_flags = UpdateFlags (sub_flags ^ update_hessians);
-      data->initialize_2nd (this, mapping, QProjector<dim>::project_to_all_subfaces(quadrature));
-    }
-
   for (unsigned int base_no=0; base_no<this->n_base_elements(); ++base_no)
     {
       // create internal objects for base elements and initialize their
       // respective output objects
       typename FiniteElement<dim,spacedim>::InternalDataBase *base_fe_data =
-        base_element(base_no).get_subface_data(sub_flags, mapping, quadrature);
+        base_element(base_no).get_subface_data(flags, mapping, quadrature);
 
       internal::FEValues::FiniteElementRelatedData<dim,spacedim> &base_fe_output_object
         = data->get_fe_output_object(base_no);
@@ -958,11 +900,6 @@ FESystem<dim,spacedim>::get_subface_data (
 
       // then store the pointer to the base internal object
       data->set_fe_data(base_no, base_fe_data);
-
-      Assert (!(base_fe_data->update_each & update_hessians),
-              ExcInternalError());
-      Assert (!(base_fe_data->update_once & update_hessians),
-              ExcInternalError());
     }
   data->update_flags = data->update_once |
                        data->update_each;
@@ -1161,10 +1098,11 @@ compute_fill_one_base (const Mapping<dim,spacedim>                      &mapping
                   output_data.shape_gradients[out_index+s][q] =
                     base_data.shape_gradients[in_index+s][q];
 
-              // _we_ handle computation of second derivatives, so the
-              // base elements should not have computed them!
-              Assert (!(base_flags & update_hessians),
-                      ExcInternalError());
+              if (base_flags & update_hessians)
+                for (unsigned int q=0; q<n_q_points; ++q)
+                  output_data.shape_hessians[out_index+s][q] =
+                    base_data.shape_hessians[in_index+s][q];
+
             }
         }
 }
@@ -1180,14 +1118,12 @@ compute_fill (const Mapping<dim,spacedim>                      &mapping,
               const unsigned int                                face_no,
               const unsigned int                                sub_no,
               const Quadrature<dim_1>                          &quadrature,
-              const CellSimilarity::Similarity                   cell_similarity,
+              const CellSimilarity::Similarity                 ,
               const typename Mapping<dim,spacedim>::InternalDataBase &mapping_internal,
               const typename FiniteElement<dim,spacedim>::InternalDataBase &fedata,
               const internal::FEValues::MappingRelatedData<dim,spacedim> &mapping_data,
               internal::FEValues::FiniteElementRelatedData<dim,spacedim> &output_data) const
 {
-  const unsigned int n_q_points = quadrature.size();
-
   // convert data object to internal
   // data for this class. fails with
   // an exception if that is not
@@ -1204,7 +1140,7 @@ compute_fill (const Mapping<dim,spacedim>                      &mapping,
                           fe_data.update_flags);
 
 
-  if (flags & (update_values | update_gradients))
+  if (flags & (update_values | update_gradients | update_hessians))
     {
       // let base elements update the necessary data
       Threads::TaskGroup<> task_group;
@@ -1223,32 +1159,6 @@ compute_fill (const Mapping<dim,spacedim>                      &mapping,
                                                            std_cxx11::ref(output_data))));
       task_group.join_all();
     }
-
-  if (fe_data.compute_hessians && cell_similarity != CellSimilarity::translation)
-    {
-      unsigned int offset = 0;
-      if (face_no != invalid_face_number)
-        {
-          if (sub_no == invalid_face_number)
-            offset=QProjector<dim>::DataSetDescriptor
-                   ::face(face_no,
-                          cell->face_orientation(face_no),
-                          cell->face_flip(face_no),
-                          cell->face_rotation(face_no),
-                          n_q_points);
-          else
-            offset=QProjector<dim>::DataSetDescriptor
-                   ::subface(face_no, sub_no,
-                             cell->face_orientation(face_no),
-                             cell->face_flip(face_no),
-                             cell->face_rotation(face_no),
-                             n_q_points,
-                             cell->subface_case(face_no));
-        }
-
-      this->compute_2nd (mapping, cell, offset, mapping_internal, fe_data,
-                         output_data);
-    }
 }
 
 
index 1df48ce7a403b5140ba2394f799ed5dc93de9298..89df6a5fb00b8bd6bc6cc778c0328cf663681f14 100644 (file)
@@ -657,6 +657,21 @@ MappingCartesian<dim,spacedim>::transform (
     }
 
     case mapping_piola:
+    {
+      Assert (data.update_flags & update_contravariant_transformation,
+              typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
+      Assert (data.update_flags & update_volume_elements,
+              typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_volume_elements"));
+
+      for (unsigned int i=0; i<output.size(); ++i)
+        for (unsigned int d1=0; d1<dim; ++d1)
+          for (unsigned int d2=0; d2<dim; ++d2)
+            output[i][d1][d2] = input[i][d1][d2] * data.length[d2]
+                                / data.volume_element;
+      return;
+    }
+
+    case mapping_piola_gradient:
     {
       Assert (data.update_flags & update_contravariant_transformation,
               typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
@@ -695,6 +710,68 @@ MappingCartesian<dim,spacedim>::transform (
 
   switch (mapping_type)
     {
+    case mapping_covariant:
+    {
+      Assert (data.update_flags & update_covariant_transformation,
+              typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
+
+      for (unsigned int i=0; i<output.size(); ++i)
+        for (unsigned int d1=0; d1<dim; ++d1)
+          for (unsigned int d2=0; d2<dim; ++d2)
+            output[i][d1][d2] = input[i][d1][d2] / data.length[d2];
+      return;
+    }
+
+    case mapping_contravariant:
+    {
+      Assert (data.update_flags & update_contravariant_transformation,
+              typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
+
+      for (unsigned int i=0; i<output.size(); ++i)
+        for (unsigned int d1=0; d1<dim; ++d1)
+          for (unsigned int d2=0; d2<dim; ++d2)
+            output[i][d1][d2] = input[i][d1][d2] * data.length[d2];
+      return;
+    }
+
+    case mapping_covariant_gradient:
+    {
+      Assert (data.update_flags & update_covariant_transformation,
+              typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_covariant_transformation"));
+
+      for (unsigned int i=0; i<output.size(); ++i)
+        for (unsigned int d1=0; d1<dim; ++d1)
+          for (unsigned int d2=0; d2<dim; ++d2)
+            output[i][d1][d2] = input[i][d1][d2] / data.length[d2] / data.length[d1];
+      return;
+    }
+
+    case mapping_contravariant_gradient:
+    {
+      Assert (data.update_flags & update_contravariant_transformation,
+              typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
+
+      for (unsigned int i=0; i<output.size(); ++i)
+        for (unsigned int d1=0; d1<dim; ++d1)
+          for (unsigned int d2=0; d2<dim; ++d2)
+            output[i][d1][d2] = input[i][d1][d2] * data.length[d2] / data.length[d1];
+      return;
+    }
+
+    case mapping_piola:
+    {
+      Assert (data.update_flags & update_contravariant_transformation,
+              typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_contravariant_transformation"));
+      Assert (data.update_flags & update_volume_elements,
+              typename FEValuesBase<dim>::ExcAccessToUninitializedField("update_volume_elements"));
+
+      for (unsigned int i=0; i<output.size(); ++i)
+        for (unsigned int d1=0; d1<dim; ++d1)
+          for (unsigned int d2=0; d2<dim; ++d2)
+            output[i][d1][d2] = input[i][d1][d2] * data.length[d2]
+                                / data.volume_element;
+      return;
+    }
     case mapping_piola_gradient:
     {
       Assert (data.update_flags & update_contravariant_transformation,

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.