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_dgp_nonparametric.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) 2002 - 2026 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
15
17
18#include <deal.II/fe/fe.h>
22#include <deal.II/fe/mapping.h>
23
24#include <deal.II/grid/tria.h>
26
27#include <memory>
28#include <sstream>
29
30
32
33template <int dim, int spacedim>
35 const unsigned int degree)
36 : FiniteElement<dim, spacedim>(
37 FiniteElementData<dim>(get_dpo_vector(degree),
38 1,
39 degree,
40 FiniteElementData<dim>::L2),
41 std::vector<bool>(
42 FiniteElementData<dim>(get_dpo_vector(degree), 1, degree)
43 .n_dofs_per_cell(),
44 true),
45 std::vector<ComponentMask>(
46 FiniteElementData<dim>(get_dpo_vector(degree), 1, degree)
47 .n_dofs_per_cell(),
48 ComponentMask(std::vector<bool>(1, true))))
49 , polynomial_space(Polynomials::Legendre::generate_complete_basis(degree))
50{
51 const unsigned int n_dofs = this->n_dofs_per_cell();
52 for (const unsigned int ref_case :
55 {
56 if (dim != 2 && ref_case != RefinementCase<dim>::isotropic_refinement)
57 // do nothing, as anisotropic
58 // refinement is not
59 // implemented so far
60 continue;
61
62 const unsigned int nc =
63 this->reference_cell().n_children(RefinementCase<dim>(ref_case));
64 for (unsigned int i = 0; i < nc; ++i)
65 {
66 this->prolongation[ref_case - 1][i].reinit(n_dofs, n_dofs);
67 // Fill prolongation matrices with
68 // embedding operators
69 for (unsigned int j = 0; j < n_dofs; ++j)
70 this->prolongation[ref_case - 1][i](j, j) = 1.;
71 }
72 }
73
74 // restriction can be defined
75 // through projection for
76 // discontinuous elements, but is
77 // presently not implemented for DGPNonparametric
78 // elements.
79 //
80 // if it were, then the following
81 // snippet would be the right code
82 // if ((degree < Matrices::n_projection_matrices) &&
83 // (Matrices::projection_matrices[degree] != 0))
84 // {
85 // restriction[0].fill (Matrices::projection_matrices[degree]);
86 // }
87 // else
88 // // matrix undefined, set size to zero
89 // for (unsigned int i=0;i<GeometryInfo<dim>::max_children_per_cell;++i)
90 // restriction[i].reinit(0, 0);
91 // since not implemented, set to
92 // "empty". however, that is done in the
93 // default constructor already, so do nothing
94 // for (unsigned int i=0;i<GeometryInfo<dim>::max_children_per_cell;++i)
95 // this->restriction[i].reinit(0, 0);
96
97 // note further, that these
98 // elements have neither support
99 // nor face-support points, so
100 // leave these fields empty
101}
102
103
104
105template <int dim, int spacedim>
106std::string
108{
109 // note that the
110 // FETools::get_fe_by_name
111 // function depends on the
112 // particular format of the string
113 // this function returns, so they
114 // have to be kept in synch
115
116 std::ostringstream namebuf;
117 namebuf << "FE_DGPNonparametric<" << Utilities::dim_string(dim, spacedim)
118 << ">(" << this->degree << ")";
119
120 return namebuf.str();
121}
122
123
124
125template <int dim, int spacedim>
126std::unique_ptr<FiniteElement<dim, spacedim>>
128{
129 return std::make_unique<FE_DGPNonparametric<dim, spacedim>>(*this);
130}
131
132
133
134template <int dim, int spacedim>
135double
137 const Point<dim> &p) const
138{
139 (void)i;
140 (void)p;
141 AssertIndexRange(i, this->n_dofs_per_cell());
142 AssertThrow(false,
144 return 0;
145}
146
147
148
149template <int dim, int spacedim>
150double
152 const unsigned int i,
153 const Point<dim> &p,
154 const unsigned int component) const
155{
156 (void)i;
157 (void)p;
158 (void)component;
159 AssertIndexRange(i, this->n_dofs_per_cell());
160 AssertIndexRange(component, 1);
161 AssertThrow(false,
163 return 0;
164}
165
166
167
168template <int dim, int spacedim>
171 const Point<dim> &p) const
172{
173 (void)i;
174 (void)p;
175 AssertIndexRange(i, this->n_dofs_per_cell());
176 AssertThrow(false,
178 return Tensor<1, dim>();
179}
180
181
182template <int dim, int spacedim>
185 const unsigned int i,
186 const Point<dim> &p,
187 const unsigned int component) const
188{
189 (void)i;
190 (void)p;
191 (void)component;
192 AssertIndexRange(i, this->n_dofs_per_cell());
193 AssertIndexRange(component, 1);
194 AssertThrow(false,
196 return Tensor<1, dim>();
197}
198
199
200
201template <int dim, int spacedim>
204 const Point<dim> &p) const
205{
206 (void)i;
207 (void)p;
208 AssertIndexRange(i, this->n_dofs_per_cell());
209 AssertThrow(false,
211 return Tensor<2, dim>();
212}
213
214
215
216template <int dim, int spacedim>
219 const unsigned int i,
220 const Point<dim> &p,
221 const unsigned int component) const
222{
223 (void)i;
224 (void)p;
225 (void)component;
226 AssertIndexRange(i, this->n_dofs_per_cell());
227 AssertIndexRange(component, 1);
228 AssertThrow(false,
230 return Tensor<2, dim>();
231}
232
233
234//---------------------------------------------------------------------------
235// Auxiliary functions
236//---------------------------------------------------------------------------
237
238
239template <int dim, int spacedim>
240std::vector<unsigned int>
242{
243 std::vector<unsigned int> dpo(dim + 1, static_cast<unsigned int>(0));
244 dpo[dim] = deg + 1;
245 for (unsigned int i = 1; i < dim; ++i)
246 {
247 dpo[dim] *= deg + 1 + i;
248 dpo[dim] /= i + 1;
249 }
250 return dpo;
251}
252
253
254
255template <int dim, int spacedim>
258 const UpdateFlags flags) const
259{
260 UpdateFlags out = flags;
261
264
265 return out;
266}
267
268
269
270//---------------------------------------------------------------------------
271// Data field initialization
272//---------------------------------------------------------------------------
273
274template <int dim, int spacedim>
275std::unique_ptr<typename FiniteElement<dim, spacedim>::InternalDataBase>
277 const UpdateFlags update_flags,
279 const Quadrature<dim> &,
281 spacedim>
282 & /*output_data*/) const
283{
284 // generate a new data object
285 auto data_ptr =
286 std::make_unique<typename FiniteElement<dim, spacedim>::InternalDataBase>();
287 data_ptr->update_each = requires_update_flags(update_flags);
288
289 // other than that, there is nothing we can add here as discussed
290 // in the general documentation of this class
291
292 return data_ptr;
293}
294
295
296
297//---------------------------------------------------------------------------
298// Fill data of FEValues
299//---------------------------------------------------------------------------
300
301template <int dim, int spacedim>
302void
306 const Quadrature<dim> &,
310 &mapping_data,
311 const typename FiniteElement<dim, spacedim>::InternalDataBase &fe_internal,
313 spacedim>
314 &output_data) const
315{
318
319 const unsigned int n_q_points = mapping_data.quadrature_points.size();
320
321 std::vector<double> values(
322 (fe_internal.update_each & update_values) ? this->n_dofs_per_cell() : 0);
323 std::vector<Tensor<1, dim>> grads(
324 (fe_internal.update_each & update_gradients) ? this->n_dofs_per_cell() : 0);
325 std::vector<Tensor<2, dim>> grad_grads(
326 (fe_internal.update_each & update_hessians) ? this->n_dofs_per_cell() : 0);
327 std::vector<Tensor<3, dim>> empty_vector_of_3rd_order_tensors;
328 std::vector<Tensor<4, dim>> empty_vector_of_4th_order_tensors;
329
330 if (fe_internal.update_each & (update_values | update_gradients))
331 for (unsigned int i = 0; i < n_q_points; ++i)
332 {
333 polynomial_space.evaluate(mapping_data.quadrature_points[i],
334 values,
335 grads,
336 grad_grads,
337 empty_vector_of_3rd_order_tensors,
338 empty_vector_of_4th_order_tensors);
339
340 if (fe_internal.update_each & update_values)
341 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
342 output_data.shape_values[k][i] = values[k];
343
344 if (fe_internal.update_each & update_gradients)
345 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
346 output_data.shape_gradients[k][i] = grads[k];
347
348 if (fe_internal.update_each & update_hessians)
349 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
350 output_data.shape_hessians[k][i] = grad_grads[k];
351 }
352}
353
354
355
356template <int dim, int spacedim>
357void
360 const unsigned int,
365 &mapping_data,
366 const typename FiniteElement<dim, spacedim>::InternalDataBase &fe_internal,
368 spacedim>
369 &output_data) const
370{
373
374 const unsigned int n_q_points = mapping_data.quadrature_points.size();
375
376 std::vector<double> values(
377 (fe_internal.update_each & update_values) ? this->n_dofs_per_cell() : 0);
378 std::vector<Tensor<1, dim>> grads(
379 (fe_internal.update_each & update_gradients) ? this->n_dofs_per_cell() : 0);
380 std::vector<Tensor<2, dim>> grad_grads(
381 (fe_internal.update_each & update_hessians) ? this->n_dofs_per_cell() : 0);
382 std::vector<Tensor<3, dim>> empty_vector_of_3rd_order_tensors;
383 std::vector<Tensor<4, dim>> empty_vector_of_4th_order_tensors;
384
385 if (fe_internal.update_each & (update_values | update_gradients))
386 for (unsigned int i = 0; i < n_q_points; ++i)
387 {
388 polynomial_space.evaluate(mapping_data.quadrature_points[i],
389 values,
390 grads,
391 grad_grads,
392 empty_vector_of_3rd_order_tensors,
393 empty_vector_of_4th_order_tensors);
394
395 if (fe_internal.update_each & update_values)
396 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
397 output_data.shape_values[k][i] = values[k];
398
399 if (fe_internal.update_each & update_gradients)
400 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
401 output_data.shape_gradients[k][i] = grads[k];
402
403 if (fe_internal.update_each & update_hessians)
404 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
405 output_data.shape_hessians[k][i] = grad_grads[k];
406 }
407}
408
409
410
411template <int dim, int spacedim>
412void
415 const unsigned int,
416 const unsigned int,
417 const Quadrature<dim - 1> &,
421 &mapping_data,
422 const typename FiniteElement<dim, spacedim>::InternalDataBase &fe_internal,
424 spacedim>
425 &output_data) const
426{
429
430 const unsigned int n_q_points = mapping_data.quadrature_points.size();
431
432 std::vector<double> values(
433 (fe_internal.update_each & update_values) ? this->n_dofs_per_cell() : 0);
434 std::vector<Tensor<1, dim>> grads(
435 (fe_internal.update_each & update_gradients) ? this->n_dofs_per_cell() : 0);
436 std::vector<Tensor<2, dim>> grad_grads(
437 (fe_internal.update_each & update_hessians) ? this->n_dofs_per_cell() : 0);
438 std::vector<Tensor<3, dim>> empty_vector_of_3rd_order_tensors;
439 std::vector<Tensor<4, dim>> empty_vector_of_4th_order_tensors;
440
441 if (fe_internal.update_each & (update_values | update_gradients))
442 for (unsigned int i = 0; i < n_q_points; ++i)
443 {
444 polynomial_space.evaluate(mapping_data.quadrature_points[i],
445 values,
446 grads,
447 grad_grads,
448 empty_vector_of_3rd_order_tensors,
449 empty_vector_of_4th_order_tensors);
450
451 if (fe_internal.update_each & update_values)
452 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
453 output_data.shape_values[k][i] = values[k];
454
455 if (fe_internal.update_each & update_gradients)
456 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
457 output_data.shape_gradients[k][i] = grads[k];
458
459 if (fe_internal.update_each & update_hessians)
460 for (unsigned int k = 0; k < this->n_dofs_per_cell(); ++k)
461 output_data.shape_hessians[k][i] = grad_grads[k];
462 }
463}
464
465
466
467template <int dim, int spacedim>
468void
470 const FiniteElement<dim, spacedim> &x_source_fe,
471 FullMatrix<double> &interpolation_matrix,
472 const unsigned int) const
473{
474 // this is only implemented, if the source
475 // FE is also a DGPNonparametric element. in that case,
476 // both elements have no dofs on their
477 // faces and the face interpolation matrix
478 // is necessarily empty -- i.e. there isn't
479 // much we need to do here.
480 (void)interpolation_matrix;
482 (x_source_fe.get_name().find("FE_DGPNonparametric<") == 0) ||
483 (dynamic_cast<const FE_DGPNonparametric<dim, spacedim> *>(&x_source_fe) !=
484 nullptr),
486
487 Assert(interpolation_matrix.m() == 0,
488 ExcDimensionMismatch(interpolation_matrix.m(), 0));
489 Assert(interpolation_matrix.n() == 0,
490 ExcDimensionMismatch(interpolation_matrix.n(), 0));
491}
492
493
494
495template <int dim, int spacedim>
496void
498 const FiniteElement<dim, spacedim> &x_source_fe,
499 const unsigned int,
500 FullMatrix<double> &interpolation_matrix,
501 const unsigned int) const
502{
503 // this is only implemented, if the source
504 // FE is also a DGPNonparametric element. in that case,
505 // both elements have no dofs on their
506 // faces and the face interpolation matrix
507 // is necessarily empty -- i.e. there isn't
508 // much we need to do here.
509 (void)interpolation_matrix;
511 (x_source_fe.get_name().find("FE_DGPNonparametric<") == 0) ||
512 (dynamic_cast<const FE_DGPNonparametric<dim, spacedim> *>(&x_source_fe) !=
513 nullptr),
515
516 Assert(interpolation_matrix.m() == 0,
517 ExcDimensionMismatch(interpolation_matrix.m(), 0));
518 Assert(interpolation_matrix.n() == 0,
519 ExcDimensionMismatch(interpolation_matrix.n(), 0));
520}
521
522
523
524template <int dim, int spacedim>
525bool
530
531
532
533template <int dim, int spacedim>
534std::vector<std::pair<unsigned int, unsigned int>>
536 const FiniteElement<dim, spacedim> &fe_other) const
537{
538 // there are no such constraints for DGPNonparametric
539 // elements at all
540 if (dynamic_cast<const FE_DGPNonparametric<dim, spacedim> *>(&fe_other) !=
541 nullptr)
542 return std::vector<std::pair<unsigned int, unsigned int>>();
543 else
544 {
546 return std::vector<std::pair<unsigned int, unsigned int>>();
547 }
548}
549
550
551
552template <int dim, int spacedim>
553std::vector<std::pair<unsigned int, unsigned int>>
555 const FiniteElement<dim, spacedim> &fe_other) const
556{
557 // there are no such constraints for DGPNonparametric
558 // elements at all
559 if (dynamic_cast<const FE_DGPNonparametric<dim, spacedim> *>(&fe_other) !=
560 nullptr)
561 return std::vector<std::pair<unsigned int, unsigned int>>();
562 else
563 {
565 return std::vector<std::pair<unsigned int, unsigned int>>();
566 }
567}
568
569
570
571template <int dim, int spacedim>
572std::vector<std::pair<unsigned int, unsigned int>>
574 const FiniteElement<dim, spacedim> &fe_other,
575 const unsigned int) const
576{
577 // there are no such constraints for DGPNonparametric
578 // elements at all
579 if (dynamic_cast<const FE_DGPNonparametric<dim, spacedim> *>(&fe_other) !=
580 nullptr)
581 return std::vector<std::pair<unsigned int, unsigned int>>();
582 else
583 {
585 return std::vector<std::pair<unsigned int, unsigned int>>();
586 }
587}
588
589
590
591template <int dim, int spacedim>
594 const FiniteElement<dim, spacedim> &fe_other,
595 const unsigned int codim) const
596{
597 Assert(codim <= dim, ExcImpossibleInDim(dim));
598
599 // vertex/line/face domination
600 // ---------------------------
601 if (codim > 0)
602 // this is a discontinuous element, so by definition there will
603 // be no constraints wherever this element comes together with
604 // any other kind of element
606
607 // cell domination
608 // ---------------
609 if (const FE_DGPNonparametric<dim, spacedim> *fe_nonparametric_other =
610 dynamic_cast<const FE_DGPNonparametric<dim, spacedim> *>(&fe_other))
611 {
612 if (this->degree < fe_nonparametric_other->degree)
614 else if (this->degree == fe_nonparametric_other->degree)
616 else
618 }
619 else if (const FE_Nothing<dim> *fe_nothing =
620 dynamic_cast<const FE_Nothing<dim> *>(&fe_other))
621 {
622 if (fe_nothing->is_dominating())
624 else
625 // the FE_Nothing has no degrees of freedom and it is typically used
626 // in a context where we don't require any continuity along the
627 // interface
629 }
630
633}
634
635
636
637template <int dim, int spacedim>
638bool
640 const unsigned int,
641 const unsigned int) const
642{
643 return true;
644}
645
646
647
648template <int dim, int spacedim>
649std::size_t
655
656
657
658template <int dim, int spacedim>
659unsigned int
661{
662 return this->degree;
663}
664
665
666
667// explicit instantiations
668#include "fe/fe_dgp_nonparametric.inst"
669
670
virtual std::unique_ptr< typename FiniteElement< dim, spacedim >::InternalDataBase > get_data(const UpdateFlags update_flags, const Mapping< dim, spacedim > &mapping, const Quadrature< dim > &quadrature, ::internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > &output_data) const override
unsigned int get_degree() const
virtual Tensor< 1, dim > shape_grad_component(const unsigned int i, const Point< dim > &p, const unsigned int component) 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< 2, dim > shape_grad_grad_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const override
virtual bool has_support_on_face(const unsigned int shape_index, const unsigned int face_index) const override
virtual Tensor< 2, dim > shape_grad_grad(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 Tensor< 1, dim > shape_grad(const unsigned int i, const Point< dim > &p) const override
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const override
virtual double shape_value(const unsigned int i, const Point< dim > &p) const override
virtual bool hp_constraints_are_implemented() const override
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 FiniteElementDomination::Domination compare_for_domination(const FiniteElement< dim, spacedim > &fe_other, const unsigned int codim=0) const override final
virtual void get_subface_interpolation_matrix(const FiniteElement< dim, spacedim > &source, const unsigned int subface, FullMatrix< double > &matrix, const unsigned int face_no=0) const override
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_line_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const override
static std::vector< unsigned int > get_dpo_vector(const unsigned int degree)
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_vertex_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const override
virtual double shape_value_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const override
virtual std::string get_name() const override
virtual void get_face_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix, const unsigned int face_no=0) const override
virtual UpdateFlags requires_update_flags(const UpdateFlags update_flags) 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 std::size_t memory_consumption() const override
unsigned int n_dofs_per_cell() const
ReferenceCell< dim > reference_cell() const
virtual std::string get_name() const =0
std::vector< std::vector< FullMatrix< double > > > prolongation
Definition fe.h:2561
size_type n() const
size_type m() const
Abstract base class for mapping classes.
Definition mapping.h:318
Definition point.h:111
static constexpr std::array< RefinementCase< dim >, n_refinement_cases > all_refinement_cases()
#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)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
#define AssertThrow(cond, exc)
UpdateFlags
@ update_hessians
Second derivatives of shape functions.
@ update_values
Shape function values.
@ update_gradients
Shape function gradients.
@ update_quadrature_points
Transformed quadrature points.
std::string dim_string(const int dim, const int spacedim)
Definition utilities.cc:547
STL namespace.