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_q_dg0.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) 2012 - 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
17
19
20#include <deal.II/fe/fe_dgq.h>
22#include <deal.II/fe/fe_q_dg0.h>
23
24#include <memory>
25#include <sstream>
26#include <vector>
27
29
30
31template <int dim, int spacedim>
32FE_Q_DG0<dim, spacedim>::FE_Q_DG0(const unsigned int degree)
33 : FE_Q_Base<dim, spacedim>(TensorProductPolynomialsConst<dim>(
34 Polynomials::generate_complete_Lagrange_basis(
35 QGaussLobatto<1>(degree + 1).get_points())),
36 FiniteElementData<dim>(get_dpo_vector(degree),
37 1,
38 degree,
39 FiniteElementData<dim>::L2),
40 get_riaf_vector(degree))
41{
42 Assert(degree > 0,
43 ExcMessage("This element can only be used for polynomial degrees "
44 "greater than zero"));
45
46 this->initialize(QGaussLobatto<1>(degree + 1).get_points());
47
48 // adjust unit support point for discontinuous node
49 Point<dim> point;
50 for (unsigned int d = 0; d < dim; ++d)
51 point[d] = 0.5;
52 this->unit_support_points.push_back(point);
54}
55
56
57
58template <int dim, int spacedim>
60 : FE_Q_Base<dim, spacedim>(
62 Polynomials::generate_complete_Lagrange_basis(points.get_points())),
63 FiniteElementData<dim>(get_dpo_vector(points.size() - 1),
64 1,
65 points.size() - 1,
66 FiniteElementData<dim>::L2),
67 get_riaf_vector(points.size() - 1))
68{
69 const int degree = points.size() - 1;
70 Assert(degree > 0,
71 ExcMessage("This element can only be used for polynomial degrees "
72 "at least zero"));
73
74 this->initialize(points.get_points());
75
76 // adjust unit support point for discontinuous node
77 Point<dim> point;
78 for (unsigned int d = 0; d < dim; ++d)
79 point[d] = 0.5;
80 this->unit_support_points.push_back(point);
82}
83
84
85
86template <int dim, int spacedim>
87std::string
89{
90 // note that the FETools::get_fe_by_name function depends on the
91 // particular format of the string this function returns, so they have to be
92 // kept in synch
93
94 std::ostringstream namebuf;
95 bool type = true;
96 const unsigned int n_points = this->degree + 1;
97 std::vector<double> points(n_points);
98 const unsigned int dofs_per_cell = this->n_dofs_per_cell();
99 const std::vector<Point<dim>> &unit_support_points =
100 this->unit_support_points;
101 unsigned int index = 0;
102
103 // Decode the support points in one coordinate direction.
104 for (unsigned int j = 0; j < dofs_per_cell; ++j)
105 {
106 if ((dim > 1) ? (unit_support_points[j][1] == 0 &&
107 ((dim > 2) ? unit_support_points[j][2] == 0 : true)) :
108 true)
109 {
110 if (index == 0)
111 points[index] = unit_support_points[j][0];
112 else if (index == 1)
113 points[n_points - 1] = unit_support_points[j][0];
114 else
115 points[index - 1] = unit_support_points[j][0];
116
117 ++index;
118 }
119 }
120 // Do not consider the discontinuous node for dimension 1
121 Assert(index == n_points || (dim == 1 && index == n_points + 1),
123 "Could not decode support points in one coordinate direction."));
124
125 // Check whether the support points are equidistant.
126 for (unsigned int j = 0; j < n_points; ++j)
127 if (std::fabs(points[j] - static_cast<double>(j) / this->degree) > 1e-15)
128 {
129 type = false;
130 break;
131 }
132
133 if (type == true)
134 {
135 if (this->degree > 2)
136 namebuf << "FE_Q_DG0<" << Utilities::dim_string(dim, spacedim)
137 << ">(QIterated(QTrapezoid()," << this->degree << "))";
138 else
139 namebuf << "FE_Q_DG0<" << Utilities::dim_string(dim, spacedim) << ">("
140 << this->degree << ")";
141 }
142 else
143 {
144 // Check whether the support points come from QGaussLobatto.
145 const QGaussLobatto<1> points_gl(n_points);
146 type = true;
147 for (unsigned int j = 0; j < n_points; ++j)
148 if (points[j] != points_gl.point(j)[0])
149 {
150 type = false;
151 break;
152 }
153 if (type == true)
154 namebuf << "FE_Q_DG0<" << Utilities::dim_string(dim, spacedim) << ">("
155 << this->degree << ")";
156 else
157 namebuf << "FE_Q_DG0<" << Utilities::dim_string(dim, spacedim)
158 << ">(QUnknownNodes(" << this->degree << "))";
159 }
160 return namebuf.str();
161}
162
163
164
165template <int dim, int spacedim>
166std::unique_ptr<FiniteElement<dim, spacedim>>
168{
169 return std::make_unique<FE_Q_DG0<dim, spacedim>>(*this);
170}
171
172
173
174template <int dim, int spacedim>
175void
177 const std::vector<Vector<double>> &support_point_values,
178 std::vector<double> &nodal_dofs) const
179{
180 Assert(support_point_values.size() == this->unit_support_points.size(),
181 ExcDimensionMismatch(support_point_values.size(),
182 this->unit_support_points.size()));
183 Assert(nodal_dofs.size() == this->n_dofs_per_cell(),
184 ExcDimensionMismatch(nodal_dofs.size(), this->n_dofs_per_cell()));
185 Assert(support_point_values[0].size() == this->n_components(),
186 ExcDimensionMismatch(support_point_values[0].size(),
187 this->n_components()));
188
189 for (unsigned int i = 0; i < this->n_dofs_per_cell() - 1; ++i)
190 {
191 const std::pair<unsigned int, unsigned int> index =
192 this->system_to_component_index(i);
193 nodal_dofs[i] = support_point_values[i](index.first);
194 }
195
196 // We don't need the discontinuous function for local interpolation
197 nodal_dofs.back() = 0.;
198}
199
200
201
202template <int dim, int spacedim>
203void
205 const FiniteElement<dim, spacedim> &x_source_fe,
206 FullMatrix<double> &interpolation_matrix) const
207{
208 // this is only implemented, if the source FE is also a Q_DG0 element
209 using FEQDG0 = FE_Q_DG0<dim, spacedim>;
210
212 (x_source_fe.get_name().find("FE_Q_DG0<") == 0) ||
213 (dynamic_cast<const FEQDG0 *>(&x_source_fe) != nullptr),
215
216 Assert(interpolation_matrix.m() == this->n_dofs_per_cell(),
217 ExcDimensionMismatch(interpolation_matrix.m(),
218 this->n_dofs_per_cell()));
219 Assert(interpolation_matrix.n() == x_source_fe.n_dofs_per_cell(),
220 ExcDimensionMismatch(interpolation_matrix.m(),
221 x_source_fe.n_dofs_per_cell()));
222
224 x_source_fe, interpolation_matrix);
225}
226
227
228
229template <int dim, int spacedim>
230std::vector<bool>
232{
233 std::vector<bool> riaf(Utilities::fixed_power<dim>(deg + 1) + 1, false);
234 riaf.back() = true;
235 return riaf;
236}
237
238
239
240template <int dim, int spacedim>
241std::vector<unsigned int>
243{
244 std::vector<unsigned int> dpo(dim + 1, 1U);
245 for (unsigned int i = 1; i < dpo.size(); ++i)
246 dpo[i] = dpo[i - 1] * (deg - 1);
247
248 dpo[dim]++; // we need an additional DG0-node for a dim-dimensional object
249 return dpo;
250}
251
252
253
254template <int dim, int spacedim>
255bool
257 const unsigned int shape_index,
258 const unsigned int face_index) const
259{
260 // discontinuous function has support on all faces
261 if (shape_index == this->n_dofs_per_cell() - 1)
262 return true;
263 else
265 face_index);
266}
267
268
269
270template <int dim, int spacedim>
271std::pair<Table<2, bool>, std::vector<unsigned int>>
273{
274 Table<2, bool> constant_modes(2, this->n_dofs_per_cell());
275
276 // 1 represented by FE_Q part
277 for (unsigned int i = 0; i < this->n_dofs_per_cell() - 1; ++i)
278 constant_modes(0, i) = true;
279
280 // 1 represented by DG0 part
281 constant_modes(1, this->n_dofs_per_cell() - 1) = true;
282
283 return std::pair<Table<2, bool>, std::vector<unsigned int>>(
284 constant_modes, std::vector<unsigned int>(2, 0));
285}
286
287
288
289template <int dim, int spacedim>
292 const FiniteElement<dim, spacedim> &fe_other,
293 const unsigned int codim) const
294{
295 Assert(codim <= dim, ExcImpossibleInDim(dim));
296
297 // vertex/line/face domination
298 // (if fe_other is derived from FE_DGQ)
299 // ------------------------------------
300 if (codim > 0)
301 if (dynamic_cast<const FE_DGQ<dim, spacedim> *>(&fe_other) != nullptr)
302 // there are no requirements between continuous and discontinuous elements
304
305 // vertex/line/face domination
306 // (if fe_other is not derived from FE_DGQ)
307 // & cell domination
308 // ----------------------------------------
309 if (const FE_Q_DG0<dim, spacedim> *fe_dg0_other =
310 dynamic_cast<const FE_Q_DG0<dim, spacedim> *>(&fe_other))
311 {
312 if (this->degree < fe_dg0_other->degree)
314 else if (this->degree == fe_dg0_other->degree)
316 else
318 }
319 else if (const FE_Nothing<dim> *fe_nothing =
320 dynamic_cast<const FE_Nothing<dim> *>(&fe_other))
321 {
322 if (fe_nothing->is_dominating())
324 else
325 // the FE_Nothing has no degrees of freedom and it is typically used
326 // in a context where we don't require any continuity along the
327 // interface
329 }
330
333}
334
335
336// explicit instantiations
337#include "fe/fe_q_dg0.inst"
338
virtual void get_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix) const override
void initialize(const std::vector< Point< 1 > > &support_points_1d)
virtual bool has_support_on_face(const unsigned int shape_index, const unsigned int face_index) const override
virtual void get_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix) const override
Definition fe_q_dg0.cc:204
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const override
Definition fe_q_dg0.cc:167
virtual std::pair< Table< 2, bool >, std::vector< unsigned int > > get_constant_modes() const override
Definition fe_q_dg0.cc:272
FE_Q_DG0(const unsigned int p)
Definition fe_q_dg0.cc:32
virtual std::string get_name() const override
Definition fe_q_dg0.cc:88
static std::vector< bool > get_riaf_vector(const unsigned int degree)
Definition fe_q_dg0.cc:231
virtual bool has_support_on_face(const unsigned int shape_index, const unsigned int face_index) const override
Definition fe_q_dg0.cc:256
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
Definition fe_q_dg0.cc:176
virtual FiniteElementDomination::Domination compare_for_domination(const FiniteElement< dim, spacedim > &fe_other, const unsigned int codim=0) const override final
Definition fe_q_dg0.cc:291
static std::vector< unsigned int > get_dpo_vector(const unsigned int degree)
Definition fe_q_dg0.cc:242
const unsigned int degree
Definition fe_data.h:450
unsigned int n_dofs_per_cell() const
virtual std::string get_name() const =0
std::vector< Point< dim > > unit_support_points
Definition fe.h:2585
size_type n() const
size_type m() const
Definition point.h:111
const std::vector< Point< dim > > & get_points() const
unsigned int size() const
#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 & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::size_t size
Definition mpi.cc:733
std::string dim_string(const int dim, const int spacedim)
Definition utilities.cc:547