deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
fe_poly.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2004 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13
14#include <deal.II/base/config.h>
15
24
25#include <deal.II/fe/fe_poly.h>
28
30
31#ifndef DOXYGEN
32
33template <int dim, int spacedim>
35 : FiniteElement<dim, spacedim>(fe)
36 , poly_space(fe.poly_space->clone())
37{}
38
39template <int dim, int spacedim>
41 const ScalarPolynomialsBase<dim> &poly_space,
42 const FiniteElementData<dim> &fe_data,
43 const std::vector<bool> &restriction_is_additive_flags,
44 const std::vector<ComponentMask> &nonzero_components)
45 : FiniteElement<dim, spacedim>(fe_data,
46 restriction_is_additive_flags,
47 nonzero_components)
48 , poly_space(poly_space.clone())
49{}
50
51
52template <int dim, int spacedim>
53unsigned int
55{
56 return this->degree;
57}
58
59
60template <int dim, int spacedim>
61double
62FE_Poly<dim, spacedim>::shape_value(const unsigned int i,
63 const Point<dim> &p) const
64{
65 AssertIndexRange(i, this->n_dofs_per_cell());
66 return poly_space->compute_value(i, p);
67}
68
69
70template <int dim, int spacedim>
71double
73 const unsigned int i,
74 const Point<dim> &p,
75 const unsigned int component) const
76{
77 (void)component;
78 AssertIndexRange(i, this->n_dofs_per_cell());
79 AssertIndexRange(component, 1);
80 return poly_space->compute_value(i, p);
81}
82
83
84
85template <int dim, int spacedim>
87FE_Poly<dim, spacedim>::shape_grad(const unsigned int i,
88 const Point<dim> &p) const
89{
90 AssertIndexRange(i, this->n_dofs_per_cell());
91 return poly_space->template compute_derivative<1>(i, p);
92}
93
94
95
96template <int dim, int spacedim>
99 const Point<dim> &p,
100 const unsigned int component) const
101{
102 (void)component;
103 AssertIndexRange(i, this->n_dofs_per_cell());
104 AssertIndexRange(component, 1);
105 return poly_space->template compute_derivative<1>(i, p);
106}
107
108
109
110template <int dim, int spacedim>
112FE_Poly<dim, spacedim>::shape_grad_grad(const unsigned int i,
113 const Point<dim> &p) const
114{
115 AssertIndexRange(i, this->n_dofs_per_cell());
116 return poly_space->template compute_derivative<2>(i, p);
117}
118
119
120
121template <int dim, int spacedim>
124 const unsigned int i,
125 const Point<dim> &p,
126 const unsigned int component) const
127{
128 (void)component;
129 AssertIndexRange(i, this->n_dofs_per_cell());
130 AssertIndexRange(component, 1);
131 return poly_space->template compute_derivative<2>(i, p);
132}
133
134
135
136template <int dim, int spacedim>
139 const Point<dim> &p) const
140{
141 AssertIndexRange(i, this->n_dofs_per_cell());
142 return poly_space->template compute_derivative<3>(i, p);
143}
144
145
146
147template <int dim, int spacedim>
150 const unsigned int i,
151 const Point<dim> &p,
152 const unsigned int component) const
153{
154 (void)component;
155 AssertIndexRange(i, this->n_dofs_per_cell());
156 AssertIndexRange(component, 1);
157 return poly_space->template compute_derivative<3>(i, p);
158}
159
160
161
162template <int dim, int spacedim>
165 const Point<dim> &p) const
166{
167 AssertIndexRange(i, this->n_dofs_per_cell());
168 return poly_space->template compute_derivative<4>(i, p);
169}
170
171
172
173template <int dim, int spacedim>
176 const unsigned int i,
177 const Point<dim> &p,
178 const unsigned int component) const
179{
180 (void)component;
181 AssertIndexRange(i, this->n_dofs_per_cell());
182 AssertIndexRange(component, 1);
183 return poly_space->template compute_derivative<4>(i, p);
184}
185
186
187
188//---------------------------------------------------------------------------
189// Auxiliary functions
190//---------------------------------------------------------------------------
191
192
193template <int dim, int spacedim>
196{
198
199 if (flags & update_values)
200 out |= update_values;
201 if (flags & update_gradients)
203 if (flags & update_hessians)
206 if (flags & update_3rd_derivatives)
211 if (flags & update_normal_vectors)
213
214 return out;
215}
216
217
218
219//---------------------------------------------------------------------------
220// Fill data of FEValues
221//---------------------------------------------------------------------------
222
223
224
234template <int dim, int spacedim>
235bool
236higher_derivatives_need_correcting(
237 const Mapping<dim, spacedim> &mapping,
239 &mapping_data,
240 const unsigned int n_q_points,
241 const UpdateFlags update_flags)
242{
243 // If higher derivatives weren't requested we don't need to correct them.
244 const bool update_higher_derivatives =
245 (update_flags & update_hessians) || (update_flags & update_3rd_derivatives);
246 if (!update_higher_derivatives)
247 return false;
248
249 // If we have a Cartesian mapping, we know that jacoban_pushed_forward_grads
250 // are identically zero.
251 if (dynamic_cast<const MappingCartesian<dim> *>(&mapping))
252 return false;
253
254 // Here, we should check if jacobian_pushed_forward_grads are zero at the
255 // quadrature points. This is yet to be implemented.
256 (void)mapping_data;
257 (void)n_q_points;
258
259 return true;
260}
261
262
263
264template <int dim, int spacedim>
265void
268 const CellSimilarity::Similarity cell_similarity,
269 const Quadrature<dim> &quadrature,
270 const Mapping<dim, spacedim> &mapping,
271 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_internal,
273 &mapping_data,
274 const typename FiniteElement<dim, spacedim>::InternalDataBase &fe_internal,
276 spacedim>
277 &output_data) const
278{
279 // convert data object to internal
280 // data for this class. fails with
281 // an exception if that is not
282 // possible
283 Assert(dynamic_cast<const InternalData *>(&fe_internal) != nullptr,
285 const InternalData &fe_data = static_cast<const InternalData &>(fe_internal);
286
287 const UpdateFlags flags(fe_data.update_each);
288
289 const bool need_to_correct_higher_derivatives =
290 higher_derivatives_need_correcting(mapping,
291 mapping_data,
292 quadrature.size(),
293 flags);
294
295 // transform gradients and higher derivatives. there is nothing to do
296 // for values since we already emplaced them into output_data when
297 // we were in get_data()
298 if ((flags & update_gradients) &&
299 (cell_similarity != CellSimilarity::translation))
300 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
301 mapping.transform(make_array_view(fe_data.shape_gradients, k),
303 mapping_internal,
304 make_array_view(output_data.shape_gradients, k));
305
306 if ((flags & update_hessians) &&
307 (cell_similarity != CellSimilarity::translation))
308 {
309 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
310 mapping.transform(make_array_view(fe_data.shape_hessians, k),
312 mapping_internal,
313 make_array_view(output_data.shape_hessians, k));
314
315 if (need_to_correct_higher_derivatives)
316 correct_hessians(output_data, mapping_data, quadrature.size());
317 }
318
319 if ((flags & update_3rd_derivatives) &&
320 (cell_similarity != CellSimilarity::translation))
321 {
322 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
323 mapping.transform(make_array_view(fe_data.shape_3rd_derivatives, k),
325 mapping_internal,
326 make_array_view(output_data.shape_3rd_derivatives,
327 k));
328
329 if (need_to_correct_higher_derivatives)
330 correct_third_derivatives(output_data, mapping_data, quadrature.size());
331 }
332}
333
334
335
336template <int dim, int spacedim>
337void
340 const unsigned int face_no,
341 const hp::QCollection<dim - 1> &quadrature,
342 const Mapping<dim, spacedim> &mapping,
343 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_internal,
345 &mapping_data,
346 const typename FiniteElement<dim, spacedim>::InternalDataBase &fe_internal,
348 spacedim>
349 &output_data) const
350{
351 const unsigned int n_q_points =
352 quadrature[quadrature.size() == 1 ? 0 : face_no].size();
353
354 // convert data object to internal
355 // data for this class. fails with
356 // an exception if that is not
357 // possible
358 Assert(dynamic_cast<const InternalData *>(&fe_internal) != nullptr,
360 const InternalData &fe_data = static_cast<const InternalData &>(fe_internal);
361
362 // offset determines which data set
363 // to take (all data sets for all
364 // faces are stored contiguously)
365
366 const auto offset =
368 face_no,
369 cell->combined_face_orientation(
370 face_no),
371 quadrature);
372
373 const UpdateFlags flags(fe_data.update_each);
374
375 const bool need_to_correct_higher_derivatives =
376 higher_derivatives_need_correcting(mapping,
377 mapping_data,
378 n_q_points,
379 flags);
380
381 // transform gradients and higher derivatives. we also have to copy
382 // the values (unlike in the case of fill_fe_values()) since
383 // we need to take into account the offsets
384 if (flags & update_values)
385 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
386 for (unsigned int i = 0; i < n_q_points; ++i)
387 output_data.shape_values(k, i) = fe_data.shape_values[k][i + offset];
388
389 if (flags & update_gradients)
390 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
391 mapping.transform(
392 make_array_view(fe_data.shape_gradients, k, offset, n_q_points),
394 mapping_internal,
395 make_array_view(output_data.shape_gradients, k));
396
397 if (flags & update_hessians)
398 {
399 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
400 mapping.transform(
401 make_array_view(fe_data.shape_hessians, k, offset, n_q_points),
403 mapping_internal,
404 make_array_view(output_data.shape_hessians, k));
405
406 if (need_to_correct_higher_derivatives)
407 correct_hessians(output_data, mapping_data, n_q_points);
408 }
409
410 if (flags & update_3rd_derivatives)
411 {
412 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
413 mapping.transform(
414 make_array_view(fe_data.shape_3rd_derivatives, k, offset, n_q_points),
416 mapping_internal,
417 make_array_view(output_data.shape_3rd_derivatives, k));
418
419 if (need_to_correct_higher_derivatives)
420 correct_third_derivatives(output_data, mapping_data, n_q_points);
421 }
422}
423
424
425
426template <int dim, int spacedim>
427void
430 const unsigned int face_no,
431 const unsigned int sub_no,
432 const Quadrature<dim - 1> &quadrature,
433 const Mapping<dim, spacedim> &mapping,
434 const typename Mapping<dim, spacedim>::InternalDataBase &mapping_internal,
436 &mapping_data,
437 const typename FiniteElement<dim, spacedim>::InternalDataBase &fe_internal,
439 spacedim>
440 &output_data) const
441{
442 // convert data object to internal
443 // data for this class. fails with
444 // an exception if that is not
445 // possible
446 Assert(dynamic_cast<const InternalData *>(&fe_internal) != nullptr,
448 const InternalData &fe_data = static_cast<const InternalData &>(fe_internal);
449
450 // offset determines which data set
451 // to take (all data sets for all
452 // sub-faces are stored contiguously)
453
454 const auto offset =
456 face_no,
457 sub_no,
458 cell->combined_face_orientation(
459 face_no),
460 quadrature.size(),
461 cell->subface_case(face_no));
462
463 const UpdateFlags flags(fe_data.update_each);
464
465 const bool need_to_correct_higher_derivatives =
466 higher_derivatives_need_correcting(mapping,
467 mapping_data,
468 quadrature.size(),
469 flags);
470
471 // transform gradients and higher derivatives. we also have to copy
472 // the values (unlike in the case of fill_fe_values()) since
473 // we need to take into account the offsets
474 if (flags & update_values)
475 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
476 for (unsigned int i = 0; i < quadrature.size(); ++i)
477 output_data.shape_values(k, i) = fe_data.shape_values[k][i + offset];
478
479 if (flags & update_gradients)
480 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
481 mapping.transform(
482 make_array_view(fe_data.shape_gradients, k, offset, quadrature.size()),
484 mapping_internal,
485 make_array_view(output_data.shape_gradients, k));
486
487 if (flags & update_hessians)
488 {
489 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
490 mapping.transform(
491 make_array_view(fe_data.shape_hessians, k, offset, quadrature.size()),
493 mapping_internal,
494 make_array_view(output_data.shape_hessians, k));
495
496 if (need_to_correct_higher_derivatives)
497 correct_hessians(output_data, mapping_data, quadrature.size());
498 }
499
500 if (flags & update_3rd_derivatives)
501 {
502 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
503 mapping.transform(make_array_view(fe_data.shape_3rd_derivatives,
504 k,
505 offset,
506 quadrature.size()),
508 mapping_internal,
509 make_array_view(output_data.shape_3rd_derivatives,
510 k));
511
512 if (need_to_correct_higher_derivatives)
513 correct_third_derivatives(output_data, mapping_data, quadrature.size());
514 }
515}
516
517
518
519template <int dim, int spacedim>
520void
523 &output_data,
525 &mapping_data,
526 const unsigned int n_q_points) const
527{
528 for (unsigned int dof = 0; dof < this->n_dofs_per_cell(); ++dof)
529 for (unsigned int i = 0; i < n_q_points; ++i)
530 for (unsigned int j = 0; j < spacedim; ++j)
531 output_data.shape_hessians[dof][i] -=
532 mapping_data.jacobian_pushed_forward_grads[i][j] *
533 output_data.shape_gradients[dof][i][j];
534}
535
536
537
538template <int dim, int spacedim>
539void
542 &output_data,
544 &mapping_data,
545 const unsigned int n_q_points) const
546{
547 for (unsigned int dof = 0; dof < this->n_dofs_per_cell(); ++dof)
548 for (unsigned int i = 0; i < n_q_points; ++i)
549 for (unsigned int j = 0; j < spacedim; ++j)
550 for (unsigned int k = 0; k < spacedim; ++k)
551 for (unsigned int l = 0; l < spacedim; ++l)
552 for (unsigned int m = 0; m < spacedim; ++m)
553 {
554 output_data.shape_3rd_derivatives[dof][i][j][k][l] -=
555 (mapping_data.jacobian_pushed_forward_grads[i][m][j][l] *
556 output_data.shape_hessians[dof][i][k][m]) +
557 (mapping_data.jacobian_pushed_forward_grads[i][m][k][l] *
558 output_data.shape_hessians[dof][i][j][m]) +
559 (mapping_data.jacobian_pushed_forward_grads[i][m][j][k] *
560 output_data.shape_hessians[dof][i][l][m]) +
561 (mapping_data
562 .jacobian_pushed_forward_2nd_derivatives[i][m][j][k][l] *
563 output_data.shape_gradients[dof][i][m]);
564 }
565}
566
567
568
569template <int dim, int spacedim>
572{
573 return *poly_space;
574}
575
576
577
578template <int dim, int spacedim>
579std::vector<unsigned int>
581{
582 auto *const space_tensor_prod =
583 dynamic_cast<TensorProductPolynomials<dim> *>(this->poly_space.get());
584 if (space_tensor_prod != nullptr)
585 return space_tensor_prod->get_numbering();
586
587 auto *const space_tensor_prod_aniso =
588 dynamic_cast<AnisotropicPolynomials<dim> *>(this->poly_space.get());
589 if (space_tensor_prod_aniso != nullptr)
590 return space_tensor_prod_aniso->get_numbering();
591
592 auto *const space_tensor_prod_piecewise = dynamic_cast<
594 this->poly_space.get());
595 if (space_tensor_prod_piecewise != nullptr)
596 return space_tensor_prod_piecewise->get_numbering();
597
598 auto *const space_tensor_prod_bubbles =
600 this->poly_space.get());
601 if (space_tensor_prod_bubbles != nullptr)
602 return space_tensor_prod_bubbles->get_numbering();
603
604 auto *const space_tensor_prod_const =
605 dynamic_cast<TensorProductPolynomialsConst<dim> *>(this->poly_space.get());
606 if (space_tensor_prod_const != nullptr)
607 return space_tensor_prod_const->get_numbering();
608
610 return std::vector<unsigned int>();
611}
612
613
614
615template <int dim, int spacedim>
616std::vector<unsigned int>
618{
619 return Utilities::invert_permutation(get_poly_space_numbering());
620}
621
622
623
624template <int dim, int spacedim>
625std::size_t
627{
629 poly_space->memory_consumption();
630}
631
632#endif
633
634#include "fe/fe_poly.inst"
635
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
const std::vector< unsigned int > & get_numbering() const
virtual Tensor< 2, dim > shape_grad_grad(const unsigned int i, const Point< dim > &p) const override
virtual Tensor< 2, dim > shape_grad_grad_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const override
virtual Tensor< 3, dim > shape_3rd_derivative_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const override
std::vector< unsigned int > get_poly_space_numbering_inverse() const
virtual double shape_value_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const override
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)
void correct_hessians(internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > &output_data, const internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &mapping_data, const unsigned int n_q_points) const
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 Tensor< 1, dim > shape_grad(const unsigned int i, const Point< dim > &p) const override
unsigned int get_degree() const
const ScalarPolynomialsBase< dim > & get_poly_space() const
virtual Tensor< 4, dim > shape_4th_derivative_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const override
void 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
virtual double shape_value(const unsigned int i, const Point< dim > &p) const override
virtual Tensor< 3, dim > shape_3rd_derivative(const unsigned int i, const Point< dim > &p) 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 UpdateFlags requires_update_flags(const UpdateFlags update_flags) const override
virtual Tensor< 4, dim > shape_4th_derivative(const unsigned int i, const Point< dim > &p) const override
std::vector< unsigned int > get_poly_space_numbering() const
virtual std::size_t memory_consumption() const override
virtual void 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, ::internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > &output_data) const override
virtual Tensor< 1, dim > shape_grad_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const override
virtual std::size_t memory_consumption() const
Abstract base class for mapping classes.
Definition mapping.h:318
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
Definition point.h:111
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)
static DataSetDescriptor subface(const ReferenceCell< dim > &reference_cell, const unsigned int face_no, const unsigned int subface_no, const types::geometric_orientation combined_orientation, const unsigned int n_quadrature_points, const internal::SubfaceCase< dim > ref_case=internal::SubfaceCase< dim >::case_isotropic)
unsigned int size() const
const std::vector< unsigned int > & get_numbering() const
const std::vector< unsigned int > & get_numbering() const
const std::vector< unsigned int > & get_numbering() const
unsigned int size() const
Definition collection.h:314
std::vector< Tensor< 3, spacedim > > jacobian_pushed_forward_grads
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_NOT_IMPLEMENTED()
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
UpdateFlags
@ update_jacobian_pushed_forward_2nd_derivatives
@ update_jacobian_pushed_forward_grads
@ update_hessians
Second derivatives of shape functions.
@ update_values
Shape function values.
@ update_normal_vectors
Normal vectors.
@ update_3rd_derivatives
Third derivatives of shape functions.
@ update_JxW_values
Transformed quadrature weights.
@ update_covariant_transformation
Covariant transformation.
@ update_gradients
Shape function gradients.
@ update_default
No update.
@ mapping_covariant_gradient
Definition mapping.h:100
@ mapping_covariant
Definition mapping.h:89
@ mapping_covariant_hessian
Definition mapping.h:150
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell< dim > &reference_cell)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
Definition utilities.h:1670