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_bernardi_raugel.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) 2018 - 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
21#include <deal.II/base/tensor.h>
23
24#include <Kokkos_Macros.hpp>
25
26#include <memory>
27#include <ostream>
28
30
31
32template <int dim>
34 : TensorPolynomialsBase<dim>(k + 1, n_polynomials(k))
35 , polynomial_space_Q(create_polynomials_Q())
36 , polynomial_space_bubble(create_polynomials_bubble())
37{}
38
39
40template <int dim>
41std::vector<std::vector<Polynomials::Polynomial<double>>>
43{
44 std::vector<std::vector<Polynomials::Polynomial<double>>> pols;
45 std::vector<Polynomials::Polynomial<double>> bubble_shapes;
46 bubble_shapes.push_back(Polynomials::LagrangeEquidistant(1, 0));
47 bubble_shapes.push_back(Polynomials::LagrangeEquidistant(1, 1));
48 bubble_shapes.push_back(Polynomials::LagrangeEquidistant(2, 1));
49
50 pols.reserve(dim);
51 for (unsigned int d = 0; d < dim; ++d)
52 pols.push_back(bubble_shapes);
53 // In 2d, the only q_ij polynomials we will use are 31,32,13,23
54 // where ij corresponds to index (i-1)+3*(j-1) (2,5,6,7)
55
56 // In 3d, the only q_ijk polynomials we will use are 331,332,313,323,133,233
57 // where ijk corresponds to index (i-1)+3*(j-1)+9*(k-1) (8,17,20,23,24,25)
58 return pols;
59}
60
61
62
63template <int dim>
64std::vector<std::vector<Polynomials::Polynomial<double>>>
66{
67 std::vector<std::vector<Polynomials::Polynomial<double>>> pols;
68 std::vector<Polynomials::Polynomial<double>> Q_shapes;
69 Q_shapes.push_back(Polynomials::LagrangeEquidistant(1, 0));
70 Q_shapes.push_back(Polynomials::LagrangeEquidistant(1, 1));
71 pols.reserve(dim);
72 for (unsigned int d = 0; d < dim; ++d)
73 pols.push_back(Q_shapes);
74
75 return pols;
76}
77
78
79template <int dim>
80void
82 const Point<dim> &unit_point,
83 std::vector<Tensor<1, dim>> &values,
84 std::vector<Tensor<2, dim>> &grads,
85 std::vector<Tensor<3, dim>> &grad_grads,
86 std::vector<Tensor<4, dim>> &third_derivatives,
87 std::vector<Tensor<5, dim>> &fourth_derivatives) const
88{
89 Assert(values.size() == this->n() || values.empty(),
90 ExcDimensionMismatch(values.size(), this->n()));
91 Assert(grads.size() == this->n() || grads.empty(),
92 ExcDimensionMismatch(grads.size(), this->n()));
93 Assert(grad_grads.size() == this->n() || grad_grads.empty(),
94 ExcDimensionMismatch(grad_grads.size(), this->n()));
95 Assert(third_derivatives.size() == this->n() || third_derivatives.empty(),
96 ExcDimensionMismatch(third_derivatives.size(), this->n()));
97 Assert(fourth_derivatives.size() == this->n() || fourth_derivatives.empty(),
98 ExcDimensionMismatch(fourth_derivatives.size(), this->n()));
99
100 std::vector<double> Q_values;
101 std::vector<Tensor<1, dim>> Q_grads;
102 std::vector<Tensor<2, dim>> Q_grad_grads;
103 std::vector<Tensor<3, dim>> Q_third_derivatives;
104 std::vector<Tensor<4, dim>> Q_fourth_derivatives;
105 std::vector<double> bubble_values;
106 std::vector<Tensor<1, dim>> bubble_grads;
107 std::vector<Tensor<2, dim>> bubble_grad_grads;
108 std::vector<Tensor<3, dim>> bubble_third_derivatives;
109 std::vector<Tensor<4, dim>> bubble_fourth_derivatives;
110
111 constexpr int n_bubbles =
112 Utilities::pow(3, dim); // size for create_polynomials_bubble
113 constexpr int n_q = 1 << dim; // size for create_polynomials_q
114
115 // don't resize if the provided vector has 0 length
116 Q_values.resize((values.empty()) ? 0 : n_q);
117 Q_grads.resize((grads.empty()) ? 0 : n_q);
118 Q_grad_grads.resize((grad_grads.empty()) ? 0 : n_q);
119 Q_third_derivatives.resize((third_derivatives.empty()) ? 0 : n_q);
120 Q_fourth_derivatives.resize((fourth_derivatives.empty()) ? 0 : n_q);
121 bubble_values.resize((values.empty()) ? 0 : n_bubbles);
122 bubble_grads.resize((grads.empty()) ? 0 : n_bubbles);
123 bubble_grad_grads.resize((grad_grads.empty()) ? 0 : n_bubbles);
124 bubble_third_derivatives.resize((third_derivatives.empty()) ? 0 : n_bubbles);
125 bubble_fourth_derivatives.resize((fourth_derivatives.empty()) ? 0 :
126 n_bubbles);
127
128 // 1 normal vector per face, ordering consistent with GeometryInfo
129 // Normal vectors point in the +x, +y, and +z directions for
130 // consistent orientation across edges
131 std::vector<Tensor<1, dim>> normals;
132 for (const unsigned int i : GeometryInfo<dim>::face_indices())
133 {
134 Tensor<1, dim> normal;
135 normal[i / 2] = 1;
136 normals.push_back(normal);
137 }
138
139 // dim standard basis vectors for R^dim, usual ordering
140 std::vector<Tensor<1, dim>> units;
141 for (unsigned int i = 0; i < dim; ++i)
142 {
143 Tensor<1, dim> unit;
144 unit[i] = 1;
145 units.push_back(unit);
146 }
147
148 // set indices for the anisotropic polynomials to find
149 // them after polynomial_space_bubble.evaluate is called
150 std::vector<int> aniso_indices;
151 if (dim == 2)
152 {
153 aniso_indices.push_back(6);
154 aniso_indices.push_back(7);
155 aniso_indices.push_back(2);
156 aniso_indices.push_back(5);
157 }
158 else if (dim == 3)
159 {
160 aniso_indices.push_back(24);
161 aniso_indices.push_back(25);
162 aniso_indices.push_back(20);
163 aniso_indices.push_back(23);
164 aniso_indices.push_back(8);
165 aniso_indices.push_back(17);
166 }
167
168 polynomial_space_bubble.evaluate(unit_point,
169 bubble_values,
170 bubble_grads,
171 bubble_grad_grads,
172 bubble_third_derivatives,
173 bubble_fourth_derivatives);
174 polynomial_space_Q.evaluate(unit_point,
175 Q_values,
176 Q_grads,
177 Q_grad_grads,
178 Q_third_derivatives,
179 Q_fourth_derivatives);
180
181 // first dim*vertices_per_cell functions are Q_1^2 functions
182 for (unsigned int i = 0; i < dim * GeometryInfo<dim>::vertices_per_cell; ++i)
183 {
184 if (values.size() != 0)
185 {
186 values[i] = units[i % dim] * Q_values[i / dim];
187 }
188 if (grads.size() != 0)
189 {
190 grads[i] = outer_product(units[i % dim], Q_grads[i / dim]);
191 }
192 if (grad_grads.size() != 0)
193 {
194 grad_grads[i] = outer_product(units[i % dim], Q_grad_grads[i / dim]);
195 }
196 if (third_derivatives.size() != 0)
197 {
198 third_derivatives[i] =
199 outer_product(units[i % dim], Q_third_derivatives[i / dim]);
200 }
201 if (fourth_derivatives.size() != 0)
202 {
203 fourth_derivatives[i] =
204 outer_product(units[i % dim], Q_fourth_derivatives[i / dim]);
205 }
206 }
207
208 // last faces_per_cell functions are bubble functions
209 for (unsigned int i = dim * GeometryInfo<dim>::vertices_per_cell;
210 i < dim * GeometryInfo<dim>::vertices_per_cell +
212 ++i)
213 {
214 unsigned int j =
215 i -
216 dim *
217 GeometryInfo<dim>::vertices_per_cell; // ranges 0 to faces_per_cell-1
218 if (values.size() != 0)
219 {
220 values[i] = normals[j] * bubble_values[aniso_indices[j]];
221 }
222 if (grads.size() != 0)
223 {
224 grads[i] = outer_product(normals[j], bubble_grads[aniso_indices[j]]);
225 }
226 if (grad_grads.size() != 0)
227 {
228 grad_grads[i] =
229 outer_product(normals[j], bubble_grad_grads[aniso_indices[j]]);
230 }
231 if (third_derivatives.size() != 0)
232 {
233 third_derivatives[i] =
234 outer_product(normals[j],
235 bubble_third_derivatives[aniso_indices[j]]);
236 }
237 if (fourth_derivatives.size() != 0)
238 {
239 fourth_derivatives[i] =
240 outer_product(normals[j],
241 bubble_fourth_derivatives[aniso_indices[j]]);
242 }
243 }
244}
245
246template <int dim>
247unsigned int
249{
250 (void)k;
251 Assert(k == 1, ExcNotImplemented());
252 if (dim == 2 || dim == 3)
255 // 2*4+4=12 polynomials in 2d and 3*8+6=30 polynomials in 3d
256
258 return 0;
259}
260
261
262template <int dim>
263std::unique_ptr<TensorPolynomialsBase<dim>>
265{
266 return std::make_unique<PolynomialsBernardiRaugel<dim>>(*this);
267}
268
269template class PolynomialsBernardiRaugel<1>; // to prevent errors
270template class PolynomialsBernardiRaugel<2>;
271template class PolynomialsBernardiRaugel<3>;
272
273
Definition point.h:111
static std::vector< std::vector< Polynomials::Polynomial< double > > > create_polynomials_bubble()
void evaluate(const Point< dim > &unit_point, std::vector< Tensor< 1, dim > > &values, std::vector< Tensor< 2, dim > > &grads, std::vector< Tensor< 3, dim > > &grad_grads, std::vector< Tensor< 4, dim > > &third_derivatives, std::vector< Tensor< 5, dim > > &fourth_derivatives) const override
PolynomialsBernardiRaugel(const unsigned int k)
static std::vector< std::vector< Polynomials::Polynomial< double > > > create_polynomials_Q()
virtual std::unique_ptr< TensorPolynomialsBase< dim > > clone() const override
static unsigned int n_polynomials(const unsigned int k)
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
constexpr T pow(const T base, const int iexp)
Definition utilities.h:966
static std_cxx20::ranges::iota_view< unsigned int, unsigned int > face_indices()
constexpr SymmetricTensor< 4, dim, Number > outer_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, Number > &t2)