deal.II version 9.8.0
\(\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 {
38
39 if (degree == 1)
40 {
41 dpo.dofs_per_object_exclusive = {{1}, {0}, {0, 0, 0, 0, 0}, {0}};
42 dpo.dofs_per_object_inclusive = {{1}, {2}, {3, 3, 4, 4, 4}, {6}};
43 dpo.object_index = {{}, {6}, {6}, {6}};
44 dpo.first_object_index_on_face = {{}, {3, 3, 4, 4, 4}, {3, 3, 4, 4, 4}};
45 }
46 else if (degree == 2)
47 {
48 dpo.dofs_per_object_exclusive = {{1}, {1}, {0, 0, 1, 1, 1}, {0}};
49 dpo.dofs_per_object_inclusive = {{1}, {3}, {6, 6, 9, 9, 9}, {18}};
50 dpo.object_index = {{}, {6}, {15, 15, 15, 16, 17}, {18}};
51 dpo.first_object_index_on_face = {{}, {3, 3, 4, 4, 4}, {6, 6, 8, 8, 8}};
52 }
53 else
54 {
56 }
57
58 return dpo;
59 }
60
65 get_dpo_vector_fe_wedge_dgp(const unsigned int degree)
66 {
67 unsigned int n_dofs = 0;
68
69 if (degree == 1)
70 n_dofs = 6;
71 else if (degree == 2)
72 n_dofs = 18;
73 else
75
76 return internal::expand<3>({{0, 0, 0, n_dofs}}, ReferenceCells::Wedge);
77 }
78} // namespace
79
80
81
82template <int dim, int spacedim>
84 const unsigned int degree,
86 const bool prolongation_is_additive,
87 const typename FiniteElementData<dim>::Conformity conformity)
88 : ::FE_Poly<dim, spacedim>(
90 FiniteElementData<dim>(dpos,
91 reinterpret_cast<const ReferenceCell<dim> &>(
92 ReferenceCells::Wedge),
93 1,
94 degree,
95 conformity),
96 std::vector<bool>(
97 FiniteElementData<dim>(dpos,
98 reinterpret_cast<const ReferenceCell<dim> &>(
99 ReferenceCells::Wedge),
100 1,
101 degree)
103 prolongation_is_additive),
104 std::vector<ComponentMask>(
105 FiniteElementData<dim>(dpos,
106 reinterpret_cast<const ReferenceCell<dim> &>(
107 ReferenceCells::Wedge),
108 1,
109 degree)
111 ComponentMask(std::vector<bool>(1, true))))
112{
113 AssertDimension(dim, 3);
114
115 Assert(1 <= degree && degree <= 2, ExcNotImplemented());
116
117 const FE_SimplexP<2> fe_triangle(degree);
118 const FE_Q<1> fe_line(degree);
119 const FE_Q<2> fe_quad(degree);
120
122
123 this->unit_face_support_points.resize(this->reference_cell().n_faces());
124
125 for (const auto f : this->reference_cell().face_indices())
126 if (this->reference_cell().face_reference_cell(f) ==
128 for (const auto &p : fe_triangle.get_unit_support_points())
129 this->unit_face_support_points[f].emplace_back(p[0], p[1]);
130 else if (this->reference_cell().face_reference_cell(f) ==
132 for (const auto &p : fe_quad.get_unit_support_points())
133 this->unit_face_support_points[f].emplace_back(p[0], p[1]);
134 else
136}
137
138
139
140template <int dim, int spacedim>
141void
144 const std::vector<Vector<double>> &support_point_values,
145 std::vector<double> &nodal_values) const
146{
147 AssertDimension(support_point_values.size(),
148 this->get_unit_support_points().size());
149 AssertDimension(support_point_values.size(), nodal_values.size());
150 AssertDimension(this->dofs_per_cell, nodal_values.size());
151
152 for (unsigned int i = 0; i < this->dofs_per_cell; ++i)
153 {
154 AssertDimension(support_point_values[i].size(), 1);
155
156 nodal_values[i] = support_point_values[i](0);
157 }
158}
159
160
161
162template <int dim, int spacedim>
164 : FE_WedgePoly<dim, spacedim>(degree,
165 get_dpo_vector_fe_wedge_p(degree),
166 false,
167 FiniteElementData<dim>::H1)
168{}
169
170
171
172template <int dim, int spacedim>
173std::unique_ptr<FiniteElement<dim, spacedim>>
175{
176 return std::make_unique<FE_WedgeP<dim, spacedim>>(*this);
177}
178
179
180
181template <int dim, int spacedim>
182std::string
184{
185 std::ostringstream namebuf;
186 namebuf << "FE_WedgeP<" << Utilities::dim_string(dim, spacedim) << ">("
187 << this->degree << ")";
188
189 return namebuf.str();
190}
191
192
193
194template <int dim, int spacedim>
197 const FiniteElement<dim, spacedim> &fe_other,
198 const unsigned int codim) const
199{
200 Assert(codim <= dim, ExcImpossibleInDim(dim));
201
202 // vertex/line/face domination
203 // (if fe_other is derived from FE_SimplexDGP)
204 // ------------------------------------
205 if (codim > 0)
206 if (dynamic_cast<const FE_SimplexDGP<dim, spacedim> *>(&fe_other) !=
207 nullptr)
208 // there are no requirements between continuous and discontinuous
209 // elements
211
212
213 // vertex/line/face domination
214 // (if fe_other is not derived from FE_SimplexDGP)
215 // & cell domination
216 // ----------------------------------------
217 if (const FE_WedgeP<dim, spacedim> *fe_wp_other =
218 dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other))
219 {
220 if (this->degree < fe_wp_other->degree)
222 else if (this->degree == fe_wp_other->degree)
224 else
226 }
227 else if (const FE_SimplexP<dim, spacedim> *fe_p_other =
228 dynamic_cast<const FE_SimplexP<dim, spacedim> *>(&fe_other))
229 {
230 if (this->degree < fe_p_other->degree)
232 else if (this->degree == fe_p_other->degree)
234 else
236 }
237 else if (const FE_Q<dim, spacedim> *fe_q_other =
238 dynamic_cast<const FE_Q<dim, spacedim> *>(&fe_other))
239 {
240 if (this->degree < fe_q_other->degree)
242 else if (this->degree == fe_q_other->degree)
244 else
246 }
247 else if (const FE_PyramidP<dim, spacedim> *fe_p_other =
248 dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other))
249 {
250 if (this->degree < fe_p_other->degree)
252 else if (this->degree == fe_p_other->degree)
254 else
256 }
257 else if (const FE_Nothing<dim> *fe_nothing =
258 dynamic_cast<const FE_Nothing<dim> *>(&fe_other))
259 {
260 if (fe_nothing->is_dominating())
262 else
263 // the FE_Nothing has no degrees of freedom and it is typically used
264 // in a context where we don't require any continuity along the
265 // interface
267 }
268
271}
272
273
274
275template <int dim, int spacedim>
276std::vector<std::pair<unsigned int, unsigned int>>
278 const FiniteElement<dim, spacedim> &fe_other) const
279{
280 (void)fe_other;
281
282 Assert((dynamic_cast<const FE_SimplexP<dim, spacedim> *>(&fe_other)) ||
283 (dynamic_cast<const FE_Q<dim, spacedim> *>(&fe_other)) ||
284 (dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other)) ||
285 (dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other)),
287
288 return {{0, 0}};
289}
290
291
292
293template <int dim, int spacedim>
294std::vector<std::pair<unsigned int, unsigned int>>
296 const FiniteElement<dim, spacedim> &fe_other) const
297{
298 Assert((dynamic_cast<const FE_SimplexP<dim, spacedim> *>(&fe_other)) ||
299 (dynamic_cast<const FE_Q<dim, spacedim> *>(&fe_other)) ||
300 (dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other)) ||
301 (dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other)),
303
304 std::vector<std::pair<unsigned int, unsigned int>> identities;
305 // check if the support points are the same location on the line
306 // to avoid rescaling for pyramids use the support points on the faces
307 const auto &face_support_points = this->get_unit_face_support_points(0);
308 const auto &face_support_points_other =
310
311 // now just compare the DoFs on the line going from [0,0] to [1,0]
312 // for a triangular face that is the first line
313 // for a quad face that is the third line
314 // adjust the offsets accordingly
315 // face number 0 of the wedge is a triangle
316 const unsigned int offset =
317 this->reference_cell().face_reference_cell(0).n_vertices();
318
319 const unsigned int offset_other =
320 fe_other.reference_cell().face_reference_cell(0).is_hyper_cube() ?
321 fe_other.reference_cell().face_reference_cell(0).n_vertices() +
322 2 * fe_other.n_dofs_per_line() :
323 fe_other.reference_cell().face_reference_cell(0).n_vertices();
324
325 // now get the identities
326 for (unsigned int i = 0; i < this->n_dofs_per_line(); ++i)
327 for (unsigned int j = 0; j < fe_other.n_dofs_per_line(); ++j)
328 if (face_support_points[i + offset].distance(
329 face_support_points_other[j + offset_other]) < 1e-14)
330 identities.emplace_back(i, j);
331
332 return identities;
333}
334
335
336
337template <int dim, int spacedim>
338std::vector<std::pair<unsigned int, unsigned int>>
340 const FiniteElement<dim, spacedim> &fe_other,
341 const unsigned int face_no) const
342{
343 AssertIndexRange(face_no, 5);
344
345 std::vector<std::pair<unsigned int, unsigned int>> result;
346 unsigned int face_no_neighbor;
347
348 if (face_no < 2)
349 {
350 // triangular face
351 Assert((dynamic_cast<const FE_SimplexP<dim, spacedim> *>(&fe_other)) ||
352 (dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other)) ||
353 (dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other)),
355 if ((dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other)))
356 face_no_neighbor = 1;
357 else
358 face_no_neighbor = 0;
359 }
360 else
361 {
362 // quad face
363 Assert((dynamic_cast<const FE_Q<dim, spacedim> *>(&fe_other)) ||
364 (dynamic_cast<const FE_PyramidP<dim, spacedim> *>(&fe_other)) ||
365 (dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other)),
367 if ((dynamic_cast<const FE_WedgeP<dim, spacedim> *>(&fe_other)))
368 face_no_neighbor = 2;
369 else
370 face_no_neighbor = 0;
371 }
372
373 // compare the face support points
374 const auto &face_support_points = this->get_unit_face_support_points(face_no);
375 const auto &face_support_points_other =
376 fe_other.get_unit_face_support_points(face_no_neighbor);
377
378 // get the offsets to skip vertices and lines
379 const auto face_reference_cell =
380 this->reference_cell().face_reference_cell(face_no);
381 Assert(face_reference_cell ==
382 fe_other.reference_cell().face_reference_cell(face_no_neighbor),
384
385 const auto offset = face_reference_cell.n_vertices() +
386 face_reference_cell.n_lines() * this->n_dofs_per_line();
387
388 const auto offset_other =
389 face_reference_cell.n_vertices() +
390 face_reference_cell.n_lines() * fe_other.n_dofs_per_line();
391
392 // now compare the points
393 for (unsigned int i = 0; i < this->n_dofs_per_quad(face_no); ++i)
394 for (unsigned int j = 0; j < fe_other.n_dofs_per_quad(face_no_neighbor);
395 ++j)
396 if (face_support_points[i + offset].distance(
397 face_support_points_other[j + offset_other]) < 1e-14)
398 result.emplace_back(i, j);
399 return result;
400}
401
402
403
404template <int dim, int spacedim>
406 : FE_WedgePoly<dim, spacedim>(degree,
407 get_dpo_vector_fe_wedge_dgp(degree),
408 true,
409 FiniteElementData<dim>::L2)
410{}
411
412
413
414template <int dim, int spacedim>
415std::unique_ptr<FiniteElement<dim, spacedim>>
417{
418 return std::make_unique<FE_WedgeDGP<dim, spacedim>>(*this);
419}
420
421
422
423template <int dim, int spacedim>
424std::string
426{
427 std::ostringstream namebuf;
428 namebuf << "FE_WedgeDGP<" << Utilities::dim_string(dim, spacedim) << ">("
429 << this->degree << ")";
430
431 return namebuf.str();
432}
433
434// explicit instantiations
435#include "fe/fe_wedge_p.inst"
436
FE_Poly(const ScalarPolynomialsBase< dim > &poly_space, const FiniteElementData< dim > &fe_data, const std::vector< bool > &restriction_is_additive_flags, const std::vector< ComponentMask > &nonzero_components)
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)
Definition fe_wedge_p.cc:83
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
const unsigned int dofs_per_cell
Definition fe_data.h:434
FiniteElementData(const std::vector< unsigned int > &dofs_per_object, const unsigned int n_components, const unsigned int degree, const Conformity conformity=unknown, const BlockIndices &block_indices=BlockIndices())
Definition fe_data.cc:112
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
FiniteElement(const FiniteElementData< dim > &fe_data, const std::vector< bool > &restriction_is_additive_flags, const std::vector< ComponentMask > &nonzero_components)
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()
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:549
template internal::GenericDoFsPerObject expand< 3 >(const std::vector< unsigned int > &dofs_per_object, const ReferenceCell< 3 > cell_type)
std::vector< Point< dim > > get_wedge_support_points(const unsigned int degree)
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