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.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) 2001 - 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
15
16#include <deal.II/fe/fe_dgq.h>
20#include <deal.II/fe/fe_q.h>
24
25#include <deal.II/lac/vector.h>
26
27#include <memory>
28#include <sstream>
29#include <vector>
30
32
33
34namespace internal
35{
36 namespace FE_Q
37 {
38 namespace
39 {
40 std::vector<Point<1>>
41 get_QGaussLobatto_points(const unsigned int degree)
42 {
43 if (degree > 0)
44 return QGaussLobatto<1>(degree + 1).get_points();
45 else
46 {
47 using FEQ = ::FE_Q_Base<1, 1>;
48 AssertThrow(false, FEQ::ExcFEQCannotHaveDegree0());
49 }
50 return std::vector<Point<1>>();
51 }
52 } // namespace
53 } // namespace FE_Q
54} // namespace internal
55
56
57
58template <int dim, int spacedim>
59FE_Q<dim, spacedim>::FE_Q(const unsigned int degree)
60 : FE_Q_Base<dim, spacedim>(
62 Polynomials::generate_complete_Lagrange_basis(
63 internal::FE_Q::get_QGaussLobatto_points(degree))),
64 FiniteElementData<dim>(this->get_dpo_vector(degree),
65 1,
66 degree,
67 FiniteElementData<dim>::H1),
68 std::vector<bool>(1, false))
69{
70 this->initialize(internal::FE_Q::get_QGaussLobatto_points(degree));
71}
72
73
74
75template <int dim, int spacedim>
77 : FE_Q_Base<dim, spacedim>(
79 Polynomials::generate_complete_Lagrange_basis(points.get_points())),
80 FiniteElementData<dim>(this->get_dpo_vector(points.size() - 1),
81 1,
82 points.size() - 1,
83 FiniteElementData<dim>::H1),
84 std::vector<bool>(1, false))
85{
86 this->initialize(points.get_points());
87}
88
89
90
91template <int dim, int spacedim>
92std::string
94{
95 // note that the FETools::get_fe_by_name function depends on the
96 // particular format of the string this function returns, so they have to be
97 // kept in synch
98
99 std::ostringstream namebuf;
100 bool equidistant = true;
101 std::vector<double> points(this->degree + 1);
102
103 // Decode the support points in one coordinate direction.
104 TensorProductPolynomials<dim> *poly_space_derived_ptr =
105 dynamic_cast<TensorProductPolynomials<dim> *>(this->poly_space.get());
106 std::vector<unsigned int> lexicographic =
107 poly_space_derived_ptr->get_numbering_inverse();
108 for (unsigned int j = 0; j <= this->degree; ++j)
109 points[j] = this->unit_support_points[lexicographic[j]][0];
110
111 // Check whether the support points are equidistant.
112 for (unsigned int j = 0; j <= this->degree; ++j)
113 if (std::fabs(points[j] - static_cast<double>(j) / this->degree) > 1e-15)
114 {
115 equidistant = false;
116 break;
117 }
118
119 if (equidistant == true)
120 {
121 if (this->degree > 2)
122 namebuf << "FE_Q<" << Utilities::dim_string(dim, spacedim)
123 << ">(QIterated(QTrapezoid()," << this->degree << "))";
124 else
125 namebuf << "FE_Q<" << Utilities::dim_string(dim, spacedim) << ">("
126 << this->degree << ")";
127 }
128 else
129 {
130 // Check whether the support points come from QGaussLobatto.
131 const QGaussLobatto<1> points_gl(this->degree + 1);
132 bool gauss_lobatto = true;
133 for (unsigned int j = 0; j <= this->degree; ++j)
134 if (points[j] != points_gl.point(j)[0])
135 {
136 gauss_lobatto = false;
137 break;
138 }
139 if (gauss_lobatto == true)
140 namebuf << "FE_Q<" << Utilities::dim_string(dim, spacedim) << ">("
141 << this->degree << ")";
142 else
143 namebuf << "FE_Q<" << Utilities::dim_string(dim, spacedim)
144 << ">(QUnknownNodes(" << this->degree << "))";
145 }
146 return namebuf.str();
147}
148
149
150
151template <int dim, int spacedim>
152void
154 const std::vector<Vector<double>> &support_point_values,
155 std::vector<double> &nodal_values) const
156{
157 AssertDimension(support_point_values.size(),
158 this->get_unit_support_points().size());
159 AssertDimension(support_point_values.size(), nodal_values.size());
160 AssertDimension(this->n_dofs_per_cell(), nodal_values.size());
161
162 for (unsigned int i = 0; i < this->n_dofs_per_cell(); ++i)
163 {
164 AssertDimension(support_point_values[i].size(), 1);
165
166 nodal_values[i] = support_point_values[i](0);
167 }
168}
169
170
171
172template <int dim, int spacedim>
173std::unique_ptr<FiniteElement<dim, spacedim>>
175{
176 return std::make_unique<FE_Q<dim, spacedim>>(*this);
177}
178
179
180
181template <int dim, int spacedim>
184 const FiniteElement<dim, spacedim> &fe_other,
185 const unsigned int codim) const
186{
187 Assert(codim <= dim, ExcImpossibleInDim(dim));
188
189 // vertex/line/face domination
190 // (if fe_other is derived from FE_DGQ)
191 // ------------------------------------
192 if (codim > 0)
193 if (dynamic_cast<const FE_DGQ<dim, spacedim> *>(&fe_other) != nullptr)
194 // there are no requirements between continuous and discontinuous elements
196
197 // vertex/line/face domination
198 // (if fe_other is not derived from FE_DGQ)
199 // & cell domination
200 // ----------------------------------------
201 if (const FE_Q<dim, spacedim> *fe_q_other =
202 dynamic_cast<const FE_Q<dim, spacedim> *>(&fe_other))
203 {
204 if (this->degree < fe_q_other->degree)
206 else if (this->degree == fe_q_other->degree)
208 else
210 }
211 else if (const FE_SimplexP<dim, spacedim> *fe_p_other =
212 dynamic_cast<const FE_SimplexP<dim, spacedim> *>(&fe_other))
213 {
214 if (this->degree < fe_p_other->degree)
216 else if (this->degree == fe_p_other->degree)
218 else
220 }
221 else if (const FE_WedgeP<dim, spacedim> *fe_wp_other =
222 dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other))
223 {
224 if (this->degree < fe_wp_other->degree)
226 else if (this->degree == fe_wp_other->degree)
228 else
230 }
231 else if (const FE_PyramidP<dim, spacedim> *fe_pp_other =
232 dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other))
233 {
234 if (this->degree < fe_pp_other->degree)
236 else if (this->degree == fe_pp_other->degree)
238 else
240 }
241 else if (const FE_Nothing<dim, spacedim> *fe_nothing =
242 dynamic_cast<const FE_Nothing<dim, spacedim> *>(&fe_other))
243 {
244 if (fe_nothing->is_dominating())
246 else
247 // the FE_Nothing has no degrees of freedom and it is typically used
248 // in a context where we don't require any continuity along the
249 // interface
251 }
252 else if (const FE_Hermite<dim, spacedim> *fe_hermite_other =
253 dynamic_cast<const FE_Hermite<dim, spacedim> *>(&fe_other))
254 {
255 if (this->degree == 1)
256 {
257 if (fe_hermite_other->degree > 1)
259 else
261 }
262 else if (this->degree >= fe_hermite_other->degree)
264 else
266 }
267
270}
271
272
273// explicit instantiations
274#include "fe/fe_q.inst"
275
void initialize(const std::vector< Point< 1 > > &support_points_1d)
Definition fe_q.h:552
FE_Q(const unsigned int p)
Definition fe_q.cc:59
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.cc:153
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const override
Definition fe_q.cc:174
virtual FiniteElementDomination::Domination compare_for_domination(const FiniteElement< dim, spacedim > &fe_other, const unsigned int codim=0) const override final
Definition fe_q.cc:183
virtual std::string get_name() const override
Definition fe_q.cc:93
const unsigned int degree
Definition fe_data.h:450
const std::vector< Point< dim > > & get_points() const
const std::vector< unsigned int > & get_numbering_inverse() 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)
#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
STL namespace.