deal.II version GIT relicensing-6842-g793a97d2aa 2026-10-02 14:00: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_barycentric.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
19
21
23
24namespace internal
25{
30 template <int dim>
31 unsigned int
33 const std::vector<typename BarycentricPolynomials<dim>::PolyType> &polys)
34 {
35 // Since the first variable in a simplex polynomial is, e.g., in 2d,
36 //
37 // t0 = 1 - x - y
38 //
39 // (that is, it depends on the Cartesian variables), we have to compute
40 // its degree separately. An example: t0*t1*t2 has degree 1 in the affine
41 // polynomial basis but is degree 2 in the Cartesian polynomial basis.
42 std::size_t max_degree = 0;
43 for (const auto &poly : polys)
44 {
45 const TableIndices<dim + 1> degrees = poly.degrees();
46
47 const auto degree_0 = degrees[0];
48 std::size_t degree_d = 0;
49 for (unsigned int d = 1; d < dim + 1; ++d)
50 degree_d = std::max(degree_d, degrees[d]);
51
52 max_degree = std::max(max_degree, degree_d + degree_0);
53 }
54
55 return max_degree;
56 }
57} // namespace internal
58
59
60template <int dim>
63{
64 std::vector<PolyType> polys;
65
66 const auto reference_cell = ReferenceCells::get_simplex<dim>();
67
68 switch (degree)
69 {
70 case 0:
72 1);
73 break;
74 case 1:
75 {
76 for (const unsigned int v : reference_cell.vertex_indices())
78 break;
79 }
80 case 2:
81 {
82 // vertices, then lines:
83 for (const unsigned int v : reference_cell.vertex_indices())
84 polys.push_back(
87 for (const unsigned int l : reference_cell.line_indices())
88 {
89 const auto v0 = reference_cell.line_to_cell_vertices(l, 0);
90 const auto v1 = reference_cell.line_to_cell_vertices(l, 1);
91 polys.push_back(4 *
94 }
95 break;
96 }
97 case 3:
98 {
99 // vertices, then lines, then quads:
100 for (const unsigned int v : reference_cell.vertex_indices())
101 polys.push_back(
105 for (unsigned int l : reference_cell.line_indices())
106 {
107 const auto v0 = reference_cell.line_to_cell_vertices(l, 0);
108 const auto v1 = reference_cell.line_to_cell_vertices(l, 1);
109 polys.push_back(
113 polys.push_back(
117 }
118
119 if (dim == 2)
120 {
121 polys.push_back(27 *
125 }
126 else if (dim == 3)
127 {
128 polys.push_back(27 *
132 polys.push_back(27 *
136 polys.push_back(27 *
140 polys.push_back(27 *
144 }
145
146 break;
147 }
148 default:
150 }
151
152 return BarycentricPolynomials<dim>(polys);
153}
154
155
156
157template <int dim>
159 const std::vector<PolyType> &polynomials)
160 : ScalarPolynomialsBase<dim>(internal::get_degree<dim>(polynomials),
161 polynomials.size())
162 , polys(polynomials)
163{
164 poly_grads.resize(polynomials.size());
165 poly_hessians.resize(polynomials.size());
166 poly_third_derivatives.resize(polynomials.size());
167 poly_fourth_derivatives.resize(polynomials.size());
168
169 for (std::size_t i = 0; i < polynomials.size(); ++i)
170 {
171 // gradients
172 for (unsigned int d = 0; d < dim; ++d)
173 poly_grads[i][d] = polynomials[i].derivative(d);
174
175 // hessians
176 for (unsigned int d0 = 0; d0 < dim; ++d0)
177 for (unsigned int d1 = 0; d1 < dim; ++d1)
178 poly_hessians[i][d0][d1] = poly_grads[i][d0].derivative(d1);
179
180 // third derivatives
181 for (unsigned int d0 = 0; d0 < dim; ++d0)
182 for (unsigned int d1 = 0; d1 < dim; ++d1)
183 for (unsigned int d2 = 0; d2 < dim; ++d2)
184 poly_third_derivatives[i][d0][d1][d2] =
185 poly_hessians[i][d0][d1].derivative(d2);
186
187 // fourth derivatives
188 for (unsigned int d0 = 0; d0 < dim; ++d0)
189 for (unsigned int d1 = 0; d1 < dim; ++d1)
190 for (unsigned int d2 = 0; d2 < dim; ++d2)
191 for (unsigned int d3 = 0; d3 < dim; ++d3)
192 poly_fourth_derivatives[i][d0][d1][d2][d3] =
193 poly_third_derivatives[i][d0][d1][d2].derivative(d3);
194 }
195}
196
197
198
199template <int dim>
200void
202 const Point<dim> &unit_point,
203 std::vector<double> &values,
204 std::vector<Tensor<1, dim>> &grads,
205 std::vector<Tensor<2, dim>> &grad_grads,
206 std::vector<Tensor<3, dim>> &third_derivatives,
207 std::vector<Tensor<4, dim>> &fourth_derivatives) const
208{
209 Assert(values.size() == this->n() || values.empty(),
210 ExcDimensionMismatch2(values.size(), this->n(), 0));
211 Assert(grads.size() == this->n() || grads.empty(),
212 ExcDimensionMismatch2(grads.size(), this->n(), 0));
213 Assert(grad_grads.size() == this->n() || grad_grads.empty(),
214 ExcDimensionMismatch2(grad_grads.size(), this->n(), 0));
215 Assert(third_derivatives.size() == this->n() || third_derivatives.empty(),
216 ExcDimensionMismatch2(third_derivatives.size(), this->n(), 0));
217 Assert(fourth_derivatives.size() == this->n() || fourth_derivatives.empty(),
218 ExcDimensionMismatch2(fourth_derivatives.size(), this->n(), 0));
219
220 for (std::size_t i = 0; i < polys.size(); ++i)
221 {
222 if (values.size() == this->n())
223 values[i] = polys[i].value(unit_point);
224
225 // gradients
226 if (grads.size() == this->n())
227 for (unsigned int d = 0; d < dim; ++d)
228 grads[i][d] = poly_grads[i][d].value(unit_point);
229
230 // hessians
231 if (grad_grads.size() == this->n())
232 for (unsigned int d0 = 0; d0 < dim; ++d0)
233 for (unsigned int d1 = 0; d1 < dim; ++d1)
234 grad_grads[i][d0][d1] = poly_hessians[i][d0][d1].value(unit_point);
235
236 // third derivatives
237 if (third_derivatives.size() == this->n())
238 for (unsigned int d0 = 0; d0 < dim; ++d0)
239 for (unsigned int d1 = 0; d1 < dim; ++d1)
240 for (unsigned int d2 = 0; d2 < dim; ++d2)
241 third_derivatives[i][d0][d1][d2] =
242 poly_third_derivatives[i][d0][d1][d2].value(unit_point);
243
244 // fourth derivatives
245 if (fourth_derivatives.size() == this->n())
246 for (unsigned int d0 = 0; d0 < dim; ++d0)
247 for (unsigned int d1 = 0; d1 < dim; ++d1)
248 for (unsigned int d2 = 0; d2 < dim; ++d2)
249 for (unsigned int d3 = 0; d3 < dim; ++d3)
250 fourth_derivatives[i][d0][d1][d2][d3] =
251 poly_fourth_derivatives[i][d0][d1][d2][d3].value(unit_point);
252 }
253}
254
255
256
257template <int dim>
258double
260 const Point<dim> &p) const
261{
262 AssertIndexRange(i, this->n());
263 return polys[i].value(p);
264}
265
266
267
268template <int dim>
271 const Point<dim> &p) const
272{
273 Tensor<1, dim> result;
274 for (unsigned int d = 0; d < dim; ++d)
275 result[d] = poly_grads[i][d].value(p);
276 return result;
277}
278
279
280
281template <int dim>
284 const Point<dim> &p) const
285{
286 Tensor<2, dim> result;
287 for (unsigned int d0 = 0; d0 < dim; ++d0)
288 for (unsigned int d1 = 0; d1 < dim; ++d1)
289 result[d0][d1] = poly_hessians[i][d0][d1].value(p);
290
291 return result;
292}
293
294
295
296template <int dim>
299 const Point<dim> &p) const
300{
301 Tensor<3, dim> result;
302 for (unsigned int d0 = 0; d0 < dim; ++d0)
303 for (unsigned int d1 = 0; d1 < dim; ++d1)
304 for (unsigned int d2 = 0; d2 < dim; ++d2)
305 result[d0][d1][d2] = poly_third_derivatives[i][d0][d1][d2].value(p);
306
307 return result;
308}
309
310
311
312template <int dim>
315 const Point<dim> &p) const
316{
317 Tensor<4, dim> result;
318 for (unsigned int d0 = 0; d0 < dim; ++d0)
319 for (unsigned int d1 = 0; d1 < dim; ++d1)
320 for (unsigned int d2 = 0; d2 < dim; ++d2)
321 for (unsigned int d3 = 0; d3 < dim; ++d3)
322 result[d0][d1][d2][d3] =
323 poly_fourth_derivatives[i][d0][d1][d2][d3].value(p);
324
325 return result;
326}
327
328
329
330template <int dim>
333 const Point<dim> &p) const
334{
335 return compute_1st_derivative(i, p);
336}
337
338
339
340template <int dim>
343 const Point<dim> &p) const
344{
345 return compute_2nd_derivative(i, p);
346}
347
348
349
350template <int dim>
351std::unique_ptr<ScalarPolynomialsBase<dim>>
353{
354 return std::make_unique<BarycentricPolynomials<dim>>(*this);
355}
356
357
358
359template <int dim>
360std::string
362{
363 return "BarycentricPolynomials<" + std::to_string(dim) + ">";
364}
365
366
367
368template <int dim>
369std::size_t
371{
372 std::size_t poly_memory = 0;
373 for (const auto &poly : polys)
374 poly_memory += poly.memory_consumption();
378 MemoryConsumption::memory_consumption(poly_third_derivatives) +
379 MemoryConsumption::memory_consumption(poly_fourth_derivatives);
380}
381
382template class BarycentricPolynomials<1>;
383template class BarycentricPolynomials<2>;
384template class BarycentricPolynomials<3>;
385
static BarycentricPolynomial< dim, Number > monomial(const unsigned int d)
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const override
BarycentricPolynomials(const std::vector< BarycentricPolynomial< dim > > &polynomials)
virtual std::size_t memory_consumption() const override
Tensor< 2, dim > compute_grad_grad(const unsigned int i, const Point< dim > &p) const override
std::vector< GradType > poly_grads
std::string name() const override
Tensor< 3, dim > compute_3rd_derivative(const unsigned int i, const Point< dim > &p) const override
Tensor< 1, dim > compute_1st_derivative(const unsigned int i, const Point< dim > &p) const override
Tensor< 2, dim > compute_2nd_derivative(const unsigned int i, const Point< dim > &p) const override
void evaluate(const Point< dim > &unit_point, std::vector< double > &values, std::vector< Tensor< 1, dim > > &grads, std::vector< Tensor< 2, dim > > &grad_grads, std::vector< Tensor< 3, dim > > &third_derivatives, std::vector< Tensor< 4, dim > > &fourth_derivatives) const override
double compute_value(const unsigned int i, const Point< dim > &p) const override
std::vector< ThirdDerivativesType > poly_third_derivatives
virtual std::unique_ptr< ScalarPolynomialsBase< dim > > clone() const override
Tensor< 4, dim > compute_4th_derivative(const unsigned int i, const Point< dim > &p) const override
std::vector< HessianType > poly_hessians
static BarycentricPolynomials< dim > get_fe_p_basis(const unsigned int degree)
std::vector< FourthDerivativesType > poly_fourth_derivatives
Definition point.h:111
virtual std::size_t memory_consumption() const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_NOT_IMPLEMENTED()
const unsigned int v0
const unsigned int v1
#define Assert(cond, exc)
static ::ExceptionBase & ExcDimensionMismatch2(std::size_t arg1, std::size_t arg2, std::size_t arg3)
#define AssertIndexRange(index, range)
std::size_t size
Definition mpi.cc:733
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
unsigned int get_degree(const std::vector< typename BarycentricPolynomials< dim >::PolyType > &polys)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)