Reference documentation for deal.II version 9.1.1
\(\newcommand{\dealcoloneq}{\mathrel{\vcenter{:}}=}\)
polynomials_bernardi_raugel.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/base/polynomials_bernardi_raugel.h>
18 
19 DEAL_II_NAMESPACE_OPEN
20 
21 
22 template <int dim>
24  : my_degree(k)
25  , n_pols(compute_n_pols(k))
26  , polynomial_space_Q(create_polynomials_Q())
27  , polynomial_space_bubble(create_polynomials_bubble())
28 {}
29 
30 
31 template <int dim>
32 std::vector<std::vector<Polynomials::Polynomial<double>>>
34 {
35  std::vector<std::vector<Polynomials::Polynomial<double>>> pols;
36  std::vector<Polynomials::Polynomial<double>> bubble_shapes;
37  bubble_shapes.push_back(Polynomials::LagrangeEquidistant(1, 0));
38  bubble_shapes.push_back(Polynomials::LagrangeEquidistant(1, 1));
39  bubble_shapes.push_back(Polynomials::LagrangeEquidistant(2, 1));
40 
41  for (unsigned int d = 0; d < dim; ++d)
42  pols.push_back(bubble_shapes);
43  // In 2D, the only q_ij polynomials we will use are 31,32,13,23
44  // where ij corresponds to index (i-1)+3*(j-1) (2,5,6,7)
45 
46  // In 3D, the only q_ijk polynomials we will use are 331,332,313,323,133,233
47  // where ijk corresponds to index (i-1)+3*(j-1)+9*(k-1) (8,17,20,23,24,25)
48  return pols;
49 }
50 
51 
52 
53 template <int dim>
54 std::vector<std::vector<Polynomials::Polynomial<double>>>
56 {
57  std::vector<std::vector<Polynomials::Polynomial<double>>> pols;
58  std::vector<Polynomials::Polynomial<double>> Q_shapes;
59  Q_shapes.push_back(Polynomials::LagrangeEquidistant(1, 0));
60  Q_shapes.push_back(Polynomials::LagrangeEquidistant(1, 1));
61  for (unsigned int d = 0; d < dim; ++d)
62  pols.push_back(Q_shapes);
63 
64  return pols;
65 }
66 
67 
68 template <int dim>
69 void
71  const Point<dim> & unit_point,
72  std::vector<Tensor<1, dim>> &values,
73  std::vector<Tensor<2, dim>> &grads,
74  std::vector<Tensor<3, dim>> &grad_grads,
75  std::vector<Tensor<4, dim>> &third_derivatives,
76  std::vector<Tensor<5, dim>> &fourth_derivatives) const
77 {
78  Assert(values.size() == n_pols || values.size() == 0,
79  ExcDimensionMismatch(values.size(), n_pols));
80  Assert(grads.size() == n_pols || grads.size() == 0,
81  ExcDimensionMismatch(grads.size(), n_pols));
82  Assert(grad_grads.size() == n_pols || grad_grads.size() == 0,
83  ExcDimensionMismatch(grad_grads.size(), n_pols));
84  Assert(third_derivatives.size() == n_pols || third_derivatives.size() == 0,
85  ExcDimensionMismatch(third_derivatives.size(), n_pols));
86  Assert(fourth_derivatives.size() == n_pols || fourth_derivatives.size() == 0,
87  ExcDimensionMismatch(fourth_derivatives.size(), n_pols));
88 
89  std::vector<double> Q_values;
90  std::vector<Tensor<1, dim>> Q_grads;
91  std::vector<Tensor<2, dim>> Q_grad_grads;
92  std::vector<Tensor<3, dim>> Q_third_derivatives;
93  std::vector<Tensor<4, dim>> Q_fourth_derivatives;
94  std::vector<double> bubble_values;
95  std::vector<Tensor<1, dim>> bubble_grads;
96  std::vector<Tensor<2, dim>> bubble_grad_grads;
97  std::vector<Tensor<3, dim>> bubble_third_derivatives;
98  std::vector<Tensor<4, dim>> bubble_fourth_derivatives;
99 
100  constexpr int n_bubbles =
101  Utilities::pow(3, dim); // size for create_polynomials_bubble
102  constexpr int n_q = 1 << dim; // size for create_polynomials_q
103 
104  // don't resize if the provided vector has 0 length
105  Q_values.resize((values.size() == 0) ? 0 : n_q);
106  Q_grads.resize((grads.size() == 0) ? 0 : n_q);
107  Q_grad_grads.resize((grad_grads.size() == 0) ? 0 : n_q);
108  Q_third_derivatives.resize((third_derivatives.size() == 0) ? 0 : n_q);
109  Q_fourth_derivatives.resize((fourth_derivatives.size() == 0) ? 0 : n_q);
110  bubble_values.resize((values.size() == 0) ? 0 : n_bubbles);
111  bubble_grads.resize((grads.size() == 0) ? 0 : n_bubbles);
112  bubble_grad_grads.resize((grad_grads.size() == 0) ? 0 : n_bubbles);
113  bubble_third_derivatives.resize((third_derivatives.size() == 0) ? 0 :
114  n_bubbles);
115  bubble_fourth_derivatives.resize(
116  (fourth_derivatives.size() == 0) ? 0 : n_bubbles);
117 
118  // 1 normal vector per face, ordering consistent with GeometryInfo
119  // Normal vectors point in the +x, +y, and +z directions for
120  // consistent orientation across edges
121  std::vector<Tensor<1, dim>> normals;
122  for (unsigned int i = 0; i < GeometryInfo<dim>::faces_per_cell; ++i)
123  {
124  Tensor<1, dim> normal;
125  normal[i / 2] = 1;
126  normals.push_back(normal);
127  }
128 
129  // dim standard basis vectors for R^dim, usual ordering
130  std::vector<Tensor<1, dim>> units;
131  for (unsigned int i = 0; i < dim; ++i)
132  {
133  Tensor<1, dim> unit;
134  unit[i] = 1;
135  units.push_back(unit);
136  }
137 
138  // set indices for the anisotropic polynomials to find
139  // them after polynomial_space_bubble.compute is called
140  std::vector<int> aniso_indices;
141  if (dim == 2)
142  {
143  aniso_indices.push_back(6);
144  aniso_indices.push_back(7);
145  aniso_indices.push_back(2);
146  aniso_indices.push_back(5);
147  }
148  else if (dim == 3)
149  {
150  aniso_indices.push_back(24);
151  aniso_indices.push_back(25);
152  aniso_indices.push_back(20);
153  aniso_indices.push_back(23);
154  aniso_indices.push_back(8);
155  aniso_indices.push_back(17);
156  }
157 
158  polynomial_space_bubble.compute(unit_point,
159  bubble_values,
160  bubble_grads,
161  bubble_grad_grads,
162  bubble_third_derivatives,
163  bubble_fourth_derivatives);
164  polynomial_space_Q.compute(unit_point,
165  Q_values,
166  Q_grads,
167  Q_grad_grads,
168  Q_third_derivatives,
169  Q_fourth_derivatives);
170 
171  // first dim*vertices_per_cell functions are Q_1^2 functions
172  for (unsigned int i = 0; i < dim * GeometryInfo<dim>::vertices_per_cell; ++i)
173  {
174  if (values.size() != 0)
175  {
176  values[i] = units[i % dim] * Q_values[i / dim];
177  }
178  if (grads.size() != 0)
179  {
180  grads[i] = outer_product(units[i % dim], Q_grads[i / dim]);
181  }
182  if (grad_grads.size() != 0)
183  {
184  grad_grads[i] = outer_product(units[i % dim], Q_grad_grads[i / dim]);
185  }
186  if (third_derivatives.size() != 0)
187  {
188  third_derivatives[i] =
189  outer_product(units[i % dim], Q_third_derivatives[i / dim]);
190  }
191  if (fourth_derivatives.size() != 0)
192  {
193  fourth_derivatives[i] =
194  outer_product(units[i % dim], Q_fourth_derivatives[i / dim]);
195  }
196  }
197 
198  // last faces_per_cell functions are bubble functions
199  for (unsigned int i = dim * GeometryInfo<dim>::vertices_per_cell;
200  i < dim * GeometryInfo<dim>::vertices_per_cell +
202  ++i)
203  {
204  unsigned int j =
205  i -
206  dim *
207  GeometryInfo<dim>::vertices_per_cell; // ranges 0 to faces_per_cell-1
208  if (values.size() != 0)
209  {
210  values[i] = normals[j] * bubble_values[aniso_indices[j]];
211  }
212  if (grads.size() != 0)
213  {
214  grads[i] = outer_product(normals[j], bubble_grads[aniso_indices[j]]);
215  }
216  if (grad_grads.size() != 0)
217  {
218  grad_grads[i] =
219  outer_product(normals[j], bubble_grad_grads[aniso_indices[j]]);
220  }
221  if (third_derivatives.size() != 0)
222  {
223  third_derivatives[i] =
224  outer_product(normals[j],
225  bubble_third_derivatives[aniso_indices[j]]);
226  }
227  if (fourth_derivatives.size() != 0)
228  {
229  fourth_derivatives[i] =
230  outer_product(normals[j],
231  bubble_fourth_derivatives[aniso_indices[j]]);
232  }
233  }
234 }
235 
236 template <int dim>
237 unsigned int
239 {
240  (void)k;
241  Assert(k == 1, ExcNotImplemented());
242  if (dim == 2 || dim == 3)
245  // 2*4+4=12 polynomials in 2D and 3*8+6=30 polynomials in 3D
246 
247  Assert(false, ExcNotImplemented());
248  return 0;
249 }
250 
251 template class PolynomialsBernardiRaugel<1>; // to prevent errors
252 template class PolynomialsBernardiRaugel<2>;
253 template class PolynomialsBernardiRaugel<3>;
254 
255 
256 DEAL_II_NAMESPACE_CLOSE
static std::vector< std::vector< Polynomials::Polynomial< double > > > create_polynomials_Q()
#define Assert(cond, exc)
Definition: exceptions.h:1407
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
constexpr unsigned int pow(const unsigned int base, const int iexp)
Definition: utilities.h:428
SymmetricTensor< 4, dim, Number > outer_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, Number > &t2)
static std::vector< std::vector< Polynomials::Polynomial< double > > > create_polynomials_bubble()
PolynomialsBernardiRaugel(const unsigned int k)
static unsigned int compute_n_pols(const unsigned int k)
static ::ExceptionBase & ExcNotImplemented()
void compute(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