65 get_regularity_from_degree(
const unsigned int fe_degree)
68 ExcMessage(
"FE_Hermite only supports odd polynomial degrees."));
69 return (fe_degree == 0) ? 0 : (fe_degree - 1) / 2;
74 std::vector<unsigned int>
75 get_hermite_dpo_vector(
const unsigned int dim,
76 const unsigned int regularity)
78 std::vector<unsigned int> result(dim + 1, 0);
93 hermite_hierarchic_to_lexicographic_numbering(
94 const unsigned int regularity,
95 std::vector<unsigned int> &h2l);
101 hermite_hierarchic_to_lexicographic_numbering<1>(
102 const unsigned int regularity,
103 std::vector<unsigned int> &h2l)
105 const unsigned int node_dofs_1d = regularity + 1;
110 for (
unsigned int di = 0; di < 2; ++di)
111 for (
unsigned int i = 0; i < node_dofs_1d; ++i)
112 h2l[i + di * node_dofs_1d] = i + di * node_dofs_1d;
119 hermite_hierarchic_to_lexicographic_numbering<2>(
120 const unsigned int regularity,
121 std::vector<unsigned int> &h2l)
123 const unsigned int node_dofs_1d = regularity + 1;
124 const unsigned int dim_dofs_1d = 2 * node_dofs_1d;
125 unsigned int offset = 0;
130 for (
unsigned int di = 0; di < 2; ++di)
131 for (
unsigned int dj = 0; dj < 2; ++dj)
133 for (
unsigned int i = 0; i < node_dofs_1d; ++i)
134 for (
unsigned int j = 0; j < node_dofs_1d; ++j)
135 h2l[j + i * node_dofs_1d + offset] =
136 j + i * dim_dofs_1d + (dj + di * dim_dofs_1d) * node_dofs_1d;
138 offset += node_dofs_1d * node_dofs_1d;
146 hermite_hierarchic_to_lexicographic_numbering<3>(
147 const unsigned int regularity,
148 std::vector<unsigned int> &h2l)
150 const unsigned int node_dofs_1d = regularity + 1;
151 const unsigned int node_dofs_2d = node_dofs_1d * node_dofs_1d;
153 const unsigned int dim_dofs_1d = 2 * node_dofs_1d;
154 const unsigned int dim_dofs_2d = dim_dofs_1d * dim_dofs_1d;
156 unsigned int offset = 0;
161 for (
unsigned int di = 0; di < 2; ++di)
162 for (
unsigned int dj = 0; dj < 2; ++dj)
163 for (
unsigned int dk = 0; dk < 2; ++dk)
165 for (
unsigned int i = 0; i < node_dofs_1d; ++i)
166 for (
unsigned int j = 0; j < node_dofs_1d; ++j)
167 for (
unsigned int k = 0; k < node_dofs_1d; ++k)
168 h2l[k + j * node_dofs_1d + i * node_dofs_2d + offset] =
169 k + j * dim_dofs_1d + i * dim_dofs_2d +
170 node_dofs_1d * (dk + dj * dim_dofs_1d + di * dim_dofs_2d);
172 offset += node_dofs_1d * node_dofs_2d;
179 std::vector<unsigned int>
180 hermite_hierarchic_to_lexicographic_numbering(
const unsigned int regularity)
182 const std::vector<unsigned int> dpo =
183 get_hermite_dpo_vector(dim, regularity);
184 const ::FiniteElementData<dim> face_data(dpo,
187 std::vector<unsigned int> renumbering(face_data.dofs_per_cell);
189 hermite_hierarchic_to_lexicographic_numbering<dim>(regularity,
198 std::vector<unsigned int>
199 hermite_lexicographic_to_hierarchic_numbering(
const unsigned int regularity)
202 hermite_hierarchic_to_lexicographic_numbering<dim>(regularity));
209 get_hermite_polynomials(
const unsigned int fe_degree)
211 const unsigned int regularity = get_regularity_from_degree(fe_degree);
216 std::vector<unsigned int> renumber =
217 internal::hermite_hierarchic_to_lexicographic_numbering<dim>(
219 polynomial_basis.set_numbering(renumber);
221 return polynomial_basis;
235 template <
int spacedim,
typename Number>
237 rescale_fe_hermite_values(
242 double cell_extent = 1.0;
246 &mapping_data) !=
nullptr)
258 const unsigned int n_q_points_out = value_list.size(1);
259 (void)n_dofs_per_cell;
264 std::vector<unsigned int> l2h =
265 internal::hermite_lexicographic_to_hierarchic_numbering<1>(
268 for (
unsigned int q = 0; q < n_q_points_out; ++q)
270 double factor_1 = 1.0;
272 for (
unsigned int d1 = 0, d2 = regularity + 1; d2 < n_dofs_per_cell;
280 value_list(l2h[d1], q) *= factor_1;
281 value_list(l2h[d2], q) *= factor_1;
283 factor_1 *= cell_extent;
290 template <
int spacedim,
typename Number>
292 rescale_fe_hermite_values(
301 &mapping_data) !=
nullptr)
306 cell_extents =
data->cell_extents;
313 const unsigned int n_dofs_per_dim = 2 * regularity + 2;
314 const unsigned int n_q_points_out = value_list.size(1);
315 (void)n_dofs_per_cell;
320 std::vector<unsigned int> l2h =
321 internal::hermite_lexicographic_to_hierarchic_numbering<2>(
326 for (
unsigned int q = 0; q < n_q_points_out; ++q)
328 double factor_2 = 1.0;
330 for (
unsigned int d3 = 0, d4 = regularity + 1; d4 < n_dofs_per_dim;
333 double factor_1 = factor_2;
335 for (
unsigned int d1 = 0, d2 = regularity + 1;
345 value_list(l2h[d1 + d3 * n_dofs_per_dim], q) *= factor_1;
346 value_list(l2h[d2 + d3 * n_dofs_per_dim], q) *= factor_1;
347 value_list(l2h[d1 + d4 * n_dofs_per_dim], q) *= factor_1;
348 value_list(l2h[d2 + d4 * n_dofs_per_dim], q) *= factor_1;
350 factor_1 *= cell_extents[0];
353 factor_2 *= cell_extents[1];
360 template <
int spacedim,
typename Number>
362 rescale_fe_hermite_values(
371 &mapping_data) !=
nullptr)
376 cell_extents =
data->cell_extents;
383 const unsigned int n_dofs_per_dim = 2 * regularity + 2;
384 const unsigned int n_dofs_per_quad = n_dofs_per_dim * n_dofs_per_dim;
385 const unsigned int n_q_points_out = value_list.size(1);
386 (void)n_dofs_per_cell;
391 std::vector<unsigned int> l2h =
392 internal::hermite_lexicographic_to_hierarchic_numbering<3>(
395 for (
unsigned int q = 0; q < n_q_points_out; ++q)
397 double factor_3 = 1.0;
399 for (
unsigned int d5 = 0, d6 = regularity + 1; d6 < n_dofs_per_dim;
402 double factor_2 = factor_3;
404 for (
unsigned int d3 = 0, d4 = regularity + 1;
408 double factor_1 = factor_2;
410 for (
unsigned int d1 = 0, d2 = regularity + 1;
421 l2h[d1 + d3 * n_dofs_per_dim + d5 * n_dofs_per_quad],
424 l2h[d2 + d3 * n_dofs_per_dim + d5 * n_dofs_per_quad],
427 l2h[d1 + d4 * n_dofs_per_dim + d5 * n_dofs_per_quad],
430 l2h[d2 + d4 * n_dofs_per_dim + d5 * n_dofs_per_quad],
433 l2h[d1 + d3 * n_dofs_per_dim + d6 * n_dofs_per_quad],
436 l2h[d2 + d3 * n_dofs_per_dim + d6 * n_dofs_per_quad],
439 l2h[d1 + d4 * n_dofs_per_dim + d6 * n_dofs_per_quad],
442 l2h[d2 + d4 * n_dofs_per_dim + d6 * n_dofs_per_quad],
445 factor_1 *= cell_extents[0];
448 factor_2 *= cell_extents[1];
451 factor_3 *= cell_extents[2];
462template <
int dim,
int spacedim>
465 internal::get_hermite_polynomials<dim>(fe_degree),
468 internal::get_regularity_from_degree(fe_degree)),
470 std::max(1U, fe_degree),
478 , regularity(
internal::get_regularity_from_degree(fe_degree))
480 Assert((fe_degree % 2 == 1),
482 "ERROR: The current implementation of Hermite interpolation "
483 "polynomials is only defined for odd polynomial degrees. Running "
484 "in release mode will use a polynomial degree of max(1,fe_degree-1) "
485 "to protect against unexpected internal bugs."));
490template <
int dim,
int spacedim>
494 std::ostringstream name_buffer;
496 << this->degree <<
")";
497 return name_buffer.str();
502template <
int dim,
int spacedim>
503std::unique_ptr<FiniteElement<dim, spacedim>>
506 return std::make_unique<FE_Hermite<dim, spacedim>>(*this);
511template <
int dim,
int spacedim>
530template <
int dim,
int spacedim>
531std::vector<std::pair<unsigned int, unsigned int>>
585template <
int dim,
int spacedim>
586std::vector<std::pair<unsigned int, unsigned int>>
600template <
int dim,
int spacedim>
601std::vector<std::pair<unsigned int, unsigned int>>
604 const unsigned int face_no)
const
617template <
int dim,
int spacedim>
621 const unsigned int codim)
const
638 if (this->degree < fe_hermite_other->degree)
640 else if (this->degree == fe_hermite_other->degree)
648 if (fe_q_other->degree == 1)
650 if (this->degree == 1)
655 else if (this->degree <= fe_q_other->degree)
663 if (fe_p_other->degree == 1)
665 if (this->degree == 1)
670 else if (this->degree <= fe_p_other->degree)
678 if (fe_wp_other->degree == 1)
680 if (this->degree == 1)
685 else if (this->degree <= fe_wp_other->degree)
693 if (fe_pp_other->degree == 1)
695 if (this->degree == 1)
700 else if (this->degree <= fe_pp_other->degree)
708 if (fe_nothing->is_dominating())
723template <
int dim,
int spacedim>
724std::vector<unsigned int>
727 return internal::hermite_lexicographic_to_hierarchic_numbering<dim>(
733template <
int dim,
int spacedim>
736 const unsigned int derivative_order)
const
742 const unsigned int degree = this->degree;
743 const unsigned int regularity = this->get_regularity();
744 const unsigned int dofs_per_face = this->n_dofs_per_face();
749 const unsigned int relevant_dofs_per_face = dofs_per_face / (regularity + 1);
756 const std::vector<unsigned int> l2h =
757 get_lexicographic_to_hierarchic_numbering();
758 const unsigned int dofs_per_cell =
Utilities::pow(degree + 1, dim);
781 for (
unsigned int d = 0, batch_size = 1; d < dim;
782 ++d, batch_size *= degree + 1)
783 for (
unsigned int sublist_index = 0; sublist_index < relevant_dofs_per_face;
786 const unsigned int local_index = sublist_index % batch_size;
787 const unsigned int batch_index = sublist_index / batch_size;
791 (batch_index * (degree + 1) + derivative_order) * batch_size;
792 unsigned int correction = batch_size * (regularity + 1);
793 Assert(index + correction < dofs_per_cell,
796 dofs_on_each_face(2 * d, sublist_index) = l2h[index];
797 dofs_on_each_face(2 * d + 1, sublist_index) = l2h[index + correction];
800 return dofs_on_each_face;
805template <
int dim,
int spacedim>
813 const ::internal::FEValuesImplementation::MappingRelatedData<dim,
825 &fe_internal) !=
nullptr),
838 internal::Rescaler shape_fix;
839 for (
unsigned int i = 0; i < output_data.shape_values.size(0); ++i)
840 for (
unsigned int q = 0; q < output_data.shape_values.size(1); ++q)
841 output_data.shape_values(i, q) = fe_data.
shape_values(i, q);
842 shape_fix.rescale_fe_hermite_values(*
this,
844 output_data.shape_values);
850 for (
unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
856 internal::Rescaler grad_fix;
857 grad_fix.rescale_fe_hermite_values(*
this,
859 output_data.shape_gradients);
865 for (
unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
871 internal::Rescaler hessian_fix;
872 hessian_fix.rescale_fe_hermite_values(*
this,
874 output_data.shape_hessians);
880 for (
unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
887 internal::Rescaler third_dev_fix;
888 third_dev_fix.rescale_fe_hermite_values(
889 *
this, mapping_internal, output_data.shape_3rd_derivatives);
895template <
int dim,
int spacedim>
899 const unsigned int face_no,
903 const ::internal::FEValuesImplementation::MappingRelatedData<dim,
917 &fe_internal) !=
nullptr),
925 &mapping_internal) !=
nullptr),
936 ReferenceCells::get_hypercube<dim>(),
938 cell->combined_face_orientation(face_no),
939 quadrature[0].
size());
946 for (
unsigned int k = 0; k < this->dofs_per_cell; ++k)
947 for (
unsigned int i = 0; i < quadrature[0].
size(); ++i)
948 output_data.shape_values(k, i) = fe_data.
shape_values[k][i + offset];
950 internal::Rescaler shape_face_fix;
951 shape_face_fix.rescale_fe_hermite_values(*
this,
953 output_data.shape_values);
958 for (
unsigned int k = 0; k < this->dofs_per_cell; ++k)
962 quadrature[0].
size()),
967 internal::Rescaler grad_face_fix;
968 grad_face_fix.rescale_fe_hermite_values(*
this,
970 output_data.shape_gradients);
975 for (
unsigned int k = 0; k < this->dofs_per_cell; ++k)
979 quadrature[0].
size()),
984 internal::Rescaler hessian_face_fix;
985 hessian_face_fix.rescale_fe_hermite_values(*
this,
987 output_data.shape_hessians);
992 for (
unsigned int k = 0; k < this->dofs_per_cell; ++k)
996 quadrature[0].
size()),
1002 internal::Rescaler shape_3rd_face_fix;
1003 shape_3rd_face_fix.rescale_fe_hermite_values(
1004 *
this, mapping_internal, output_data.shape_3rd_derivatives);
1011#include "fe/fe_hermite.inst"
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const override
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_vertex_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const override
Table< 2, unsigned int > get_dofs_corresponding_to_outward_normal_derivatives(const unsigned int derivative_order) const
unsigned int get_regularity() const
virtual FiniteElementDomination::Domination compare_for_domination(const FiniteElement< dim, spacedim > &other_fe, const unsigned int codim) const override
virtual void fill_fe_values(const typename Triangulation< dim, spacedim >::cell_iterator &cell, 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, ::internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > &output_data) const override
virtual UpdateFlags requires_update_flags(const UpdateFlags update_flags) const override
virtual std::string get_name() const override
std::vector< unsigned int > get_lexicographic_to_hierarchic_numbering() const
FE_Hermite(const unsigned int fe_degree)
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_quad_dof_identities(const FiniteElement< dim, spacedim > &fe_other, const unsigned int face_no=0) const override
virtual void 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, ::internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > &output_data) const override
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_line_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const override
Table< 2, double > shape_values
Table< 2, Tensor< 3, dim > > shape_3rd_derivatives
Table< 2, Tensor< 2, dim > > shape_hessians
Table< 2, Tensor< 1, dim > > shape_gradients
virtual UpdateFlags requires_update_flags(const UpdateFlags update_flags) const override
unsigned int n_dofs_per_cell() const
unsigned int n_dofs_per_face(unsigned int face_no=0, unsigned int child=0) const
unsigned int n_unique_faces() const
Tensor< 1, dim > cell_extents
Abstract base class for mapping classes.
virtual void transform(const ArrayView< const Tensor< 1, dim > > &input, const MappingKind kind, const typename Mapping< dim, spacedim >::InternalDataBase &internal, const ArrayView< Tensor< 1, spacedim > > &output) const =0
static std::vector< Polynomial< double > > generate_complete_basis(const unsigned int regularity)
Class storing the offset index into a Quadrature rule created by project_to_all_faces() or project_to...
static DataSetDescriptor face(const ReferenceCell< dim > &reference_cell, const unsigned int face_no, const types::geometric_orientation combined_orientation, const unsigned int n_quadrature_points)
unsigned int size() const
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
@ update_hessians
Second derivatives of shape functions.
@ update_values
Shape function values.
@ update_3rd_derivatives
Third derivatives of shape functions.
@ update_gradients
Shape function gradients.
@ mapping_covariant_gradient
@ mapping_covariant_hessian
std::vector< index_type > data
@ either_element_can_dominate
@ other_element_dominates
@ neither_element_dominates
std::string dim_string(const int dim, const int spacedim)
constexpr T pow(const T base, const int iexp)
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)