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_iso_q1.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) 2013 - 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
16
17#include <deal.II/fe/fe_dgq.h>
20#include <deal.II/fe/fe_tools.h>
21
22#include <deal.II/lac/vector.h>
23
24#include <memory>
25#include <sstream>
26#include <vector>
27
29
30
31namespace internal
32{
33 template <int dim>
35 make_local_sparsity_pattern(unsigned int n_points_1d)
36 {
37 const unsigned int n_per_cell = Utilities::pow(n_points_1d, dim);
38
39 const std::vector<unsigned int> R =
40 FETools::lexicographic_to_hierarchic_numbering<dim>(n_points_1d - 1);
41
42 Table<2, bool> table;
43 table.reinit(n_per_cell, n_per_cell);
44 table.fill(false);
45
46 const int N1d = n_points_1d;
47 for (unsigned int i = 0; i < n_per_cell; ++i)
48 for (unsigned int j = 0; j < n_per_cell; ++j)
49 {
50 // compute l1 distance:
51 int distance = 0;
52
53 int xi = i;
54 int xj = j;
55 for (unsigned int d = 0; d < dim; ++d)
56 {
57 int current_distance = std::abs((xi % N1d) - (xj % N1d));
58 xi /= N1d;
59 xj /= N1d;
60 distance = std::max(distance, current_distance);
61 if (distance > 1)
62 break;
63 }
64
65 if (distance <= 1)
66 table(R[i], R[j]) = true;
67 }
68
69 return table;
70 }
71} // namespace internal
72
73
74
75template <int dim, int spacedim>
76FE_Q_iso_Q1<dim, spacedim>::FE_Q_iso_Q1(const unsigned int subdivisions)
77 : FE_Q_Base<dim, spacedim>(
78 TensorProductPolynomials<dim, Polynomials::PiecewisePolynomial<double>>(
79 Polynomials::generate_complete_Lagrange_basis_on_subdivisions(
80 subdivisions,
81 1)),
82 FiniteElementData<dim>(this->get_dpo_vector(subdivisions),
83 1,
84 subdivisions,
85 FiniteElementData<dim>::H1),
86 std::vector<bool>(1, false))
87{
88 Assert(subdivisions > 0,
89 ExcMessage("This element can only be used with a positive number of "
90 "subelements"));
91
92 const QTrapezoid<1> trapez;
93 const QIterated<1> points(trapez, subdivisions);
94
95 this->initialize(points.get_points());
97 internal::make_local_sparsity_pattern<dim>(subdivisions + 1);
98}
99
100
101
102template <int dim, int spacedim>
104 const std::vector<Point<1>> &support_points)
105 : FE_Q_Base<dim, spacedim>(
106 TensorProductPolynomials<dim, Polynomials::PiecewisePolynomial<double>>(
107 Polynomials::generate_complete_linear_basis_on_subdivisions(
108 support_points)),
109 FiniteElementData<dim>(this->get_dpo_vector(support_points.size() - 1),
110 1,
111 support_points.size() - 1,
112 FiniteElementData<dim>::H1),
113 std::vector<bool>(1, false))
114{
115 Assert(support_points.size() > 1,
116 ExcMessage("This element can only be used with a positive number of "
117 "subelements"));
118
119 this->initialize(support_points);
121 internal::make_local_sparsity_pattern<dim>(support_points.size());
122}
123
124
125
126template <int dim, int spacedim>
127std::string
129{
130 // note that the FETools::get_fe_by_name function depends on the
131 // particular format of the string this function returns, so they have to be
132 // kept in sync
133
134 std::ostringstream namebuf;
135 namebuf << "FE_Q_iso_Q1<" << Utilities::dim_string(dim, spacedim) << ">("
136 << this->degree << ")";
137 return namebuf.str();
138}
139
140
141
142template <int dim, int spacedim>
143void
146 const std::vector<Vector<double>> &support_point_values,
147 std::vector<double> &nodal_values) const
148{
149 AssertDimension(support_point_values.size(),
150 this->get_unit_support_points().size());
151 AssertDimension(support_point_values.size(), nodal_values.size());
152 AssertDimension(this->n_dofs_per_cell(), nodal_values.size());
153
154 for (unsigned int i = 0; i < this->n_dofs_per_cell(); ++i)
155 {
156 AssertDimension(support_point_values[i].size(), 1);
157
158 nodal_values[i] = support_point_values[i](0);
159 }
160}
161
162
163
164template <int dim, int spacedim>
165std::unique_ptr<FiniteElement<dim, spacedim>>
167{
168 return std::make_unique<FE_Q_iso_Q1<dim, spacedim>>(*this);
169}
170
171
172
173template <int dim, int spacedim>
176 const FiniteElement<dim, spacedim> &fe_other,
177 const unsigned int codim) const
178{
179 Assert(codim <= dim, ExcImpossibleInDim(dim));
180 (void)codim;
181
182 // vertex/line/face domination
183 // (if fe_other is derived from FE_DGQ)
184 // ------------------------------------
185 if (codim > 0)
186 if (dynamic_cast<const FE_DGQ<dim, spacedim> *>(&fe_other) != nullptr)
187 // there are no requirements between continuous and discontinuous elements
189
190 // vertex/line/face domination
191 // (if fe_other is not derived from FE_DGQ)
192 // & cell domination
193 // ----------------------------------------
194 if (const FE_Q_iso_Q1<dim, spacedim> *fe_q_iso_q1_other =
195 dynamic_cast<const FE_Q_iso_Q1<dim, spacedim> *>(&fe_other))
196 {
197 // different behavior as in FE_Q: as FE_Q_iso_Q1(2) is not a subspace of
198 // FE_Q_iso_Q1(3), need that the element degrees are multiples of each
199 // other
200 if (this->degree < fe_q_iso_q1_other->degree &&
201 fe_q_iso_q1_other->degree % this->degree == 0)
203 else if (this->degree == fe_q_iso_q1_other->degree)
205 else if (this->degree > fe_q_iso_q1_other->degree &&
206 this->degree % fe_q_iso_q1_other->degree == 0)
208 else
210 }
211 else if (const FE_Nothing<dim> *fe_nothing =
212 dynamic_cast<const FE_Nothing<dim> *>(&fe_other))
213 {
214 if (fe_nothing->is_dominating())
216 else
217 // the FE_Nothing has no degrees of freedom and it is typically used
218 // in a context where we don't require any continuity along the
219 // interface
221 }
222
225}
226
227
228
229// explicit instantiations
230#include "fe/fe_q_iso_q1.inst"
231
void initialize(const std::vector< Point< 1 > > &support_points_1d)
virtual FiniteElementDomination::Domination compare_for_domination(const FiniteElement< dim, spacedim > &fe_other, const unsigned int codim=0) const override final
virtual std::string get_name() const override
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
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const override
FE_Q_iso_Q1(const unsigned int n_subdivisions)
Table< 2, bool > local_dof_sparsity_pattern
Definition fe.h:2746
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()
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcMessage(std::string arg1)
std::size_t size
Definition mpi.cc:733
std::string dim_string(const int dim, const int spacedim)
Definition utilities.cc:547
constexpr T pow(const T base, const int iexp)
Definition utilities.h:966
Table< 2, bool > make_local_sparsity_pattern(unsigned int n_points_1d)
STL namespace.
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)