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_wedge_p.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) 2021 - 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#include <deal.II/base/config.h>
14
17
18#include <deal.II/fe/fe_dgq.h>
21#include <deal.II/fe/fe_q.h>
24#include <deal.II/fe/fe_tools.h>
26
28
29namespace
30{
35 get_dpo_vector_fe_wedge_p(const unsigned int degree)
36 {
37 Assert(degree > 0, ExcNotImplemented());
38
40
41 const unsigned int n_dofs_total =
42 (degree + 1) * (degree + 1) * (degree + 2) / 2;
43
44 const unsigned int n_dofs_per_line = degree - 1;
45
46 const unsigned int n_dofs_per_tri =
47 degree > 1 ? (degree - 2) * (degree - 1) / 2 : 0;
49 const unsigned int n_dofs_per_quad = (degree - 1) * (degree - 1);
50
51 const unsigned int n_dof_per_volume =
52 n_dofs_total - 6 - 9 * n_dofs_per_line - 2 * n_dofs_per_tri -
53 3 * n_dofs_per_quad;
54
55 const unsigned int n_dof_per_tri_inclusive =
56 (degree + 1) * (degree + 2) / 2;
57
58 const unsigned int n_dofs_per_quad_inclusive = (degree + 1) * (degree + 1);
59
61 {n_dofs_per_line},
62 {n_dofs_per_tri,
63 n_dofs_per_tri,
64 n_dofs_per_quad,
65 n_dofs_per_quad,
66 n_dofs_per_quad},
67 {n_dof_per_volume}};
68
70 {n_dofs_per_line + 2},
71 {n_dof_per_tri_inclusive,
72 n_dof_per_tri_inclusive,
73 n_dofs_per_quad_inclusive,
74 n_dofs_per_quad_inclusive,
75 n_dofs_per_quad_inclusive},
76 {n_dofs_total}};
77
78 dpo.object_index = {
79 {},
80 {6},
81 {6 + 9 * n_dofs_per_line,
82 6 + 9 * n_dofs_per_line + n_dofs_per_tri,
83 6 + 9 * n_dofs_per_line + 2 * n_dofs_per_tri,
84 6 + 9 * n_dofs_per_line + 2 * n_dofs_per_tri + n_dofs_per_quad,
85 6 + 9 * n_dofs_per_line + 2 * n_dofs_per_tri + 2 * n_dofs_per_quad},
86 {6 + 9 * n_dofs_per_line + 2 * n_dofs_per_tri + 3 * n_dofs_per_quad}};
87
89 {3, 3, 4, 4, 4},
90 {3 + 3 * n_dofs_per_line,
91 3 + 3 * n_dofs_per_line,
92 4 + 4 * n_dofs_per_line,
93 4 + 4 * n_dofs_per_line,
94 4 + 4 * n_dofs_per_line}};
95
96 return dpo;
97 }
98
103 get_dpo_vector_fe_wedge_dgp(const unsigned int degree)
104 {
105 Assert(degree > 0, ExcNotImplemented());
106
107 const unsigned int n_dofs = (degree + 1) * (degree + 1) * (degree + 2) / 2;
108
109 return internal::expand<3>({{0, 0, 0, n_dofs}}, ReferenceCells::Wedge);
110 }
111} // namespace
112
113
114
115template <int dim, int spacedim>
117 const unsigned int degree,
119 const bool prolongation_is_additive,
120 const typename FiniteElementData<dim>::Conformity conformity)
121 : ::FE_Poly<dim, spacedim>(
123 FiniteElementData<dim>(dpos,
124 reinterpret_cast<const ReferenceCell<dim> &>(
125 ReferenceCells::Wedge),
126 1,
127 degree,
128 conformity),
129 std::vector<bool>(
130 FiniteElementData<dim>(dpos,
131 reinterpret_cast<const ReferenceCell<dim> &>(
132 ReferenceCells::Wedge),
133 1,
134 degree)
135 .dofs_per_cell,
136 prolongation_is_additive),
137 std::vector<ComponentMask>(
138 FiniteElementData<dim>(dpos,
139 reinterpret_cast<const ReferenceCell<dim> &>(
140 ReferenceCells::Wedge),
141 1,
142 degree)
143 .dofs_per_cell,
144 ComponentMask(std::vector<bool>(1, true))))
145{
146 AssertDimension(dim, 3);
147
148 Assert(1 <= degree && degree <= 2, ExcNotImplemented());
149
150 const FE_SimplexP<2> fe_triangle(degree);
151 const FE_Q<1> fe_line(degree);
152 const FE_Q<2> fe_quad(degree);
153
154 this->unit_support_points = internal::get_wedge_support_points<dim>(degree);
155
156 this->unit_face_support_points.resize(this->reference_cell().n_faces());
157
158 for (const auto f : this->reference_cell().face_indices())
159 if (this->reference_cell().face_reference_cell(f) ==
161 for (const auto &p : fe_triangle.get_unit_support_points())
162 this->unit_face_support_points[f].emplace_back(p[0], p[1]);
163 else if (this->reference_cell().face_reference_cell(f) ==
165 for (const auto &p : fe_quad.get_unit_support_points())
166 this->unit_face_support_points[f].emplace_back(p[0], p[1]);
167 else
169}
170
171
172
173template <int dim, int spacedim>
174void
177 const std::vector<Vector<double>> &support_point_values,
178 std::vector<double> &nodal_values) const
179{
180 AssertDimension(support_point_values.size(),
181 this->get_unit_support_points().size());
182 AssertDimension(support_point_values.size(), nodal_values.size());
183 AssertDimension(this->dofs_per_cell, nodal_values.size());
184
185 for (unsigned int i = 0; i < this->dofs_per_cell; ++i)
186 {
187 AssertDimension(support_point_values[i].size(), 1);
188
189 nodal_values[i] = support_point_values[i](0);
190 }
191}
192
193
194
195template <int dim, int spacedim>
196FE_WedgeP<dim, spacedim>::FE_WedgeP(const unsigned int degree)
197 : FE_WedgePoly<dim, spacedim>(degree,
198 get_dpo_vector_fe_wedge_p(degree),
199 false,
200 FiniteElementData<dim>::H1)
201{}
202
203
204
205template <int dim, int spacedim>
206std::unique_ptr<FiniteElement<dim, spacedim>>
208{
209 return std::make_unique<FE_WedgeP<dim, spacedim>>(*this);
210}
211
212
213
214template <int dim, int spacedim>
215std::string
217{
218 std::ostringstream namebuf;
219 namebuf << "FE_WedgeP<" << Utilities::dim_string(dim, spacedim) << ">("
220 << this->degree << ")";
221
222 return namebuf.str();
223}
224
225
226
227template <int dim, int spacedim>
230 const FiniteElement<dim, spacedim> &fe_other,
231 const unsigned int codim) const
232{
233 Assert(codim <= dim, ExcImpossibleInDim(dim));
234
235 // vertex/line/face domination
236 // (if fe_other is derived from FE_SimplexDGP)
237 // ------------------------------------
238 if (codim > 0)
239 if (dynamic_cast<const FE_SimplexDGP<dim, spacedim> *>(&fe_other) !=
240 nullptr)
241 // there are no requirements between continuous and discontinuous
242 // elements
244
245
246 // vertex/line/face domination
247 // (if fe_other is not derived from FE_SimplexDGP)
248 // & cell domination
249 // ----------------------------------------
250 if (const FE_WedgeP<dim, spacedim> *fe_wp_other =
251 dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other))
252 {
253 if (this->degree < fe_wp_other->degree)
255 else if (this->degree == fe_wp_other->degree)
257 else
259 }
260 else if (const FE_SimplexP<dim, spacedim> *fe_p_other =
261 dynamic_cast<const FE_SimplexP<dim, spacedim> *>(&fe_other))
262 {
263 if (this->degree < fe_p_other->degree)
265 else if (this->degree == fe_p_other->degree)
267 else
269 }
270 else if (const FE_Q<dim, spacedim> *fe_q_other =
271 dynamic_cast<const FE_Q<dim, spacedim> *>(&fe_other))
272 {
273 if (this->degree < fe_q_other->degree)
275 else if (this->degree == fe_q_other->degree)
277 else
279 }
280 else if (const FE_PyramidP<dim, spacedim> *fe_p_other =
281 dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other))
282 {
283 if (this->degree < fe_p_other->degree)
285 else if (this->degree == fe_p_other->degree)
287 else
289 }
290 else if (const FE_Nothing<dim> *fe_nothing =
291 dynamic_cast<const FE_Nothing<dim> *>(&fe_other))
292 {
293 if (fe_nothing->is_dominating())
295 else
296 // the FE_Nothing has no degrees of freedom and it is typically used
297 // in a context where we don't require any continuity along the
298 // interface
300 }
301
304}
305
306
307
308template <int dim, int spacedim>
309std::vector<std::pair<unsigned int, unsigned int>>
311 const FiniteElement<dim, spacedim> &fe_other) const
312{
313 (void)fe_other;
314
315 Assert((dynamic_cast<const FE_SimplexP<dim, spacedim> *>(&fe_other)) ||
316 (dynamic_cast<const FE_Q<dim, spacedim> *>(&fe_other)) ||
317 (dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other)) ||
318 (dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other)),
320
321 return {{0, 0}};
322}
323
324
325
326template <int dim, int spacedim>
327std::vector<std::pair<unsigned int, unsigned int>>
329 const FiniteElement<dim, spacedim> &fe_other) const
330{
331 Assert((dynamic_cast<const FE_SimplexP<dim, spacedim> *>(&fe_other)) ||
332 (dynamic_cast<const FE_Q<dim, spacedim> *>(&fe_other)) ||
333 (dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other)) ||
334 (dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other)),
336
337 std::vector<std::pair<unsigned int, unsigned int>> identities;
338 // check if the support points are the same location on the line
339 // to avoid rescaling for pyramids use the support points on the faces
340 const auto &face_support_points = this->get_unit_face_support_points(0);
341 const auto &face_support_points_other =
343
344 // now just compare the DoFs on the line going from [0,0] to [1,0]
345 // for a triangular face that is the first line
346 // for a quad face that is the third line
347 // adjust the offsets accordingly
348 // face number 0 of the wedge is a triangle
349 const unsigned int offset =
350 this->reference_cell().face_reference_cell(0).n_vertices();
351
352 const unsigned int offset_other =
353 fe_other.reference_cell().face_reference_cell(0).is_hyper_cube() ?
354 fe_other.reference_cell().face_reference_cell(0).n_vertices() +
355 2 * fe_other.n_dofs_per_line() :
356 fe_other.reference_cell().face_reference_cell(0).n_vertices();
357
358 // now get the identities
359 for (unsigned int i = 0; i < this->n_dofs_per_line(); ++i)
360 for (unsigned int j = 0; j < fe_other.n_dofs_per_line(); ++j)
361 if (face_support_points[i + offset].distance(
362 face_support_points_other[j + offset_other]) < 1e-14)
363 identities.emplace_back(i, j);
364
365 return identities;
366}
367
368
369
370template <int dim, int spacedim>
371std::vector<std::pair<unsigned int, unsigned int>>
373 const FiniteElement<dim, spacedim> &fe_other,
374 const unsigned int face_no) const
375{
376 AssertIndexRange(face_no, 5);
377
378 std::vector<std::pair<unsigned int, unsigned int>> result;
379 unsigned int face_no_neighbor;
380
381 if (face_no < 2)
382 {
383 // triangular face
384 Assert((dynamic_cast<const FE_SimplexP<dim, spacedim> *>(&fe_other)) ||
385 (dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other)) ||
386 (dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other)),
388 if ((dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other)))
389 face_no_neighbor = 1;
390 else
391 face_no_neighbor = 0;
392 }
393 else
394 {
395 // quad face
396 Assert((dynamic_cast<const FE_Q<dim, spacedim> *>(&fe_other)) ||
397 (dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other)) ||
398 (dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other)),
400 if ((dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other)))
401 face_no_neighbor = 2;
402 else
403 face_no_neighbor = 0;
404 }
405
406 // compare the face support points
407 const auto &face_support_points = this->get_unit_face_support_points(face_no);
408 const auto &face_support_points_other =
409 fe_other.get_unit_face_support_points(face_no_neighbor);
410
411 // get the offsets to skip vertices and lines
412 const auto face_reference_cell =
413 this->reference_cell().face_reference_cell(face_no);
414 Assert(face_reference_cell ==
415 fe_other.reference_cell().face_reference_cell(face_no_neighbor),
417
418 const auto offset = face_reference_cell.n_vertices() +
419 face_reference_cell.n_lines() * this->n_dofs_per_line();
420
421 const auto offset_other =
422 face_reference_cell.n_vertices() +
423 face_reference_cell.n_lines() * fe_other.n_dofs_per_line();
424
425 // now compare the points
426 for (unsigned int i = 0; i < this->n_dofs_per_quad(face_no); ++i)
427 for (unsigned int j = 0; j < fe_other.n_dofs_per_quad(face_no_neighbor);
428 ++j)
429 if (face_support_points[i + offset].distance(
430 face_support_points_other[j + offset_other]) < 1e-14)
431 result.emplace_back(i, j);
432 return result;
433}
434
435
436
437template <int dim, int spacedim>
439 : FE_WedgePoly<dim, spacedim>(degree,
440 get_dpo_vector_fe_wedge_dgp(degree),
441 true,
442 FiniteElementData<dim>::L2)
443{}
444
445
446
447template <int dim, int spacedim>
448std::unique_ptr<FiniteElement<dim, spacedim>>
450{
451 return std::make_unique<FE_WedgeDGP<dim, spacedim>>(*this);
452}
453
454
455
456template <int dim, int spacedim>
457std::string
459{
460 std::ostringstream namebuf;
461 namebuf << "FE_WedgeDGP<" << Utilities::dim_string(dim, spacedim) << ">("
462 << this->degree << ")";
463
464 return namebuf.str();
465}
466
467// explicit instantiations
468#include "fe/fe_wedge_p.inst"
469
Definition fe_q.h:552
std::unique_ptr< FiniteElement< dim, spacedim > > clone() const override
std::string get_name() const override
FE_WedgeDGP(const unsigned int degree)
std::vector< std::pair< unsigned int, unsigned int > > hp_quad_dof_identities(const FiniteElement< dim, spacedim > &fe_other, const unsigned int face_no=0) const override
FE_WedgeP(const unsigned int degree)
std::vector< std::pair< unsigned int, unsigned int > > hp_vertex_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const override
std::vector< std::pair< unsigned int, unsigned int > > hp_line_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const override
FiniteElementDomination::Domination compare_for_domination(const FiniteElement< dim, spacedim > &fe_other, const unsigned int codim) const override
std::unique_ptr< FiniteElement< dim, spacedim > > clone() const override
std::string get_name() const override
FE_WedgePoly(const unsigned int degree, const internal::GenericDoFsPerObject &dpos, const bool prolongation_is_additive, const typename FiniteElementData< dim >::Conformity conformity)
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
const unsigned int degree
Definition fe_data.h:450
unsigned int n_dofs_per_line() const
unsigned int n_dofs_per_quad(unsigned int face_no=0) const
ReferenceCell< dim > reference_cell() const
std::vector< std::vector< Point< dim - 1 > > > unit_face_support_points
Definition fe.h:2592
const std::vector< Point< dim > > & get_unit_support_points() const
const std::vector< Point< dim - 1 > > & get_unit_face_support_points(const unsigned int face_no=0) const
std::vector< Point< dim > > unit_support_points
Definition fe.h:2585
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
std::size_t size
Definition mpi.cc:733
constexpr ReferenceCell< 2 > Quadrilateral
constexpr ReferenceCell< 2 > Triangle
constexpr ReferenceCell< 3 > Wedge
std::string dim_string(const int dim, const int spacedim)
Definition utilities.cc:547
template internal::GenericDoFsPerObject expand< 3 >(const std::vector< unsigned int > &dofs_per_object, const ReferenceCell< 3 > cell_type)
STL namespace.
std::vector< std::vector< unsigned int > > object_index
Definition fe_data.h:195
std::vector< std::vector< unsigned int > > first_object_index_on_face
Definition fe_data.h:200
std::vector< std::vector< unsigned int > > dofs_per_object_inclusive
Definition fe_data.h:190
std::vector< std::vector< unsigned int > > dofs_per_object_exclusive
Definition fe_data.h:185