]> https://gitweb.dealii.org/ - dealii.git/commitdiff
FE_Poly: move content from .templates.h to .cc 17830/head
authorPeter Munch <peterrmuench@gmail.com>
Sun, 3 Nov 2024 18:40:17 +0000 (19:40 +0100)
committerPeter Munch <peterrmuench@gmail.com>
Sun, 3 Nov 2024 18:40:17 +0000 (19:40 +0100)
include/deal.II/fe/fe_poly.templates.h [deleted file]
source/fe/fe_poly.cc

diff --git a/include/deal.II/fe/fe_poly.templates.h b/include/deal.II/fe/fe_poly.templates.h
deleted file mode 100644 (file)
index 06ffa6e..0000000
+++ /dev/null
@@ -1,634 +0,0 @@
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2006 - 2024 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#ifndef dealii_fe_poly_templates_h
-#define dealii_fe_poly_templates_h
-
-
-#include <deal.II/base/config.h>
-
-#include <deal.II/base/polynomial_space.h>
-#include <deal.II/base/polynomials_piecewise.h>
-#include <deal.II/base/qprojector.h>
-#include <deal.II/base/tensor_product_polynomials.h>
-#include <deal.II/base/tensor_product_polynomials_bubbles.h>
-#include <deal.II/base/tensor_product_polynomials_const.h>
-
-#include <deal.II/fe/fe_poly.h>
-#include <deal.II/fe/fe_values.h>
-#include <deal.II/fe/mapping_cartesian.h>
-
-
-DEAL_II_NAMESPACE_OPEN
-
-template <int dim, int spacedim>
-FE_Poly<dim, spacedim>::FE_Poly(
-  const ScalarPolynomialsBase<dim> &poly_space,
-  const FiniteElementData<dim>     &fe_data,
-  const std::vector<bool>          &restriction_is_additive_flags,
-  const std::vector<ComponentMask> &nonzero_components)
-  : FiniteElement<dim, spacedim>(fe_data,
-                                 restriction_is_additive_flags,
-                                 nonzero_components)
-  , poly_space(poly_space.clone())
-{}
-
-
-template <int dim, int spacedim>
-unsigned int
-FE_Poly<dim, spacedim>::get_degree() const
-{
-  return this->degree;
-}
-
-
-template <int dim, int spacedim>
-double
-FE_Poly<dim, spacedim>::shape_value(const unsigned int i,
-                                    const Point<dim>  &p) const
-{
-  AssertIndexRange(i, this->n_dofs_per_cell());
-  return poly_space->compute_value(i, p);
-}
-
-
-template <int dim, int spacedim>
-double
-FE_Poly<dim, spacedim>::shape_value_component(
-  const unsigned int i,
-  const Point<dim>  &p,
-  const unsigned int component) const
-{
-  (void)component;
-  AssertIndexRange(i, this->n_dofs_per_cell());
-  AssertIndexRange(component, 1);
-  return poly_space->compute_value(i, p);
-}
-
-
-
-template <int dim, int spacedim>
-Tensor<1, dim>
-FE_Poly<dim, spacedim>::shape_grad(const unsigned int i,
-                                   const Point<dim>  &p) const
-{
-  AssertIndexRange(i, this->n_dofs_per_cell());
-  return poly_space->template compute_derivative<1>(i, p);
-}
-
-
-
-template <int dim, int spacedim>
-Tensor<1, dim>
-FE_Poly<dim, spacedim>::shape_grad_component(const unsigned int i,
-                                             const Point<dim>  &p,
-                                             const unsigned int component) const
-{
-  (void)component;
-  AssertIndexRange(i, this->n_dofs_per_cell());
-  AssertIndexRange(component, 1);
-  return poly_space->template compute_derivative<1>(i, p);
-}
-
-
-
-template <int dim, int spacedim>
-Tensor<2, dim>
-FE_Poly<dim, spacedim>::shape_grad_grad(const unsigned int i,
-                                        const Point<dim>  &p) const
-{
-  AssertIndexRange(i, this->n_dofs_per_cell());
-  return poly_space->template compute_derivative<2>(i, p);
-}
-
-
-
-template <int dim, int spacedim>
-Tensor<2, dim>
-FE_Poly<dim, spacedim>::shape_grad_grad_component(
-  const unsigned int i,
-  const Point<dim>  &p,
-  const unsigned int component) const
-{
-  (void)component;
-  AssertIndexRange(i, this->n_dofs_per_cell());
-  AssertIndexRange(component, 1);
-  return poly_space->template compute_derivative<2>(i, p);
-}
-
-
-
-template <int dim, int spacedim>
-Tensor<3, dim>
-FE_Poly<dim, spacedim>::shape_3rd_derivative(const unsigned int i,
-                                             const Point<dim>  &p) const
-{
-  AssertIndexRange(i, this->n_dofs_per_cell());
-  return poly_space->template compute_derivative<3>(i, p);
-}
-
-
-
-template <int dim, int spacedim>
-Tensor<3, dim>
-FE_Poly<dim, spacedim>::shape_3rd_derivative_component(
-  const unsigned int i,
-  const Point<dim>  &p,
-  const unsigned int component) const
-{
-  (void)component;
-  AssertIndexRange(i, this->n_dofs_per_cell());
-  AssertIndexRange(component, 1);
-  return poly_space->template compute_derivative<3>(i, p);
-}
-
-
-
-template <int dim, int spacedim>
-Tensor<4, dim>
-FE_Poly<dim, spacedim>::shape_4th_derivative(const unsigned int i,
-                                             const Point<dim>  &p) const
-{
-  AssertIndexRange(i, this->n_dofs_per_cell());
-  return poly_space->template compute_derivative<4>(i, p);
-}
-
-
-
-template <int dim, int spacedim>
-Tensor<4, dim>
-FE_Poly<dim, spacedim>::shape_4th_derivative_component(
-  const unsigned int i,
-  const Point<dim>  &p,
-  const unsigned int component) const
-{
-  (void)component;
-  AssertIndexRange(i, this->n_dofs_per_cell());
-  AssertIndexRange(component, 1);
-  return poly_space->template compute_derivative<4>(i, p);
-}
-
-
-
-//---------------------------------------------------------------------------
-// Auxiliary functions
-//---------------------------------------------------------------------------
-
-
-template <int dim, int spacedim>
-UpdateFlags
-FE_Poly<dim, spacedim>::requires_update_flags(const UpdateFlags flags) const
-{
-  UpdateFlags out = update_default;
-
-  if (flags & update_values)
-    out |= update_values;
-  if (flags & update_gradients)
-    out |= update_gradients | update_covariant_transformation;
-  if (flags & update_hessians)
-    out |= update_hessians | update_covariant_transformation |
-           update_gradients | update_jacobian_pushed_forward_grads;
-  if (flags & update_3rd_derivatives)
-    out |= update_3rd_derivatives | update_covariant_transformation |
-           update_hessians | update_gradients |
-           update_jacobian_pushed_forward_grads |
-           update_jacobian_pushed_forward_2nd_derivatives;
-  if (flags & update_normal_vectors)
-    out |= update_normal_vectors | update_JxW_values;
-
-  return out;
-}
-
-
-
-//---------------------------------------------------------------------------
-// Fill data of FEValues
-//---------------------------------------------------------------------------
-
-
-
-/**
- * Returns whether we need to correct the Hessians and third derivatives with
- * the derivatives of the Jacobian. This is determined by checking if
- * the jacobian_pushed_forward are zero.
- *
- * Especially for the third derivatives, the correction term is very expensive,
- * which is why we check if the derivatives are zero before computing the
- * correction.
- */
-template <int dim, int spacedim>
-bool
-higher_derivatives_need_correcting(
-  const Mapping<dim, spacedim> &mapping,
-  const internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
-                    &mapping_data,
-  const unsigned int n_q_points,
-  const UpdateFlags  update_flags)
-{
-  // If higher derivatives weren't requested we don't need to correct them.
-  const bool update_higher_derivatives =
-    (update_flags & update_hessians) || (update_flags & update_3rd_derivatives);
-  if (!update_higher_derivatives)
-    return false;
-
-  // If we have a Cartesian mapping, we know that jacoban_pushed_forward_grads
-  // are identically zero.
-  if (dynamic_cast<const MappingCartesian<dim> *>(&mapping))
-    return false;
-
-  // Here, we should check if jacobian_pushed_forward_grads are zero at the
-  // quadrature points. This is yet to be implemented.
-  (void)mapping_data;
-  (void)n_q_points;
-
-  return true;
-}
-
-
-
-template <int dim, int spacedim>
-void
-FE_Poly<dim, spacedim>::fill_fe_values(
-  const typename Triangulation<dim, spacedim>::cell_iterator &,
-  const CellSimilarity::Similarity                         cell_similarity,
-  const Quadrature<dim>                                   &quadrature,
-  const Mapping<dim, spacedim>                            &mapping,
-  const typename Mapping<dim, spacedim>::InternalDataBase &mapping_internal,
-  const internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
-                                                                &mapping_data,
-  const typename FiniteElement<dim, spacedim>::InternalDataBase &fe_internal,
-  dealii::internal::FEValuesImplementation::FiniteElementRelatedData<dim,
-                                                                     spacedim>
-    &output_data) const
-{
-  // convert data object to internal
-  // data for this class. fails with
-  // an exception if that is not
-  // possible
-  Assert(dynamic_cast<const InternalData *>(&fe_internal) != nullptr,
-         ExcInternalError());
-  const InternalData &fe_data = static_cast<const InternalData &>(fe_internal);
-
-  const UpdateFlags flags(fe_data.update_each);
-
-  const bool need_to_correct_higher_derivatives =
-    higher_derivatives_need_correcting(mapping,
-                                       mapping_data,
-                                       quadrature.size(),
-                                       flags);
-
-  // transform gradients and higher derivatives. there is nothing to do
-  // for values since we already emplaced them into output_data when
-  // we were in get_data()
-  if ((flags & update_gradients) &&
-      (cell_similarity != CellSimilarity::translation))
-    for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
-      mapping.transform(make_array_view(fe_data.shape_gradients, k),
-                        mapping_covariant,
-                        mapping_internal,
-                        make_array_view(output_data.shape_gradients, k));
-
-  if ((flags & update_hessians) &&
-      (cell_similarity != CellSimilarity::translation))
-    {
-      for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
-        mapping.transform(make_array_view(fe_data.shape_hessians, k),
-                          mapping_covariant_gradient,
-                          mapping_internal,
-                          make_array_view(output_data.shape_hessians, k));
-
-      if (need_to_correct_higher_derivatives)
-        correct_hessians(output_data, mapping_data, quadrature.size());
-    }
-
-  if ((flags & update_3rd_derivatives) &&
-      (cell_similarity != CellSimilarity::translation))
-    {
-      for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
-        mapping.transform(make_array_view(fe_data.shape_3rd_derivatives, k),
-                          mapping_covariant_hessian,
-                          mapping_internal,
-                          make_array_view(output_data.shape_3rd_derivatives,
-                                          k));
-
-      if (need_to_correct_higher_derivatives)
-        correct_third_derivatives(output_data, mapping_data, quadrature.size());
-    }
-}
-
-
-
-template <int dim, int spacedim>
-void
-FE_Poly<dim, spacedim>::fill_fe_face_values(
-  const typename Triangulation<dim, spacedim>::cell_iterator &cell,
-  const unsigned int                                          face_no,
-  const hp::QCollection<dim - 1>                             &quadrature,
-  const Mapping<dim, spacedim>                               &mapping,
-  const typename Mapping<dim, spacedim>::InternalDataBase    &mapping_internal,
-  const internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
-                                                                &mapping_data,
-  const typename FiniteElement<dim, spacedim>::InternalDataBase &fe_internal,
-  dealii::internal::FEValuesImplementation::FiniteElementRelatedData<dim,
-                                                                     spacedim>
-    &output_data) const
-{
-  const unsigned int n_q_points =
-    quadrature[quadrature.size() == 1 ? 0 : face_no].size();
-
-  // convert data object to internal
-  // data for this class. fails with
-  // an exception if that is not
-  // possible
-  Assert(dynamic_cast<const InternalData *>(&fe_internal) != nullptr,
-         ExcInternalError());
-  const InternalData &fe_data = static_cast<const InternalData &>(fe_internal);
-
-  // offset determines which data set
-  // to take (all data sets for all
-  // faces are stored contiguously)
-
-  const auto offset =
-    QProjector<dim>::DataSetDescriptor::face(this->reference_cell(),
-                                             face_no,
-                                             cell->face_orientation(face_no),
-                                             cell->face_flip(face_no),
-                                             cell->face_rotation(face_no),
-                                             quadrature);
-
-  const UpdateFlags flags(fe_data.update_each);
-
-  const bool need_to_correct_higher_derivatives =
-    higher_derivatives_need_correcting(mapping,
-                                       mapping_data,
-                                       n_q_points,
-                                       flags);
-
-  // transform gradients and higher derivatives. we also have to copy
-  // the values (unlike in the case of fill_fe_values()) since
-  // we need to take into account the offsets
-  if (flags & update_values)
-    for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
-      for (unsigned int i = 0; i < n_q_points; ++i)
-        output_data.shape_values(k, i) = fe_data.shape_values[k][i + offset];
-
-  if (flags & update_gradients)
-    for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
-      mapping.transform(
-        make_array_view(fe_data.shape_gradients, k, offset, n_q_points),
-        mapping_covariant,
-        mapping_internal,
-        make_array_view(output_data.shape_gradients, k));
-
-  if (flags & update_hessians)
-    {
-      for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
-        mapping.transform(
-          make_array_view(fe_data.shape_hessians, k, offset, n_q_points),
-          mapping_covariant_gradient,
-          mapping_internal,
-          make_array_view(output_data.shape_hessians, k));
-
-      if (need_to_correct_higher_derivatives)
-        correct_hessians(output_data, mapping_data, n_q_points);
-    }
-
-  if (flags & update_3rd_derivatives)
-    {
-      for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
-        mapping.transform(
-          make_array_view(fe_data.shape_3rd_derivatives, k, offset, n_q_points),
-          mapping_covariant_hessian,
-          mapping_internal,
-          make_array_view(output_data.shape_3rd_derivatives, k));
-
-      if (need_to_correct_higher_derivatives)
-        correct_third_derivatives(output_data, mapping_data, n_q_points);
-    }
-}
-
-
-
-template <int dim, int spacedim>
-void
-FE_Poly<dim, spacedim>::fill_fe_subface_values(
-  const typename Triangulation<dim, spacedim>::cell_iterator &cell,
-  const unsigned int                                          face_no,
-  const unsigned int                                          sub_no,
-  const Quadrature<dim - 1>                                  &quadrature,
-  const Mapping<dim, spacedim>                               &mapping,
-  const typename Mapping<dim, spacedim>::InternalDataBase    &mapping_internal,
-  const internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
-                                                                &mapping_data,
-  const typename FiniteElement<dim, spacedim>::InternalDataBase &fe_internal,
-  dealii::internal::FEValuesImplementation::FiniteElementRelatedData<dim,
-                                                                     spacedim>
-    &output_data) const
-{
-  // convert data object to internal
-  // data for this class. fails with
-  // an exception if that is not
-  // possible
-  Assert(dynamic_cast<const InternalData *>(&fe_internal) != nullptr,
-         ExcInternalError());
-  const InternalData &fe_data = static_cast<const InternalData &>(fe_internal);
-
-  // offset determines which data set
-  // to take (all data sets for all
-  // sub-faces are stored contiguously)
-
-  const auto offset =
-    QProjector<dim>::DataSetDescriptor::subface(this->reference_cell(),
-                                                face_no,
-                                                sub_no,
-                                                cell->face_orientation(face_no),
-                                                cell->face_flip(face_no),
-                                                cell->face_rotation(face_no),
-                                                quadrature.size(),
-                                                cell->subface_case(face_no));
-
-  const UpdateFlags flags(fe_data.update_each);
-
-  const bool need_to_correct_higher_derivatives =
-    higher_derivatives_need_correcting(mapping,
-                                       mapping_data,
-                                       quadrature.size(),
-                                       flags);
-
-  // transform gradients and higher derivatives. we also have to copy
-  // the values (unlike in the case of fill_fe_values()) since
-  // we need to take into account the offsets
-  if (flags & update_values)
-    for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
-      for (unsigned int i = 0; i < quadrature.size(); ++i)
-        output_data.shape_values(k, i) = fe_data.shape_values[k][i + offset];
-
-  if (flags & update_gradients)
-    for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
-      mapping.transform(
-        make_array_view(fe_data.shape_gradients, k, offset, quadrature.size()),
-        mapping_covariant,
-        mapping_internal,
-        make_array_view(output_data.shape_gradients, k));
-
-  if (flags & update_hessians)
-    {
-      for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
-        mapping.transform(
-          make_array_view(fe_data.shape_hessians, k, offset, quadrature.size()),
-          mapping_covariant_gradient,
-          mapping_internal,
-          make_array_view(output_data.shape_hessians, k));
-
-      if (need_to_correct_higher_derivatives)
-        correct_hessians(output_data, mapping_data, quadrature.size());
-    }
-
-  if (flags & update_3rd_derivatives)
-    {
-      for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
-        mapping.transform(make_array_view(fe_data.shape_3rd_derivatives,
-                                          k,
-                                          offset,
-                                          quadrature.size()),
-                          mapping_covariant_hessian,
-                          mapping_internal,
-                          make_array_view(output_data.shape_3rd_derivatives,
-                                          k));
-
-      if (need_to_correct_higher_derivatives)
-        correct_third_derivatives(output_data, mapping_data, quadrature.size());
-    }
-}
-
-
-
-template <int dim, int spacedim>
-inline void
-FE_Poly<dim, spacedim>::correct_hessians(
-  internal::FEValuesImplementation::FiniteElementRelatedData<dim, spacedim>
-    &output_data,
-  const internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
-                    &mapping_data,
-  const unsigned int n_q_points) const
-{
-  for (unsigned int dof = 0; dof < this->n_dofs_per_cell(); ++dof)
-    for (unsigned int i = 0; i < n_q_points; ++i)
-      for (unsigned int j = 0; j < spacedim; ++j)
-        output_data.shape_hessians[dof][i] -=
-          mapping_data.jacobian_pushed_forward_grads[i][j] *
-          output_data.shape_gradients[dof][i][j];
-}
-
-
-
-template <int dim, int spacedim>
-inline void
-FE_Poly<dim, spacedim>::correct_third_derivatives(
-  internal::FEValuesImplementation::FiniteElementRelatedData<dim, spacedim>
-    &output_data,
-  const internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
-                    &mapping_data,
-  const unsigned int n_q_points) const
-{
-  for (unsigned int dof = 0; dof < this->n_dofs_per_cell(); ++dof)
-    for (unsigned int i = 0; i < n_q_points; ++i)
-      for (unsigned int j = 0; j < spacedim; ++j)
-        for (unsigned int k = 0; k < spacedim; ++k)
-          for (unsigned int l = 0; l < spacedim; ++l)
-            for (unsigned int m = 0; m < spacedim; ++m)
-              {
-                output_data.shape_3rd_derivatives[dof][i][j][k][l] -=
-                  (mapping_data.jacobian_pushed_forward_grads[i][m][j][l] *
-                   output_data.shape_hessians[dof][i][k][m]) +
-                  (mapping_data.jacobian_pushed_forward_grads[i][m][k][l] *
-                   output_data.shape_hessians[dof][i][j][m]) +
-                  (mapping_data.jacobian_pushed_forward_grads[i][m][j][k] *
-                   output_data.shape_hessians[dof][i][l][m]) +
-                  (mapping_data
-                     .jacobian_pushed_forward_2nd_derivatives[i][m][j][k][l] *
-                   output_data.shape_gradients[dof][i][m]);
-              }
-}
-
-
-
-template <int dim, int spacedim>
-inline const ScalarPolynomialsBase<dim> &
-FE_Poly<dim, spacedim>::get_poly_space() const
-{
-  return *poly_space;
-}
-
-
-
-template <int dim, int spacedim>
-std::vector<unsigned int>
-FE_Poly<dim, spacedim>::get_poly_space_numbering() const
-{
-  auto *const space_tensor_prod =
-    dynamic_cast<TensorProductPolynomials<dim> *>(this->poly_space.get());
-  if (space_tensor_prod != nullptr)
-    return space_tensor_prod->get_numbering();
-
-  auto *const space_tensor_prod_aniso =
-    dynamic_cast<AnisotropicPolynomials<dim> *>(this->poly_space.get());
-  if (space_tensor_prod_aniso != nullptr)
-    return space_tensor_prod_aniso->get_numbering();
-
-  auto *const space_tensor_prod_piecewise = dynamic_cast<
-    TensorProductPolynomials<dim, Polynomials::PiecewisePolynomial<double>> *>(
-    this->poly_space.get());
-  if (space_tensor_prod_piecewise != nullptr)
-    return space_tensor_prod_piecewise->get_numbering();
-
-  auto *const space_tensor_prod_bubbles =
-    dynamic_cast<TensorProductPolynomialsBubbles<dim> *>(
-      this->poly_space.get());
-  if (space_tensor_prod_bubbles != nullptr)
-    return space_tensor_prod_bubbles->get_numbering();
-
-  auto *const space_tensor_prod_const =
-    dynamic_cast<TensorProductPolynomialsConst<dim> *>(this->poly_space.get());
-  if (space_tensor_prod_const != nullptr)
-    return space_tensor_prod_const->get_numbering();
-
-  DEAL_II_NOT_IMPLEMENTED();
-  return std::vector<unsigned int>();
-}
-
-
-
-template <int dim, int spacedim>
-std::vector<unsigned int>
-FE_Poly<dim, spacedim>::get_poly_space_numbering_inverse() const
-{
-  return Utilities::invert_permutation(get_poly_space_numbering());
-}
-
-
-
-template <int dim, int spacedim>
-std::size_t
-FE_Poly<dim, spacedim>::memory_consumption() const
-{
-  return FiniteElement<dim, spacedim>::memory_consumption() +
-         poly_space->memory_consumption();
-}
-
-
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
index 9de0950e5d283a01aa67b1fc8240e9987be6a288..6a164dbf8210e45ae0bb11a5043029deefbba71f 100644 (file)
@@ -13,6 +13,9 @@
 // ------------------------------------------------------------------------
 
 
+#include <deal.II/base/config.h>
+
+#include <deal.II/base/polynomial_space.h>
 #include <deal.II/base/polynomials_p.h>
 #include <deal.II/base/polynomials_piecewise.h>
 #include <deal.II/base/polynomials_rannacher_turek.h>
@@ -22,8 +25,8 @@
 #include <deal.II/base/tensor_product_polynomials_const.h>
 
 #include <deal.II/fe/fe_poly.h>
-#include <deal.II/fe/fe_poly.templates.h>
 #include <deal.II/fe/fe_values.h>
+#include <deal.II/fe/mapping_cartesian.h>
 
 DEAL_II_NAMESPACE_OPEN
 
@@ -35,6 +38,601 @@ FE_Poly<dim, spacedim>::FE_Poly(const FE_Poly &fe)
   , poly_space(fe.poly_space->clone())
 {}
 
+template <int dim, int spacedim>
+FE_Poly<dim, spacedim>::FE_Poly(
+  const ScalarPolynomialsBase<dim> &poly_space,
+  const FiniteElementData<dim>     &fe_data,
+  const std::vector<bool>          &restriction_is_additive_flags,
+  const std::vector<ComponentMask> &nonzero_components)
+  : FiniteElement<dim, spacedim>(fe_data,
+                                 restriction_is_additive_flags,
+                                 nonzero_components)
+  , poly_space(poly_space.clone())
+{}
+
+
+template <int dim, int spacedim>
+unsigned int
+FE_Poly<dim, spacedim>::get_degree() const
+{
+  return this->degree;
+}
+
+
+template <int dim, int spacedim>
+double
+FE_Poly<dim, spacedim>::shape_value(const unsigned int i,
+                                    const Point<dim>  &p) const
+{
+  AssertIndexRange(i, this->n_dofs_per_cell());
+  return poly_space->compute_value(i, p);
+}
+
+
+template <int dim, int spacedim>
+double
+FE_Poly<dim, spacedim>::shape_value_component(
+  const unsigned int i,
+  const Point<dim>  &p,
+  const unsigned int component) const
+{
+  (void)component;
+  AssertIndexRange(i, this->n_dofs_per_cell());
+  AssertIndexRange(component, 1);
+  return poly_space->compute_value(i, p);
+}
+
+
+
+template <int dim, int spacedim>
+Tensor<1, dim>
+FE_Poly<dim, spacedim>::shape_grad(const unsigned int i,
+                                   const Point<dim>  &p) const
+{
+  AssertIndexRange(i, this->n_dofs_per_cell());
+  return poly_space->template compute_derivative<1>(i, p);
+}
+
+
+
+template <int dim, int spacedim>
+Tensor<1, dim>
+FE_Poly<dim, spacedim>::shape_grad_component(const unsigned int i,
+                                             const Point<dim>  &p,
+                                             const unsigned int component) const
+{
+  (void)component;
+  AssertIndexRange(i, this->n_dofs_per_cell());
+  AssertIndexRange(component, 1);
+  return poly_space->template compute_derivative<1>(i, p);
+}
+
+
+
+template <int dim, int spacedim>
+Tensor<2, dim>
+FE_Poly<dim, spacedim>::shape_grad_grad(const unsigned int i,
+                                        const Point<dim>  &p) const
+{
+  AssertIndexRange(i, this->n_dofs_per_cell());
+  return poly_space->template compute_derivative<2>(i, p);
+}
+
+
+
+template <int dim, int spacedim>
+Tensor<2, dim>
+FE_Poly<dim, spacedim>::shape_grad_grad_component(
+  const unsigned int i,
+  const Point<dim>  &p,
+  const unsigned int component) const
+{
+  (void)component;
+  AssertIndexRange(i, this->n_dofs_per_cell());
+  AssertIndexRange(component, 1);
+  return poly_space->template compute_derivative<2>(i, p);
+}
+
+
+
+template <int dim, int spacedim>
+Tensor<3, dim>
+FE_Poly<dim, spacedim>::shape_3rd_derivative(const unsigned int i,
+                                             const Point<dim>  &p) const
+{
+  AssertIndexRange(i, this->n_dofs_per_cell());
+  return poly_space->template compute_derivative<3>(i, p);
+}
+
+
+
+template <int dim, int spacedim>
+Tensor<3, dim>
+FE_Poly<dim, spacedim>::shape_3rd_derivative_component(
+  const unsigned int i,
+  const Point<dim>  &p,
+  const unsigned int component) const
+{
+  (void)component;
+  AssertIndexRange(i, this->n_dofs_per_cell());
+  AssertIndexRange(component, 1);
+  return poly_space->template compute_derivative<3>(i, p);
+}
+
+
+
+template <int dim, int spacedim>
+Tensor<4, dim>
+FE_Poly<dim, spacedim>::shape_4th_derivative(const unsigned int i,
+                                             const Point<dim>  &p) const
+{
+  AssertIndexRange(i, this->n_dofs_per_cell());
+  return poly_space->template compute_derivative<4>(i, p);
+}
+
+
+
+template <int dim, int spacedim>
+Tensor<4, dim>
+FE_Poly<dim, spacedim>::shape_4th_derivative_component(
+  const unsigned int i,
+  const Point<dim>  &p,
+  const unsigned int component) const
+{
+  (void)component;
+  AssertIndexRange(i, this->n_dofs_per_cell());
+  AssertIndexRange(component, 1);
+  return poly_space->template compute_derivative<4>(i, p);
+}
+
+
+
+//---------------------------------------------------------------------------
+// Auxiliary functions
+//---------------------------------------------------------------------------
+
+
+template <int dim, int spacedim>
+UpdateFlags
+FE_Poly<dim, spacedim>::requires_update_flags(const UpdateFlags flags) const
+{
+  UpdateFlags out = update_default;
+
+  if (flags & update_values)
+    out |= update_values;
+  if (flags & update_gradients)
+    out |= update_gradients | update_covariant_transformation;
+  if (flags & update_hessians)
+    out |= update_hessians | update_covariant_transformation |
+           update_gradients | update_jacobian_pushed_forward_grads;
+  if (flags & update_3rd_derivatives)
+    out |= update_3rd_derivatives | update_covariant_transformation |
+           update_hessians | update_gradients |
+           update_jacobian_pushed_forward_grads |
+           update_jacobian_pushed_forward_2nd_derivatives;
+  if (flags & update_normal_vectors)
+    out |= update_normal_vectors | update_JxW_values;
+
+  return out;
+}
+
+
+
+//---------------------------------------------------------------------------
+// Fill data of FEValues
+//---------------------------------------------------------------------------
+
+
+
+/**
+ * Returns whether we need to correct the Hessians and third derivatives with
+ * the derivatives of the Jacobian. This is determined by checking if
+ * the jacobian_pushed_forward are zero.
+ *
+ * Especially for the third derivatives, the correction term is very expensive,
+ * which is why we check if the derivatives are zero before computing the
+ * correction.
+ */
+template <int dim, int spacedim>
+bool
+higher_derivatives_need_correcting(
+  const Mapping<dim, spacedim> &mapping,
+  const internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
+                    &mapping_data,
+  const unsigned int n_q_points,
+  const UpdateFlags  update_flags)
+{
+  // If higher derivatives weren't requested we don't need to correct them.
+  const bool update_higher_derivatives =
+    (update_flags & update_hessians) || (update_flags & update_3rd_derivatives);
+  if (!update_higher_derivatives)
+    return false;
+
+  // If we have a Cartesian mapping, we know that jacoban_pushed_forward_grads
+  // are identically zero.
+  if (dynamic_cast<const MappingCartesian<dim> *>(&mapping))
+    return false;
+
+  // Here, we should check if jacobian_pushed_forward_grads are zero at the
+  // quadrature points. This is yet to be implemented.
+  (void)mapping_data;
+  (void)n_q_points;
+
+  return true;
+}
+
+
+
+template <int dim, int spacedim>
+void
+FE_Poly<dim, spacedim>::fill_fe_values(
+  const typename Triangulation<dim, spacedim>::cell_iterator &,
+  const CellSimilarity::Similarity                         cell_similarity,
+  const Quadrature<dim>                                   &quadrature,
+  const Mapping<dim, spacedim>                            &mapping,
+  const typename Mapping<dim, spacedim>::InternalDataBase &mapping_internal,
+  const internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
+                                                                &mapping_data,
+  const typename FiniteElement<dim, spacedim>::InternalDataBase &fe_internal,
+  dealii::internal::FEValuesImplementation::FiniteElementRelatedData<dim,
+                                                                     spacedim>
+    &output_data) const
+{
+  // convert data object to internal
+  // data for this class. fails with
+  // an exception if that is not
+  // possible
+  Assert(dynamic_cast<const InternalData *>(&fe_internal) != nullptr,
+         ExcInternalError());
+  const InternalData &fe_data = static_cast<const InternalData &>(fe_internal);
+
+  const UpdateFlags flags(fe_data.update_each);
+
+  const bool need_to_correct_higher_derivatives =
+    higher_derivatives_need_correcting(mapping,
+                                       mapping_data,
+                                       quadrature.size(),
+                                       flags);
+
+  // transform gradients and higher derivatives. there is nothing to do
+  // for values since we already emplaced them into output_data when
+  // we were in get_data()
+  if ((flags & update_gradients) &&
+      (cell_similarity != CellSimilarity::translation))
+    for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
+      mapping.transform(make_array_view(fe_data.shape_gradients, k),
+                        mapping_covariant,
+                        mapping_internal,
+                        make_array_view(output_data.shape_gradients, k));
+
+  if ((flags & update_hessians) &&
+      (cell_similarity != CellSimilarity::translation))
+    {
+      for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
+        mapping.transform(make_array_view(fe_data.shape_hessians, k),
+                          mapping_covariant_gradient,
+                          mapping_internal,
+                          make_array_view(output_data.shape_hessians, k));
+
+      if (need_to_correct_higher_derivatives)
+        correct_hessians(output_data, mapping_data, quadrature.size());
+    }
+
+  if ((flags & update_3rd_derivatives) &&
+      (cell_similarity != CellSimilarity::translation))
+    {
+      for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
+        mapping.transform(make_array_view(fe_data.shape_3rd_derivatives, k),
+                          mapping_covariant_hessian,
+                          mapping_internal,
+                          make_array_view(output_data.shape_3rd_derivatives,
+                                          k));
+
+      if (need_to_correct_higher_derivatives)
+        correct_third_derivatives(output_data, mapping_data, quadrature.size());
+    }
+}
+
+
+
+template <int dim, int spacedim>
+void
+FE_Poly<dim, spacedim>::fill_fe_face_values(
+  const typename Triangulation<dim, spacedim>::cell_iterator &cell,
+  const unsigned int                                          face_no,
+  const hp::QCollection<dim - 1>                             &quadrature,
+  const Mapping<dim, spacedim>                               &mapping,
+  const typename Mapping<dim, spacedim>::InternalDataBase    &mapping_internal,
+  const internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
+                                                                &mapping_data,
+  const typename FiniteElement<dim, spacedim>::InternalDataBase &fe_internal,
+  dealii::internal::FEValuesImplementation::FiniteElementRelatedData<dim,
+                                                                     spacedim>
+    &output_data) const
+{
+  const unsigned int n_q_points =
+    quadrature[quadrature.size() == 1 ? 0 : face_no].size();
+
+  // convert data object to internal
+  // data for this class. fails with
+  // an exception if that is not
+  // possible
+  Assert(dynamic_cast<const InternalData *>(&fe_internal) != nullptr,
+         ExcInternalError());
+  const InternalData &fe_data = static_cast<const InternalData &>(fe_internal);
+
+  // offset determines which data set
+  // to take (all data sets for all
+  // faces are stored contiguously)
+
+  const auto offset =
+    QProjector<dim>::DataSetDescriptor::face(this->reference_cell(),
+                                             face_no,
+                                             cell->face_orientation(face_no),
+                                             cell->face_flip(face_no),
+                                             cell->face_rotation(face_no),
+                                             quadrature);
+
+  const UpdateFlags flags(fe_data.update_each);
+
+  const bool need_to_correct_higher_derivatives =
+    higher_derivatives_need_correcting(mapping,
+                                       mapping_data,
+                                       n_q_points,
+                                       flags);
+
+  // transform gradients and higher derivatives. we also have to copy
+  // the values (unlike in the case of fill_fe_values()) since
+  // we need to take into account the offsets
+  if (flags & update_values)
+    for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
+      for (unsigned int i = 0; i < n_q_points; ++i)
+        output_data.shape_values(k, i) = fe_data.shape_values[k][i + offset];
+
+  if (flags & update_gradients)
+    for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
+      mapping.transform(
+        make_array_view(fe_data.shape_gradients, k, offset, n_q_points),
+        mapping_covariant,
+        mapping_internal,
+        make_array_view(output_data.shape_gradients, k));
+
+  if (flags & update_hessians)
+    {
+      for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
+        mapping.transform(
+          make_array_view(fe_data.shape_hessians, k, offset, n_q_points),
+          mapping_covariant_gradient,
+          mapping_internal,
+          make_array_view(output_data.shape_hessians, k));
+
+      if (need_to_correct_higher_derivatives)
+        correct_hessians(output_data, mapping_data, n_q_points);
+    }
+
+  if (flags & update_3rd_derivatives)
+    {
+      for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
+        mapping.transform(
+          make_array_view(fe_data.shape_3rd_derivatives, k, offset, n_q_points),
+          mapping_covariant_hessian,
+          mapping_internal,
+          make_array_view(output_data.shape_3rd_derivatives, k));
+
+      if (need_to_correct_higher_derivatives)
+        correct_third_derivatives(output_data, mapping_data, n_q_points);
+    }
+}
+
+
+
+template <int dim, int spacedim>
+void
+FE_Poly<dim, spacedim>::fill_fe_subface_values(
+  const typename Triangulation<dim, spacedim>::cell_iterator &cell,
+  const unsigned int                                          face_no,
+  const unsigned int                                          sub_no,
+  const Quadrature<dim - 1>                                  &quadrature,
+  const Mapping<dim, spacedim>                               &mapping,
+  const typename Mapping<dim, spacedim>::InternalDataBase    &mapping_internal,
+  const internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
+                                                                &mapping_data,
+  const typename FiniteElement<dim, spacedim>::InternalDataBase &fe_internal,
+  dealii::internal::FEValuesImplementation::FiniteElementRelatedData<dim,
+                                                                     spacedim>
+    &output_data) const
+{
+  // convert data object to internal
+  // data for this class. fails with
+  // an exception if that is not
+  // possible
+  Assert(dynamic_cast<const InternalData *>(&fe_internal) != nullptr,
+         ExcInternalError());
+  const InternalData &fe_data = static_cast<const InternalData &>(fe_internal);
+
+  // offset determines which data set
+  // to take (all data sets for all
+  // sub-faces are stored contiguously)
+
+  const auto offset =
+    QProjector<dim>::DataSetDescriptor::subface(this->reference_cell(),
+                                                face_no,
+                                                sub_no,
+                                                cell->face_orientation(face_no),
+                                                cell->face_flip(face_no),
+                                                cell->face_rotation(face_no),
+                                                quadrature.size(),
+                                                cell->subface_case(face_no));
+
+  const UpdateFlags flags(fe_data.update_each);
+
+  const bool need_to_correct_higher_derivatives =
+    higher_derivatives_need_correcting(mapping,
+                                       mapping_data,
+                                       quadrature.size(),
+                                       flags);
+
+  // transform gradients and higher derivatives. we also have to copy
+  // the values (unlike in the case of fill_fe_values()) since
+  // we need to take into account the offsets
+  if (flags & update_values)
+    for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
+      for (unsigned int i = 0; i < quadrature.size(); ++i)
+        output_data.shape_values(k, i) = fe_data.shape_values[k][i + offset];
+
+  if (flags & update_gradients)
+    for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
+      mapping.transform(
+        make_array_view(fe_data.shape_gradients, k, offset, quadrature.size()),
+        mapping_covariant,
+        mapping_internal,
+        make_array_view(output_data.shape_gradients, k));
+
+  if (flags & update_hessians)
+    {
+      for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
+        mapping.transform(
+          make_array_view(fe_data.shape_hessians, k, offset, quadrature.size()),
+          mapping_covariant_gradient,
+          mapping_internal,
+          make_array_view(output_data.shape_hessians, k));
+
+      if (need_to_correct_higher_derivatives)
+        correct_hessians(output_data, mapping_data, quadrature.size());
+    }
+
+  if (flags & update_3rd_derivatives)
+    {
+      for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
+        mapping.transform(make_array_view(fe_data.shape_3rd_derivatives,
+                                          k,
+                                          offset,
+                                          quadrature.size()),
+                          mapping_covariant_hessian,
+                          mapping_internal,
+                          make_array_view(output_data.shape_3rd_derivatives,
+                                          k));
+
+      if (need_to_correct_higher_derivatives)
+        correct_third_derivatives(output_data, mapping_data, quadrature.size());
+    }
+}
+
+
+
+template <int dim, int spacedim>
+inline void
+FE_Poly<dim, spacedim>::correct_hessians(
+  internal::FEValuesImplementation::FiniteElementRelatedData<dim, spacedim>
+    &output_data,
+  const internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
+                    &mapping_data,
+  const unsigned int n_q_points) const
+{
+  for (unsigned int dof = 0; dof < this->n_dofs_per_cell(); ++dof)
+    for (unsigned int i = 0; i < n_q_points; ++i)
+      for (unsigned int j = 0; j < spacedim; ++j)
+        output_data.shape_hessians[dof][i] -=
+          mapping_data.jacobian_pushed_forward_grads[i][j] *
+          output_data.shape_gradients[dof][i][j];
+}
+
+
+
+template <int dim, int spacedim>
+inline void
+FE_Poly<dim, spacedim>::correct_third_derivatives(
+  internal::FEValuesImplementation::FiniteElementRelatedData<dim, spacedim>
+    &output_data,
+  const internal::FEValuesImplementation::MappingRelatedData<dim, spacedim>
+                    &mapping_data,
+  const unsigned int n_q_points) const
+{
+  for (unsigned int dof = 0; dof < this->n_dofs_per_cell(); ++dof)
+    for (unsigned int i = 0; i < n_q_points; ++i)
+      for (unsigned int j = 0; j < spacedim; ++j)
+        for (unsigned int k = 0; k < spacedim; ++k)
+          for (unsigned int l = 0; l < spacedim; ++l)
+            for (unsigned int m = 0; m < spacedim; ++m)
+              {
+                output_data.shape_3rd_derivatives[dof][i][j][k][l] -=
+                  (mapping_data.jacobian_pushed_forward_grads[i][m][j][l] *
+                   output_data.shape_hessians[dof][i][k][m]) +
+                  (mapping_data.jacobian_pushed_forward_grads[i][m][k][l] *
+                   output_data.shape_hessians[dof][i][j][m]) +
+                  (mapping_data.jacobian_pushed_forward_grads[i][m][j][k] *
+                   output_data.shape_hessians[dof][i][l][m]) +
+                  (mapping_data
+                     .jacobian_pushed_forward_2nd_derivatives[i][m][j][k][l] *
+                   output_data.shape_gradients[dof][i][m]);
+              }
+}
+
+
+
+template <int dim, int spacedim>
+inline const ScalarPolynomialsBase<dim> &
+FE_Poly<dim, spacedim>::get_poly_space() const
+{
+  return *poly_space;
+}
+
+
+
+template <int dim, int spacedim>
+std::vector<unsigned int>
+FE_Poly<dim, spacedim>::get_poly_space_numbering() const
+{
+  auto *const space_tensor_prod =
+    dynamic_cast<TensorProductPolynomials<dim> *>(this->poly_space.get());
+  if (space_tensor_prod != nullptr)
+    return space_tensor_prod->get_numbering();
+
+  auto *const space_tensor_prod_aniso =
+    dynamic_cast<AnisotropicPolynomials<dim> *>(this->poly_space.get());
+  if (space_tensor_prod_aniso != nullptr)
+    return space_tensor_prod_aniso->get_numbering();
+
+  auto *const space_tensor_prod_piecewise = dynamic_cast<
+    TensorProductPolynomials<dim, Polynomials::PiecewisePolynomial<double>> *>(
+    this->poly_space.get());
+  if (space_tensor_prod_piecewise != nullptr)
+    return space_tensor_prod_piecewise->get_numbering();
+
+  auto *const space_tensor_prod_bubbles =
+    dynamic_cast<TensorProductPolynomialsBubbles<dim> *>(
+      this->poly_space.get());
+  if (space_tensor_prod_bubbles != nullptr)
+    return space_tensor_prod_bubbles->get_numbering();
+
+  auto *const space_tensor_prod_const =
+    dynamic_cast<TensorProductPolynomialsConst<dim> *>(this->poly_space.get());
+  if (space_tensor_prod_const != nullptr)
+    return space_tensor_prod_const->get_numbering();
+
+  DEAL_II_NOT_IMPLEMENTED();
+  return std::vector<unsigned int>();
+}
+
+
+
+template <int dim, int spacedim>
+std::vector<unsigned int>
+FE_Poly<dim, spacedim>::get_poly_space_numbering_inverse() const
+{
+  return Utilities::invert_permutation(get_poly_space_numbering());
+}
+
+
+
+template <int dim, int spacedim>
+std::size_t
+FE_Poly<dim, spacedim>::memory_consumption() const
+{
+  return FiniteElement<dim, spacedim>::memory_consumption() +
+         poly_space->memory_consumption();
+}
+
 #endif
 
 #include "fe_poly.inst"

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.