deal.II version GIT relicensing-6842-g793a97d2aa 2026-10-02 14:00: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_rt_bubbles.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) 2018 - 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
16
18
19#include <deal.II/fe/fe.h>
21#include <deal.II/fe/fe_tools.h>
23#include <deal.II/fe/mapping.h>
24
25#include <deal.II/grid/tria.h>
27
28#include <memory>
29#include <sstream>
30
31
33
34// TODO: implement the adjust_quad_dof_index_for_face_orientation_table and
35// adjust_line_dof_index_for_line_orientation_table fields, and write tests
36// similar to bits/face_orientation_and_fe_q_*
37
38template <int dim>
39FE_RT_Bubbles<dim>::FE_RT_Bubbles(const unsigned int deg)
40 : FE_PolyTensor<dim>(
41 PolynomialsRT_Bubbles<dim>(deg),
42 FiniteElementData<dim>(get_dpo_vector(deg),
43 dim,
44 deg + 1,
45 FiniteElementData<dim>::Hdiv),
46 get_ria_vector(deg),
47 std::vector<ComponentMask>(PolynomialsRT_Bubbles<dim>::n_polynomials(deg),
48 ComponentMask(std::vector<bool>(dim, true))))
49{
50 Assert(dim >= 2, ExcImpossibleInDim(dim));
51 Assert(
52 deg >= 1,
54 "Lowest order RT_Bubbles element is degree 1, but you requested for degree 0"));
55 const unsigned int n_dofs = this->n_dofs_per_cell();
56
58 // Initialize support points and quadrature weights
60 // Compute the inverse node matrix to get
61 // the correct basis functions
63 this->inverse_node_matrix.reinit(n_dofs, n_dofs);
65
66 // Reinit the vectors of prolongation matrices to the
67 // right sizes. There are no restriction matrices implemented
68 for (const unsigned int ref_case :
71 {
72 const unsigned int nc =
73 this->reference_cell().n_children(RefinementCase<dim>(ref_case));
74
75 for (unsigned int i = 0; i < nc; ++i)
76 this->prolongation[ref_case - 1][i].reinit(n_dofs, n_dofs);
77 }
78
79 // TODO: the implementation makes the assumption that all faces have the
80 // same number of dofs
82 const unsigned int face_no = 0;
83
84 // Fill prolongation matrices with embedding operators
85 // set tolerance to 1, as embedding error accumulate quickly
88 for (unsigned int i = 0; i < GeometryInfo<dim>::max_children_per_face; ++i)
89 face_embeddings[i].reinit(this->n_dofs_per_face(face_no),
90 this->n_dofs_per_face(face_no));
91 FETools::compute_face_embedding_matrices<dim, double>(*this,
92 face_embeddings,
93 0,
94 0);
95 this->interface_constraints.reinit((1 << (dim - 1)) *
96 this->n_dofs_per_face(face_no),
97 this->n_dofs_per_face(face_no));
98 unsigned int target_row = 0;
99 for (unsigned int d = 0; d < GeometryInfo<dim>::max_children_per_face; ++d)
100 for (unsigned int i = 0; i < face_embeddings[d].m(); ++i)
101 {
102 for (unsigned int j = 0; j < face_embeddings[d].n(); ++j)
103 this->interface_constraints(target_row, j) = face_embeddings[d](i, j);
104 ++target_row;
105 }
106
107 // We need to initialize the dof permutation table and the one for the sign
108 // change.
110}
111
112
113template <int dim>
114void
116{
117 // for 1d and 2d, do nothing
118 if (dim < 3)
119 return;
120
121 // TODO: Implement this for this class
122 return;
123}
124
125
126
127template <int dim>
128std::string
130{
131 // Note: this->degree is the maximal polynomial degree and is thus one higher
132 // than the argument given to the constructor
133 std::ostringstream namebuf;
134 namebuf << "FE_RT_Bubbles<" << dim << ">(" << this->degree << ")";
135
136 return namebuf.str();
137}
138
139
140
141template <int dim>
142std::unique_ptr<FiniteElement<dim, dim>>
144{
145 return std::make_unique<FE_RT_Bubbles<dim>>(*this);
146}
147
148
149//---------------------------------------------------------------------------
150// Auxiliary and internal functions
151//---------------------------------------------------------------------------
152
153
154
155template <int dim>
156void
158{
159 // TODO: the implementation makes the assumption that all faces have the
160 // same number of dofs
161 AssertDimension(this->n_unique_faces(), 1);
162 const unsigned int face_no = 0;
163
164 this->generalized_support_points.resize(this->n_dofs_per_cell());
165 this->generalized_face_support_points[face_no].resize(
166 this->n_dofs_per_face(face_no));
167
168 // Index of the point being entered
169 unsigned int current = 0;
170
171 // On the faces, we choose as many Gauss-Lobatto points
172 // as required to determine the normal component uniquely.
173 // This is the deg of the RT_Bubble element plus one.
174 if (dim > 1)
175 {
176 const QGaussLobatto<dim - 1> face_points(deg + 1);
177 Assert(face_points.size() == this->n_dofs_per_face(face_no),
179 for (unsigned int k = 0; k < this->n_dofs_per_face(face_no); ++k)
180 this->generalized_face_support_points[face_no][k] =
181 face_points.point(k);
182 Quadrature<dim> faces =
183 QProjector<dim>::project_to_all_faces(this->reference_cell(),
184 face_points);
185 for (unsigned int face_no = 0;
186 face_no < GeometryInfo<dim>::faces_per_cell;
187 ++face_no)
188 {
190 this->reference_cell(),
191 face_no,
193 face_points.size());
194 for (unsigned int face_point = 0; face_point < face_points.size();
195 ++face_point)
196 {
197 // Enter the support point into the vector
198 this->generalized_support_points[current] =
199 faces.point(offset + face_point);
200 ++current;
201 }
202 }
203 }
204
205 if (deg == 1)
206 return;
207
208 // In the interior, we need anisotropic Gauss-Lobatto quadratures,
209 // one for each direction
210 const QGaussLobatto<1> high(deg + 1);
211 std::vector<Point<1>> pts = high.get_points();
212 if (pts.size() > 2)
213 {
214 pts.erase(pts.begin());
215 pts.erase(pts.end() - 1);
216 }
217
218 std::vector<double> wts(pts.size(), 1);
219 const Quadrature<1> low(pts, wts);
220
221 for (unsigned int d = 0; d < dim; ++d)
222 {
223 std::unique_ptr<QAnisotropic<dim>> quadrature;
224 switch (dim)
225 {
226 case 1:
227 quadrature = std::make_unique<QAnisotropic<dim>>(high);
228 break;
229 case 2:
230 quadrature =
231 std::make_unique<QAnisotropic<dim>>(((d == 0) ? low : high),
232 ((d == 1) ? low : high));
233 break;
234 case 3:
235 quadrature =
236 std::make_unique<QAnisotropic<dim>>(((d == 0) ? low : high),
237 ((d == 1) ? low : high),
238 ((d == 2) ? low : high));
239 break;
240 default:
242 }
243
244 for (unsigned int k = 0; k < quadrature->size(); ++k)
245 this->generalized_support_points[current++] = quadrature->point(k);
246 }
247 Assert(current == this->n_dofs_per_cell(), ExcInternalError());
248}
249
250
251
252template <int dim>
253std::vector<unsigned int>
255{
256 // We have (deg+1)^(dim-1) DoFs per face...
257 unsigned int dofs_per_face = 1;
258 for (unsigned int d = 1; d < dim; ++d)
259 dofs_per_face *= deg + 1;
260
261 // ...plus the interior DoFs for the total of dim*(deg+1)^dim
262 const unsigned int interior_dofs =
263 dim * (deg - 1) * Utilities::pow(deg + 1, dim - 1);
264
265 std::vector<unsigned int> dpo(dim + 1);
266 dpo[dim - 1] = dofs_per_face;
267 dpo[dim] = interior_dofs;
268
269 return dpo;
270}
271
272
273
274template <>
275std::vector<bool>
277{
278 Assert(false, ExcImpossibleInDim(1));
279 return std::vector<bool>();
280}
281
282
283
284template <int dim>
285std::vector<bool>
287{
288 const unsigned int dofs_per_cell =
290 unsigned int dofs_per_face = deg + 1;
291 for (unsigned int d = 2; d < dim; ++d)
292 dofs_per_face *= deg + 1;
293 // All face dofs need to be non-additive, since they have
294 // continuity requirements. The interior dofs are
295 // made additive.
296 std::vector<bool> ret_val(dofs_per_cell, false);
297 for (unsigned int i = GeometryInfo<dim>::faces_per_cell * dofs_per_face;
298 i < dofs_per_cell;
299 ++i)
300 ret_val[i] = true;
301
302 return ret_val;
303}
304
305
306
307template <int dim>
308void
310 const std::vector<Vector<double>> &support_point_values,
311 std::vector<double> &nodal_values) const
312{
313 Assert(support_point_values.size() == this->generalized_support_points.size(),
314 ExcDimensionMismatch(support_point_values.size(),
315 this->generalized_support_points.size()));
316 Assert(nodal_values.size() == this->n_dofs_per_cell(),
317 ExcDimensionMismatch(nodal_values.size(), this->n_dofs_per_cell()));
318 Assert(support_point_values[0].size() == this->n_components(),
319 ExcDimensionMismatch(support_point_values[0].size(),
320 this->n_components()));
321
322 // First do interpolation on faces. There, the component
323 // evaluated depends on the face direction and orientation.
324 unsigned int fbase = 0;
325 unsigned int f = 0;
326 for (; f < GeometryInfo<dim>::faces_per_cell;
327 ++f, fbase += this->n_dofs_per_face(f))
328 {
329 for (unsigned int i = 0; i < this->n_dofs_per_face(f); ++i)
330 {
331 nodal_values[fbase + i] = support_point_values[fbase + i](
333 }
334 }
335
336 // The remaining points form dim chunks, one for each component.
337 const unsigned int istep = (this->n_dofs_per_cell() - fbase) / dim;
338 Assert((this->n_dofs_per_cell() - fbase) % dim == 0, ExcInternalError());
339
340 f = 0;
341 while (fbase < this->n_dofs_per_cell())
342 {
343 for (unsigned int i = 0; i < istep; ++i)
344 {
345 nodal_values[fbase + i] = support_point_values[fbase + i](f);
346 }
347 fbase += istep;
348 ++f;
349 }
350 Assert(fbase == this->n_dofs_per_cell(), ExcInternalError());
351}
352
353
354
355// explicit instantiations
356#include "fe/fe_rt_bubbles.inst"
357
358
FullMatrix< double > inverse_node_matrix
std::vector< MappingKind > mapping_kind
FE_RT_Bubbles(const unsigned int k)
virtual std::string get_name() const override
virtual std::unique_ptr< FiniteElement< dim, dim > > clone() const override
void initialize_support_points(const unsigned int rt_degree)
virtual void convert_generalized_support_point_values_to_dof_values(const std::vector< Vector< double > > &support_point_values, std::vector< double > &nodal_values) const override
static std::vector< unsigned int > get_dpo_vector(const unsigned int degree)
static std::vector< bool > get_ria_vector(const unsigned int degree)
void initialize_quad_dof_index_permutation_and_sign_change()
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
ReferenceCell< dim > reference_cell() const
FullMatrix< double > interface_constraints
Definition fe.h:2573
std::vector< std::vector< FullMatrix< double > > > prolongation
Definition fe.h:2561
size_type n() const
void invert(const FullMatrix< number2 > &M)
size_type m() const
static unsigned int n_polynomials(const unsigned int degree)
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 Quadrature< dim > project_to_all_faces(const ReferenceCell< dim > &reference_cell, const hp::QCollection< dim - 1 > &quadrature)
const Point< dim > & point(const unsigned int i) const
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 AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
@ mapping_raviart_thomas
Definition mapping.h:134
std::size_t size
Definition mpi.cc:733
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)
FullMatrix< double > compute_node_matrix(const FiniteElement< dim, spacedim > &fe)
constexpr T pow(const T base, const int iexp)
Definition utilities.h:966
constexpr types::geometric_orientation default_geometric_orientation
Definition types.h:342
STL namespace.