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_monomial.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
17#include <deal.II/fe/fe_tools.h>
18
19#include <memory>
20#include <sstream>
21
22
24
25namespace internal
26{
28 {
29 namespace
30 {
31 // storage of hand-chosen support
32 // points
33 //
34 // For dim=2, dofs_per_cell of
35 // FE_DGPMonomial(k) is given by
36 // 0.5(k+1)(k+2), i.e.
37 //
38 // k 0 1 2 3 4 5 6 7
39 // dofs 1 3 6 10 15 21 28 36
40 //
41 // indirect access of unit points:
42 // the points for degree k are
43 // located at
44 //
45 // points[start_index[k]..start_index[k+1]-1]
46 const unsigned int start_index2d[6] = {0, 1, 4, 10, 20, 35};
47 const double points2d[35][2] = {
48 {0, 0}, {0, 0}, {1, 0}, {0, 1}, {0, 0},
49 {1, 0}, {0, 1}, {1, 1}, {0.5, 0}, {0, 0.5},
50 {0, 0}, {1, 0}, {0, 1}, {1, 1}, {1. / 3., 0},
51 {2. / 3., 0}, {0, 1. / 3.}, {0, 2. / 3.}, {0.5, 1}, {1, 0.5},
52 {0, 0}, {1, 0}, {0, 1}, {1, 1}, {0.25, 0},
53 {0.5, 0}, {0.75, 0}, {0, 0.25}, {0, 0.5}, {0, 0.75},
54 {1. / 3., 1}, {2. / 3., 1}, {1, 1. / 3.}, {1, 2. / 3.}, {0.5, 0.5}};
55
56 // For dim=3, dofs_per_cell of
57 // FE_DGPMonomial(k) is given by
58 // 1./6.(k+1)(k+2)(k+3), i.e.
59 //
60 // k 0 1 2 3 4 5 6 7
61 // dofs 1 4 10 20 35 56 84 120
62 const unsigned int start_index3d[6] = {0, 1, 5, 15 /*,35*/};
63 const double points3d[35][3] = {{0, 0, 0},
64 {0, 0, 0},
65 {1, 0, 0},
66 {0, 1, 0},
67 {0, 0, 1},
68 {0, 0, 0},
69 {1, 0, 0},
70 {0, 1, 0},
71 {0, 0, 1},
72 {0.5, 0, 0},
73 {0, 0.5, 0},
74 {0, 0, 0.5},
75 {1, 1, 0},
76 {1, 0, 1},
77 {0, 1, 1}};
78
79
80 template <int dim>
81 void
82 generate_unit_points(const unsigned int, std::vector<Point<dim>> &);
83
84 template <>
85 void
86 generate_unit_points(const unsigned int k, std::vector<Point<1>> &p)
87 {
88 Assert(p.size() == k + 1, ExcDimensionMismatch(p.size(), k + 1));
89 const double h = 1. / k;
90 for (unsigned int i = 0; i < p.size(); ++i)
91 p[i][0] = i * h;
92 }
93
94 template <>
95 void
96 generate_unit_points(const unsigned int k, std::vector<Point<2>> &p)
97 {
98 Assert(k <= 4, ExcNotImplemented());
99 Assert(p.size() == start_index2d[k + 1] - start_index2d[k],
101 for (unsigned int i = 0; i < p.size(); ++i)
102 {
103 p[i][0] = points2d[start_index2d[k] + i][0];
104 p[i][1] = points2d[start_index2d[k] + i][1];
105 }
106 }
107
108 template <>
109 void
110 generate_unit_points(const unsigned int k, std::vector<Point<3>> &p)
111 {
112 Assert(k <= 2, ExcNotImplemented());
113 Assert(p.size() == start_index3d[k + 1] - start_index3d[k],
115 for (unsigned int i = 0; i < p.size(); ++i)
116 {
117 p[i][0] = points3d[start_index3d[k] + i][0];
118 p[i][1] = points3d[start_index3d[k] + i][1];
119 p[i][2] = points3d[start_index3d[k] + i][2];
120 }
121 }
122 } // namespace
123 } // namespace FE_DGPMonomial
124} // namespace internal
125
126
127
128template <int dim>
129FE_DGPMonomial<dim>::FE_DGPMonomial(const unsigned int degree)
130 : FE_Poly<dim>(PolynomialsP<dim>(degree),
131 FiniteElementData<dim>(get_dpo_vector(degree),
132 1,
133 degree,
134 FiniteElementData<dim>::L2),
135 std::vector<bool>(
136 FiniteElementData<dim>(get_dpo_vector(degree), 1, degree)
137 .n_dofs_per_cell(),
138 true),
139 std::vector<ComponentMask>(
140 FiniteElementData<dim>(get_dpo_vector(degree), 1, degree)
141 .n_dofs_per_cell(),
142 ComponentMask(std::vector<bool>(1, true))))
143{
144 Assert(this->poly_space->n() == this->n_dofs_per_cell(), ExcInternalError());
145 Assert(this->poly_space->degree() == this->degree, ExcInternalError());
146
147 // DG doesn't have constraints, so
148 // leave them empty
149
150 // Reinit the vectors of
151 // restriction and prolongation
152 // matrices to the right sizes
154 // Fill prolongation matrices with embedding operators
156 // Fill restriction matrices with L2-projection
158}
159
160
161
162template <int dim>
163std::string
165{
166 // note that the
167 // FETools::get_fe_by_name
168 // function depends on the
169 // particular format of the string
170 // this function returns, so they
171 // have to be kept in synch
172
173 std::ostringstream namebuf;
174 namebuf << "FE_DGPMonomial<" << dim << ">(" << this->degree << ")";
175
176 return namebuf.str();
177}
178
179
180
181template <int dim>
182std::unique_ptr<FiniteElement<dim, dim>>
184{
185 return std::make_unique<FE_DGPMonomial<dim>>(*this);
186}
187
188
189
190// TODO: Remove this function and use the one in FETools, if needed
191template <int dim>
192void
194 const FiniteElement<dim> &source_fe,
195 FullMatrix<double> &interpolation_matrix) const
196{
197 const FE_DGPMonomial<dim> *source_dgp_monomial =
198 dynamic_cast<const FE_DGPMonomial<dim> *>(&source_fe);
199
200 if (source_dgp_monomial)
201 {
202 // ok, source_fe is a DGP_Monomial
203 // element. Then, the interpolation
204 // matrix is simple
205 const unsigned int m = interpolation_matrix.m();
206 const unsigned int n = interpolation_matrix.n();
207 (void)m;
208 (void)n;
209 Assert(m == this->n_dofs_per_cell(),
210 ExcDimensionMismatch(m, this->n_dofs_per_cell()));
211 Assert(n == source_dgp_monomial->n_dofs_per_cell(),
212 ExcDimensionMismatch(n, source_dgp_monomial->n_dofs_per_cell()));
213
214 const unsigned int min_mn =
215 interpolation_matrix.m() < interpolation_matrix.n() ?
216 interpolation_matrix.m() :
217 interpolation_matrix.n();
218
219 for (unsigned int i = 0; i < min_mn; ++i)
220 interpolation_matrix(i, i) = 1.;
221 }
222 else
223 {
224 std::vector<Point<dim>> unit_points(this->n_dofs_per_cell());
225 internal::FE_DGPMonomial::generate_unit_points(this->degree, unit_points);
226
227 FullMatrix<double> source_fe_matrix(unit_points.size(),
228 source_fe.n_dofs_per_cell());
229 for (unsigned int j = 0; j < source_fe.n_dofs_per_cell(); ++j)
230 for (unsigned int k = 0; k < unit_points.size(); ++k)
231 source_fe_matrix(k, j) = source_fe.shape_value(j, unit_points[k]);
232
233 FullMatrix<double> this_matrix(this->n_dofs_per_cell(),
234 this->n_dofs_per_cell());
235 for (unsigned int j = 0; j < this->n_dofs_per_cell(); ++j)
236 for (unsigned int k = 0; k < unit_points.size(); ++k)
237 this_matrix(k, j) =
238 this->poly_space->compute_value(j, unit_points[k]);
239
240 this_matrix.gauss_jordan();
241
242 this_matrix.mmult(interpolation_matrix, source_fe_matrix);
243 }
244}
245
246
247
248template <int dim>
249void
254
255
256//---------------------------------------------------------------------------
257// Auxiliary functions
258//---------------------------------------------------------------------------
259
260
261template <int dim>
262std::vector<unsigned int>
264{
265 std::vector<unsigned int> dpo(dim + 1, 0U);
266 dpo[dim] = deg + 1;
267 for (unsigned int i = 1; i < dim; ++i)
268 {
269 dpo[dim] *= deg + 1 + i;
270 dpo[dim] /= i + 1;
271 }
272 return dpo;
273}
274
275
276template <int dim>
277void
279 const FiniteElement<dim> &x_source_fe,
280 FullMatrix<double> &interpolation_matrix,
281 const unsigned int) const
282{
283 // this is only implemented, if the source
284 // FE is also a DGPMonomial element. in that case,
285 // both elements have no dofs on their
286 // faces and the face interpolation matrix
287 // is necessarily empty -- i.e. there isn't
288 // much we need to do here.
289 (void)interpolation_matrix;
290 AssertThrow((x_source_fe.get_name().find("FE_DGPMonomial<") == 0) ||
291 (dynamic_cast<const FE_DGPMonomial<dim> *>(&x_source_fe) !=
292 nullptr),
294
295 Assert(interpolation_matrix.m() == 0,
296 ExcDimensionMismatch(interpolation_matrix.m(), 0));
297 Assert(interpolation_matrix.n() == 0,
298 ExcDimensionMismatch(interpolation_matrix.n(), 0));
299}
300
301
302
303template <int dim>
304void
306 const FiniteElement<dim> &x_source_fe,
307 const unsigned int,
308 FullMatrix<double> &interpolation_matrix,
309 const unsigned int) const
310{
311 // this is only implemented, if the source
312 // FE is also a DGPMonomial element. in that case,
313 // both elements have no dofs on their
314 // faces and the face interpolation matrix
315 // is necessarily empty -- i.e. there isn't
316 // much we need to do here.
317 (void)interpolation_matrix;
318 AssertThrow((x_source_fe.get_name().find("FE_DGPMonomial<") == 0) ||
319 (dynamic_cast<const FE_DGPMonomial<dim> *>(&x_source_fe) !=
320 nullptr),
322
323 Assert(interpolation_matrix.m() == 0,
324 ExcDimensionMismatch(interpolation_matrix.m(), 0));
325 Assert(interpolation_matrix.n() == 0,
326 ExcDimensionMismatch(interpolation_matrix.n(), 0));
327}
328
329
330
331template <int dim>
332bool
337
338
339
340template <int dim>
341std::vector<std::pair<unsigned int, unsigned int>>
343 const FiniteElement<dim> &fe_other) const
344{
345 // there are no such constraints for DGPMonomial
346 // elements at all
347 if (dynamic_cast<const FE_DGPMonomial<dim> *>(&fe_other) != nullptr)
348 return std::vector<std::pair<unsigned int, unsigned int>>();
349 else
350 {
352 return std::vector<std::pair<unsigned int, unsigned int>>();
353 }
354}
355
356
357
358template <int dim>
359std::vector<std::pair<unsigned int, unsigned int>>
361 const FiniteElement<dim> &fe_other) const
362{
363 // there are no such constraints for DGPMonomial
364 // elements at all
365 if (dynamic_cast<const FE_DGPMonomial<dim> *>(&fe_other) != nullptr)
366 return std::vector<std::pair<unsigned int, unsigned int>>();
367 else
368 {
370 return std::vector<std::pair<unsigned int, unsigned int>>();
371 }
372}
373
374
375
376template <int dim>
377std::vector<std::pair<unsigned int, unsigned int>>
379 const unsigned int) const
380{
381 // there are no such constraints for DGPMonomial
382 // elements at all
383 if (dynamic_cast<const FE_DGPMonomial<dim> *>(&fe_other) != nullptr)
384 return std::vector<std::pair<unsigned int, unsigned int>>();
385 else
386 {
388 return std::vector<std::pair<unsigned int, unsigned int>>();
389 }
390}
391
392
393
394template <int dim>
397 const unsigned int codim) const
398{
399 Assert(codim <= dim, ExcImpossibleInDim(dim));
400
401 // vertex/line/face domination
402 // ---------------------------
403 if (codim > 0)
404 // this is a discontinuous element, so by definition there will
405 // be no constraints wherever this element comes together with
406 // any other kind of element
408
409 // cell domination
410 // ---------------
411 if (const FE_DGPMonomial<dim> *fe_monomial_other =
412 dynamic_cast<const FE_DGPMonomial<dim> *>(&fe_other))
413 {
414 if (this->degree < fe_monomial_other->degree)
416 else if (this->degree == fe_monomial_other->degree)
418 else
420 }
421 else if (const FE_Nothing<dim> *fe_nothing =
422 dynamic_cast<const FE_Nothing<dim> *>(&fe_other))
423 {
424 if (fe_nothing->is_dominating())
426 else
427 // the FE_Nothing has no degrees of freedom and it is typically used
428 // in a context where we don't require any continuity along the
429 // interface
431 }
432
435}
436
437
438
439template <>
440bool
442 const unsigned int face_index) const
443{
444 return face_index == 1 || (face_index == 0 && this->degree == 0);
445}
446
447
448
449template <>
450bool
451FE_DGPMonomial<2>::has_support_on_face(const unsigned int shape_index,
452 const unsigned int face_index) const
453{
454 bool support_on_face = false;
455 if (face_index == 1 || face_index == 2)
456 support_on_face = true;
457 else
458 {
459 auto *const polynomial_space_p =
460 dynamic_cast<PolynomialsP<2> *>(this->poly_space.get());
461 Assert(polynomial_space_p != nullptr, ExcInternalError());
462 const std::array<unsigned int, 2> degrees =
463 polynomial_space_p->directional_degrees(shape_index);
464
465 if ((face_index == 0 && degrees[1] == 0) ||
466 (face_index == 3 && degrees[0] == 0))
467 support_on_face = true;
468 }
469 return support_on_face;
470}
471
472
473
474template <>
475bool
476FE_DGPMonomial<3>::has_support_on_face(const unsigned int shape_index,
477 const unsigned int face_index) const
478{
479 bool support_on_face = false;
480 if (face_index == 1 || face_index == 3 || face_index == 4)
481 support_on_face = true;
482 else
483 {
484 auto *const polynomial_space_p =
485 dynamic_cast<PolynomialsP<3> *>(this->poly_space.get());
486 Assert(polynomial_space_p != nullptr, ExcInternalError());
487 const std::array<unsigned int, 3> degrees =
488 polynomial_space_p->directional_degrees(shape_index);
489
490 if ((face_index == 0 && degrees[1] == 0) ||
491 (face_index == 2 && degrees[2] == 0) ||
492 (face_index == 5 && degrees[0] == 0))
493 support_on_face = true;
494 }
495 return support_on_face;
496}
497
498
499
500template <int dim>
501std::size_t
507
508
509
510// explicit instantiations
511#include "fe/fe_dgp_monomial.inst"
512
513
virtual std::unique_ptr< FiniteElement< dim, dim > > clone() const override
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_line_dof_identities(const FiniteElement< dim > &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_quad_dof_identities(const FiniteElement< dim > &fe_other, const unsigned int face_no=0) const override
FE_DGPMonomial(const unsigned int p)
virtual void get_subface_interpolation_matrix(const FiniteElement< dim > &source, const unsigned int subface, FullMatrix< double > &matrix, const unsigned int face_no=0) const override
virtual void get_interpolation_matrix(const FiniteElement< dim > &source, FullMatrix< double > &matrix) const override
virtual void get_face_interpolation_matrix(const FiniteElement< dim > &source, FullMatrix< double > &matrix, const unsigned int face_no=0) const override
virtual std::size_t memory_consumption() const override
virtual FiniteElementDomination::Domination compare_for_domination(const FiniteElement< dim > &fe_other, const unsigned int codim=0) const override final
virtual bool hp_constraints_are_implemented() const override
virtual std::string get_name() const override
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_vertex_dof_identities(const FiniteElement< dim > &fe_other) const override
void initialize_restriction()
virtual bool has_support_on_face(const unsigned int shape_index, const unsigned int face_index) const override
const std::unique_ptr< ScalarPolynomialsBase< dim > > poly_space
Definition fe_poly.h:530
unsigned int n_dofs_per_cell() const
virtual std::string get_name() const =0
std::vector< std::vector< FullMatrix< double > > > restriction
Definition fe.h:2547
void reinit_restriction_and_prolongation_matrices(const bool isotropic_restriction_only=false, const bool isotropic_prolongation_only=false)
virtual double shape_value(const unsigned int i, const Point< dim > &p) const
std::vector< std::vector< FullMatrix< double > > > prolongation
Definition fe.h:2561
void mmult(FullMatrix< number2 > &C, const FullMatrix< number2 > &B, const bool adding=false) const
size_type n() const
void gauss_jordan()
size_type m() const
Definition point.h:111
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
#define AssertThrow(cond, exc)
void compute_embedding_matrices(const FiniteElement< dim, spacedim > &fe, std::vector< std::vector< FullMatrix< number > > > &matrices, const bool isotropic_only=false, const double threshold=1.e-12)
void compute_projection_matrices(const FiniteElement< dim, spacedim > &fe, std::vector< std::vector< FullMatrix< number > > > &matrices, const bool isotropic_only=false)
STL namespace.