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
polynomials_pyramid.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) 2020 - 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
14#include <deal.II/base/config.h>
15
18#include <deal.II/base/mpi.h>
20#include <deal.II/base/point.h>
25#include <deal.II/base/table.h>
26#include <deal.II/base/tensor.h>
28
30
31#include <Kokkos_Macros.hpp>
32
33#include <algorithm>
34#include <cmath>
35#include <cstdlib>
36#include <memory>
37#include <string>
38#include <vector>
39
41
42
43namespace
44{
49 template <int dim>
50 std::vector<Point<dim>>
51 get_pyramid_vertices()
52 {
53 if constexpr (dim == 3)
54 return {ReferenceCells::Pyramid.vertex(0),
58 ReferenceCells::Pyramid.vertex(4)};
59 else
60 {
62 return {};
63 }
64 }
65} // namespace
66
67
68
69template <int dim>
71 const unsigned int degree)
72 : ScalarLagrangePolynomialPyramid<dim>(1, 5, get_pyramid_vertices<dim>())
73{
76 "This constructor only works for linear elements."));
77}
78
79
80
81template <int dim>
83 const unsigned int degree,
84 const unsigned int n_dofs,
85 const std::vector<Point<dim>> &support_points)
86 : ScalarPolynomialsVandermondeBase<dim>(degree, n_dofs)
87{
88 AssertThrow(dim == 3,
89 ExcNotImplemented("Pyramid elements only make sense in 3D."));
90
91 this->reinit(support_points);
92}
93
94
95
96template <int dim>
97double
99 dim>::evaluate_orthogonal_basis_function_by_degree(const unsigned int i,
100 const unsigned int j,
101 const unsigned int k,
102 const Point<dim> &p) const
103{
104 AssertIndexRange(i, this->degree() + 1);
105 AssertIndexRange(j, this->degree() + 1);
106 AssertIndexRange(k, this->degree() + 1 - std::max(i, j));
107
108 const double x = p[0];
109 const double y = p[1];
110 const double z = p[2];
111
112 const unsigned int max_ij = std::max(i, j);
113
114 // handle the special cases
115 // assume (1-z)^0 = 1 even when z = 1
116 if (max_ij == 0)
117 return Polynomials::jacobi_polynomial_value<double>(k, 2, 0, z, true);
118
119 // at the tip the basis looks like (x/(1-z))^i * (y/(1-z))^j * (1-z)^max(i,j)
120 // when going to the tip of the cone the relation is roughly x = 1 - z, so
121 // (x/(1-z)) = const and the (1-z)^max(i,j) term then pushes to 0
122 if (std::fabs(z - 1.0) < 1e-14)
123 return 0.0;
124
125 const double ratio = 1.0 / (1.0 - z);
126
127 const double phi =
128 Polynomials::jacobi_polynomial_value<double>(i, 0, 0, x * ratio, false) *
129 Polynomials::jacobi_polynomial_value<double>(j, 0, 0, y * ratio, false) *
130 std::pow((1.0 - z), max_ij) *
131 Polynomials::jacobi_polynomial_value<double>(k, 2 * max_ij + 2, 0, z, true);
132
133 if (std::fabs(phi) < 1e-14)
134 return 0.0;
135
136 return phi;
137}
138
139
140
141template <int dim>
142double
144 const unsigned int i,
145 const Point<dim> &p) const
146{
147 AssertIndexRange(i, this->n());
148
149 // find corresponding entry to i
150 // it holds 0 <= j, k <= degree,
151 // 0 <= l <= degree - max(j, k)
152 for (unsigned int j = 0, counter = 0; j <= this->degree(); ++j)
153 for (unsigned int k = 0; k <= this->degree(); ++k)
154 for (unsigned int l = 0; l <= this->degree() - std::max(j, k);
155 ++l, ++counter)
156 if (counter == i)
157 return evaluate_orthogonal_basis_function_by_degree(j, k, l, p);
158
160 return 0;
161}
162
163
164
165template <int dim>
169 const unsigned int j,
170 const unsigned int k,
171 const Point<dim> &p) const
172{
173 AssertIndexRange(i, this->degree() + 1);
174 AssertIndexRange(j, this->degree() + 1);
175 AssertIndexRange(k, this->degree() + 1 - std::max(i, j));
176
177 Tensor<1, dim> grad;
178
179 const double x = p[0];
180 const double y = p[1];
181 const double z = p[2];
182
183 // handle the special cases where 1/(1-z) cancels and the tip
184 if (i == 0 && j == 0)
185 {
186 // assume (1-z)^0 = 1 even when z = 1
187 grad[0] = 0.;
188 if constexpr (dim > 1)
189 grad[1] = 0.;
190 if constexpr (dim > 2)
191 grad[2] =
192 Polynomials::jacobi_polynomial_derivative<double>(k, 2, 0, z, true);
193
194 return grad;
195 }
196 else if (i == 0 && j == 1)
197 {
198 grad[0] = 0.;
199 if constexpr (dim > 1)
200 grad[1] =
201 Polynomials::jacobi_polynomial_value<double>(k, 4, 0, z, true);
202 if constexpr (dim > 2)
203 grad[2] =
204 y *
205 Polynomials::jacobi_polynomial_derivative<double>(k, 4, 0, z, true);
206
207 return grad;
208 }
209 else if (i == 1 && j == 0)
210 {
211 grad[0] = Polynomials::jacobi_polynomial_value<double>(k, 4, 0, z, true);
212 if constexpr (dim > 1)
213 grad[1] = 0.0;
214 if constexpr (dim > 2)
215 grad[2] =
216 x *
217 Polynomials::jacobi_polynomial_derivative<double>(k, 4, 0, z, true);
218
219 return grad;
220 }
221 else if (std::abs(p[2] - 1.0) < 1e-14)
222 {
223 grad = 0.;
224 if (i == 1 && j == 1)
225 // assume x/(1-z)-> 1 and y/(1-z)-> 1 at the tip
226 for (unsigned int d = 0; d < dim; ++d)
227 grad[d] =
228 Polynomials::jacobi_polynomial_value<double>(k, 4, 0, z, true);
229
230 return grad;
231 }
232
233 const unsigned int max_ij = std::max(i, j);
234 const double ratio = 1.0 / (1.0 - z);
235
236 grad[0] =
237 Polynomials::jacobi_polynomial_derivative<double>(
238 i, 0, 0, x * ratio, false) *
239 ratio *
240 Polynomials::jacobi_polynomial_value<double>(j, 0, 0, y * ratio, false) *
241 std::pow((1.0 - z), max_ij) *
242 Polynomials::jacobi_polynomial_value<double>(k, 2 * max_ij + 2, 0, z, true);
243 if constexpr (dim > 1)
244 grad[1] =
245 Polynomials::jacobi_polynomial_value<double>(i, 0, 0, x * ratio, false) *
246 Polynomials::jacobi_polynomial_derivative<double>(
247 j, 0, 0, y * ratio, false) *
248 ratio * std::pow((1.0 - z), max_ij) *
249 Polynomials::jacobi_polynomial_value<double>(
250 k, 2 * max_ij + 2, 0, z, true);
251 if constexpr (dim > 2)
252 grad[2] =
253 Polynomials::jacobi_polynomial_derivative<double>(
254 i, 0, 0, x * ratio, false) *
255 x * ratio * ratio *
256 Polynomials::jacobi_polynomial_value<double>(
257 j, 0, 0, y * ratio, false) *
258 std::pow((1.0 - z), max_ij) *
259 Polynomials::jacobi_polynomial_value<double>(
260 k, 2 * max_ij + 2, 0, z, true) +
261 Polynomials::jacobi_polynomial_value<double>(i, 0, 0, x * ratio, false) *
262 Polynomials::jacobi_polynomial_derivative<double>(
263 j, 0, 0, y * ratio, false) *
264 y * ratio * ratio * std::pow((1.0 - z), max_ij) *
265 Polynomials::jacobi_polynomial_value<double>(
266 k, 2 * max_ij + 2, 0, z, true) +
267 Polynomials::jacobi_polynomial_value<double>(i, 0, 0, x * ratio, false) *
268 Polynomials::jacobi_polynomial_value<double>(
269 j, 0, 0, y * ratio, false) *
270 (-1.0) * max_ij * std::pow((1.0 - z), max_ij - 1) *
271 Polynomials::jacobi_polynomial_value<double>(
272 k, 2 * max_ij + 2, 0, z, true) +
273 Polynomials::jacobi_polynomial_value<double>(i, 0, 0, x * ratio, false) *
274 Polynomials::jacobi_polynomial_value<double>(
275 j, 0, 0, y * ratio, false) *
276 std::pow((1.0 - z), max_ij) *
277 Polynomials::jacobi_polynomial_derivative<double>(
278 k, 2 * max_ij + 2, 0, 2.0 * z - 1.0, false) *
279 2.0;
280
281 for (unsigned int d = 0; d < dim; ++d)
282 if (std::fabs(grad[d]) < 1e-14)
283 grad[d] = 0.0;
284
285 return grad;
286}
287
288
289
290template <int dim>
293 const unsigned int i,
294 const Point<dim> &p) const
295{
296 AssertIndexRange(i, this->n());
297
298 // find corresponding entrance to i
299 for (unsigned int j = 0, counter = 0; j <= this->degree(); ++j)
300 for (unsigned int k = 0; k <= this->degree(); ++k)
301 for (unsigned int l = 0; l <= this->degree() - std::max(j, k);
302 ++l, ++counter)
303 if (counter == i)
304 return evaluate_orthogonal_basis_derivative_by_degree(j, k, l, p);
305
307 return Tensor<1, dim>();
308}
309
310
311template <int dim>
312std::string
314{
315 return "ScalarLagrangePolynomialPyramid";
316}
317
318
319
320template <int dim>
321std::unique_ptr<ScalarPolynomialsBase<dim>>
323{
324 return std::make_unique<ScalarLagrangePolynomialPyramid<dim>>(*this);
325}
326
327
328
332
Definition point.h:111
Tensor< 1, dim > evaluate_orthogonal_basis_derivative(const unsigned int i, const Point< dim > &p) const override
ScalarLagrangePolynomialPyramid(const unsigned int degree)
double evaluate_orthogonal_basis_function(const unsigned int i, const Point< dim > &p) const override
Tensor< 1, dim > evaluate_orthogonal_basis_derivative_by_degree(const unsigned int i, const unsigned int j, const unsigned int k, const Point< dim > &p) const override
virtual std::unique_ptr< ScalarPolynomialsBase< dim > > clone() const override
std::string name() const override
virtual unsigned int degree() const
void reinit(const std::vector< Point< dim > > &support_points)
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ASSERT_UNREACHABLE()
static ::ExceptionBase & ExcNotImplemented()
#define AssertIndexRange(index, range)
#define AssertThrow(cond, exc)
constexpr ReferenceCell< 3 > Pyramid
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)