Reference documentation for deal.II version 8.5.1
polynomials_bdm.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2015 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 at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/base/geometry_info.h>
18 #include <deal.II/base/polynomials_bdm.h>
19 #include <deal.II/base/polynomial_space.h>
20 #include <deal.II/base/quadrature_lib.h>
21 #include <iostream>
22 #include <iomanip>
23 
24 DEAL_II_NAMESPACE_OPEN
25 
26 
27 template <int dim>
29  :
30  polynomial_space (Polynomials::Legendre::generate_complete_basis(k)),
31  monomials((dim==2) ? (1) : (k+2)),
32  n_pols(compute_n_pols(k)),
33  p_values(polynomial_space.n()),
34  p_grads(polynomial_space.n()),
35  p_grad_grads(polynomial_space.n())
36 {
37  switch (dim)
38  {
39  case 2:
41  break;
42  case 3:
43  for (unsigned int i=0; i<monomials.size(); ++i)
45  break;
46  default:
47  Assert(false, ExcNotImplemented());
48  }
49 }
50 
51 
52 
53 template <int dim>
54 void
56  std::vector<Tensor<1,dim> > &values,
57  std::vector<Tensor<2,dim> > &grads,
58  std::vector<Tensor<3,dim> > &grad_grads,
59  std::vector<Tensor<4,dim> > &third_derivatives,
60  std::vector<Tensor<5,dim> > &fourth_derivatives) const
61 {
62  Assert(values.size()==n_pols || values.size()==0,
63  ExcDimensionMismatch(values.size(), n_pols));
64  Assert(grads.size()==n_pols|| grads.size()==0,
65  ExcDimensionMismatch(grads.size(), n_pols));
66  Assert(grad_grads.size()==n_pols|| grad_grads.size()==0,
67  ExcDimensionMismatch(grad_grads.size(), n_pols));
68  Assert(third_derivatives.size()==n_pols|| third_derivatives.size()==0,
69  ExcDimensionMismatch(third_derivatives.size(), n_pols));
70  Assert(fourth_derivatives.size()==n_pols|| fourth_derivatives.size()==0,
71  ExcDimensionMismatch(fourth_derivatives.size(), n_pols));
72 
73  // third and fourth derivatives not implemented
74  (void)third_derivatives;
75  Assert(third_derivatives.size()==0,
77  (void)fourth_derivatives;
78  Assert(fourth_derivatives.size()==0,
80 
81  const unsigned int n_sub = polynomial_space.n();
82 
83  // guard access to the scratch
84  // arrays in the following block
85  // using a mutex to make sure they
86  // are not used by multiple threads
87  // at once
88  {
89  Threads::Mutex::ScopedLock lock(mutex);
90 
91  p_values.resize((values.size() == 0) ? 0 : n_sub);
92  p_grads.resize((grads.size() == 0) ? 0 : n_sub);
93  p_grad_grads.resize((grad_grads.size() == 0) ? 0 : n_sub);
94 
95  // Compute values of complete space
96  // and insert into tensors. Result
97  // will have first all polynomials
98  // in the x-component, then y and
99  // z.
100  polynomial_space.compute (unit_point, p_values, p_grads, p_grad_grads,
101  p_third_derivatives, p_fourth_derivatives);
102 
103  std::fill(values.begin(), values.end(), Tensor<1,dim>());
104  for (unsigned int i=0; i<p_values.size(); ++i)
105  for (unsigned int j=0; j<dim; ++j)
106  values[i+j*n_sub][j] = p_values[i];
107 
108  std::fill(grads.begin(), grads.end(), Tensor<2,dim>());
109  for (unsigned int i=0; i<p_grads.size(); ++i)
110  for (unsigned int j=0; j<dim; ++j)
111  grads[i+j*n_sub][j] = p_grads[i];
112 
113  std::fill(grad_grads.begin(), grad_grads.end(), Tensor<3,dim>());
114  for (unsigned int i=0; i<p_grad_grads.size(); ++i)
115  for (unsigned int j=0; j<dim; ++j)
116  grad_grads[i+j*n_sub][j] = p_grad_grads[i];
117  }
118 
119  // This is the first polynomial not
120  // covered by the P_k subspace
121  unsigned int start = dim*n_sub;
122 
123  // Store values of auxiliary
124  // polynomials and their three
125  // derivatives
126  std::vector<std::vector<double> > monovali(dim, std::vector<double>(4));
127  std::vector<std::vector<double> > monovalk(dim, std::vector<double>(4));
128 
129  if (dim == 2)
130  {
131  for (unsigned int d=0; d<dim; ++d)
132  monomials[0].value(unit_point(d), monovali[d]);
133  if (values.size() != 0)
134  {
135  values[start][0] = monovali[0][0];
136  values[start][1] = -unit_point(1) * monovali[0][1];
137  values[start+1][0] = unit_point(0) * monovali[1][1];
138  values[start+1][1] = -monovali[1][0];
139  }
140  if (grads.size() != 0)
141  {
142  grads[start][0][0] = monovali[0][1];
143  grads[start][0][1] = 0.;
144  grads[start][1][0] = -unit_point(1) * monovali[0][2];
145  grads[start][1][1] = -monovali[0][1];
146  grads[start+1][0][0] = monovali[1][1];
147  grads[start+1][0][1] = unit_point(0) * monovali[1][2];
148  grads[start+1][1][0] = 0.;
149  grads[start+1][1][1] = -monovali[1][1];
150  }
151  if (grad_grads.size() != 0)
152  {
153  grad_grads[start][0][0][0] = monovali[0][2];
154  grad_grads[start][0][0][1] = 0.;
155  grad_grads[start][0][1][0] = 0.;
156  grad_grads[start][0][1][1] = 0.;
157  grad_grads[start][1][0][0] = -unit_point(1) * monovali[0][3];
158  grad_grads[start][1][0][1] = -monovali[0][2];
159  grad_grads[start][1][1][0] = -monovali[0][2];
160  grad_grads[start][1][1][1] = 0.;
161  grad_grads[start+1][0][0][0] = 0;
162  grad_grads[start+1][0][0][1] = monovali[1][2];
163  grad_grads[start+1][0][1][0] = monovali[1][2];
164  grad_grads[start+1][0][1][1] = unit_point(0) * monovali[1][3];
165  grad_grads[start+1][1][0][0] = 0.;
166  grad_grads[start+1][1][0][1] = 0.;
167  grad_grads[start+1][1][1][0] = 0.;
168  grad_grads[start+1][1][1][1] = -monovali[1][2];
169  }
170  }
171  else // dim == 3
172  {
173  // The number of curls in each
174  // component. Note that the
175  // table in BrezziFortin91 has
176  // a typo, but the text has the
177  // right basis
178 
179  // Note that the next basis
180  // function is always obtained
181  // from the previous by cyclic
182  // rotation of the coordinates
183  const unsigned int n_curls = monomials.size() - 1;
184  for (unsigned int i=0; i<n_curls; ++i, start+=dim)
185  {
186  for (unsigned int d=0; d<dim; ++d)
187  {
188  // p(t) = t^(i+1)
189  monomials[i+1].value(unit_point(d), monovali[d]);
190  // q(t) = t^(k-i)
191  monomials[degree()-i].value(unit_point(d), monovalk[d]);
192  }
193  if (values.size() != 0)
194  {
195  // x p'(y) q(z)
196  values[start][0] = unit_point(0) * monovali[1][1] * monovalk[2][0];
197  // - p(y) q(z)
198  values[start][1] = -monovali[1][0] * monovalk[2][0];
199  values[start][2] = 0.;
200 
201  // y p'(z) q(x)
202  values[start+1][1] = unit_point(1) * monovali[2][1] * monovalk[0][0];
203  // - p(z) q(x)
204  values[start+1][2] = -monovali[2][0] * monovalk[0][0];
205  values[start+1][0] = 0.;
206 
207  // z p'(x) q(y)
208  values[start+2][2] = unit_point(2) * monovali[0][1] * monovalk[1][0];
209  // -p(x) q(y)
210  values[start+2][0] = -monovali[0][0] * monovalk[1][0];
211  values[start+2][1] = 0.;
212  }
213  if (grads.size() != 0)
214  {
215  grads[start][0][0] = monovali[1][1] * monovalk[2][0];
216  grads[start][0][1] = unit_point(0) * monovali[1][2] * monovalk[2][0];
217  grads[start][0][2] = unit_point(0) * monovali[1][1] * monovalk[2][1];
218  grads[start][1][0] = 0.;
219  grads[start][1][1] = -monovali[1][1] * monovalk[2][0];
220  grads[start][1][2] = -monovali[1][0] * monovalk[2][1];
221  grads[start][2][0] = 0.;
222  grads[start][2][1] = 0.;
223  grads[start][2][2] = 0.;
224 
225  grads[start+1][1][1] = monovali[2][1] * monovalk[0][0];
226  grads[start+1][1][2] = unit_point(1) * monovali[2][2] * monovalk[0][0];
227  grads[start+1][1][0] = unit_point(1) * monovali[2][1] * monovalk[0][1];
228  grads[start+1][2][1] = 0.;
229  grads[start+1][2][2] = -monovali[2][1] * monovalk[0][0];
230  grads[start+1][2][0] = -monovali[2][0] * monovalk[0][1];
231  grads[start+1][0][1] = 0.;
232  grads[start+1][0][2] = 0.;
233  grads[start+1][0][0] = 0.;
234 
235  grads[start+2][2][2] = monovali[0][1] * monovalk[1][0];
236  grads[start+2][2][0] = unit_point(2) * monovali[0][2] * monovalk[1][0];
237  grads[start+2][2][1] = unit_point(2) * monovali[0][1] * monovalk[1][1];
238  grads[start+2][0][2] = 0.;
239  grads[start+2][0][0] = -monovali[0][1] * monovalk[1][0];
240  grads[start+2][0][1] = -monovali[0][0] * monovalk[1][1];
241  grads[start+2][1][2] = 0.;
242  grads[start+2][1][0] = 0.;
243  grads[start+2][1][1] = 0.;
244  }
245  if (grad_grads.size() != 0)
246  {
247  grad_grads[start][0][0][0] = 0.;
248  grad_grads[start][0][0][1] = monovali[1][2]*monovalk[2][0];
249  grad_grads[start][0][0][2] = monovali[1][1]*monovalk[2][1];
250  grad_grads[start][0][1][0] = monovali[1][2]*monovalk[2][0];
251  grad_grads[start][0][1][1] = unit_point(0)*monovali[1][3]*monovalk[2][0];
252  grad_grads[start][0][1][2] = unit_point(0)*monovali[1][2]*monovalk[2][1];
253  grad_grads[start][0][2][0] = monovali[1][1]*monovalk[2][1];
254  grad_grads[start][0][2][1] = unit_point(0)*monovali[1][2]*monovalk[2][1];
255  grad_grads[start][0][2][2] = unit_point(0)*monovali[1][1]*monovalk[2][2];
256  grad_grads[start][1][0][0] = 0.;
257  grad_grads[start][1][0][1] = 0.;
258  grad_grads[start][1][0][2] = 0.;
259  grad_grads[start][1][1][0] = 0.;
260  grad_grads[start][1][1][1] = -monovali[1][2]*monovalk[2][0];
261  grad_grads[start][1][1][2] = -monovali[1][1]*monovalk[2][1];
262  grad_grads[start][1][2][0] = 0.;
263  grad_grads[start][1][2][1] = -monovali[1][1]*monovalk[2][1];
264  grad_grads[start][1][2][2] = -monovali[1][0]*monovalk[2][2];
265  grad_grads[start][2][0][0] = 0.;
266  grad_grads[start][2][0][1] = 0.;
267  grad_grads[start][2][0][2] = 0.;
268  grad_grads[start][2][1][0] = 0.;
269  grad_grads[start][2][1][1] = 0.;
270  grad_grads[start][2][1][2] = 0.;
271  grad_grads[start][2][2][0] = 0.;
272  grad_grads[start][2][2][1] = 0.;
273  grad_grads[start][2][2][2] = 0.;
274 
275  grad_grads[start+1][0][0][0] = 0.;
276  grad_grads[start+1][0][0][1] = 0.;
277  grad_grads[start+1][0][0][2] = 0.;
278  grad_grads[start+1][0][1][0] = 0.;
279  grad_grads[start+1][0][1][1] = 0.;
280  grad_grads[start+1][0][1][2] = 0.;
281  grad_grads[start+1][0][2][0] = 0.;
282  grad_grads[start+1][0][2][1] = 0.;
283  grad_grads[start+1][0][2][2] = 0.;
284  grad_grads[start+1][1][0][0] = unit_point(1)*monovali[2][1]*monovalk[0][2];
285  grad_grads[start+1][1][0][1] = monovali[2][1]*monovalk[0][1];
286  grad_grads[start+1][1][0][2] = unit_point(1)*monovali[2][2]*monovalk[0][1];
287  grad_grads[start+1][1][1][0] = monovalk[0][1]*monovali[2][1];
288  grad_grads[start+1][1][1][1] = 0.;
289  grad_grads[start+1][1][1][2] = monovalk[0][0]*monovali[2][2];
290  grad_grads[start+1][1][2][0] = unit_point(1)*monovalk[0][1]*monovali[2][2];
291  grad_grads[start+1][1][2][1] = monovalk[0][0]*monovali[2][2];
292  grad_grads[start+1][1][2][2] = unit_point(1)*monovalk[0][0]*monovali[2][3];
293  grad_grads[start+1][2][0][0] = -monovalk[0][2]*monovali[2][0];
294  grad_grads[start+1][2][0][1] = 0.;
295  grad_grads[start+1][2][0][2] = -monovalk[0][1]*monovali[2][1];
296  grad_grads[start+1][2][1][0] = 0.;
297  grad_grads[start+1][2][1][1] = 0.;
298  grad_grads[start+1][2][1][2] = 0.;
299  grad_grads[start+1][2][2][0] = -monovalk[0][1]*monovali[2][1];
300  grad_grads[start+1][2][2][1] = 0.;
301  grad_grads[start+1][2][2][2] = -monovalk[0][0]*monovali[2][2];
302 
303  grad_grads[start+2][0][0][0] = -monovali[0][2]*monovalk[1][0];
304  grad_grads[start+2][0][0][1] = -monovali[0][1]*monovalk[1][1];
305  grad_grads[start+2][0][0][2] = 0.;
306  grad_grads[start+2][0][1][0] = -monovali[0][1]*monovalk[1][1];
307  grad_grads[start+2][0][1][1] = -monovali[0][0]*monovalk[1][2];
308  grad_grads[start+2][0][1][2] = 0.;
309  grad_grads[start+2][0][2][0] = 0.;
310  grad_grads[start+2][0][2][1] = 0.;
311  grad_grads[start+2][0][2][2] = 0.;
312  grad_grads[start+2][1][0][0] = 0.;
313  grad_grads[start+2][1][0][1] = 0.;
314  grad_grads[start+2][1][0][2] = 0.;
315  grad_grads[start+2][1][1][0] = 0.;
316  grad_grads[start+2][1][1][1] = 0.;
317  grad_grads[start+2][1][1][2] = 0.;
318  grad_grads[start+2][1][2][0] = 0.;
319  grad_grads[start+2][1][2][1] = 0.;
320  grad_grads[start+2][1][2][2] = 0.;
321  grad_grads[start+2][2][0][0] = unit_point(2)*monovali[0][3]*monovalk[1][0];
322  grad_grads[start+2][2][0][1] = unit_point(2)*monovali[0][2]*monovalk[1][1];
323  grad_grads[start+2][2][0][2] = monovali[0][2]*monovalk[1][0];
324  grad_grads[start+2][2][1][0] = unit_point(2)*monovali[0][2]*monovalk[1][1];
325  grad_grads[start+2][2][1][1] = unit_point(2)*monovali[0][1]*monovalk[1][2];
326  grad_grads[start+2][2][1][2] = monovali[0][1]*monovalk[1][1];
327  grad_grads[start+2][2][2][0] = monovali[0][2]*monovalk[1][0];
328  grad_grads[start+2][2][2][1] = monovali[0][1]*monovalk[1][1];
329  grad_grads[start+2][2][2][2] = 0.;
330 
331  }
332  }
333  Assert(start == n_pols, ExcInternalError());
334  }
335 }
336 
337 
338 /*
339 template <int dim>
340 void
341 PolynomialsBDM<dim>::compute_node_matrix (Table<2,double>& A) const
342 {
343  std::vector<Polynomial<double> > moment_weight(2);
344  for (unsigned int i=0;i<moment_weight.size();++i)
345  moment_weight[i] = Monomial<double>(i);
346 
347  QGauss<dim-1> qface(polynomial_space.degree()+1);
348 
349  std::vector<Tensor<1,dim> > values(n());
350  std::vector<Tensor<2,dim> > grads;
351  std::vector<Tensor<3,dim> > grad_grads;
352  values.resize(n());
353 
354  for (unsigned int face=0;face<2*dim;++face)
355  {
356  double orientation = 1.;
357  if ((face==0) || (face==3))
358  orientation = -1.;
359 
360  for (unsigned int k=0;k<qface.size();++k)
361  {
362  const double w = qface.weight(k) * orientation;
363  const double x = qface.point(k)(0);
364  Point<dim> p;
365  switch (face)
366  {
367  case 2:
368  p(1) = 1.;
369  case 0:
370  p(0) = x;
371  break;
372  case 1:
373  p(0) = 1.;
374  case 3:
375  p(1) = x;
376  break;
377  }
378 // std::cerr << p
379 // << '\t' << moment_weight[0].value(x)
380 // << '\t' << moment_weight[1].value(x)
381 // ;
382 
383  compute (p, values, grads, grad_grads);
384 
385  for (unsigned int i=0;i<n();++i)
386  {
387 // std::cerr << '\t' << std::setw(6) << values[i][1-face%2];
388  // Integrate normal component.
389  // This is easy on the unit square
390  for (unsigned int j=0;j<moment_weight.size();++j)
391  A(moment_weight.size()*face+j,i)
392  += w * values[i][1-face%2] * moment_weight[j].value(x);
393  }
394 // std::cerr << std::endl;
395  }
396  }
397 
398  // Volume integrals are missing
399  //
400  // This degree is one larger
401  Assert (polynomial_space.degree() <= 2,
402  ExcNotImplemented());
403 }
404 */
405 
406 template <int dim>
407 unsigned int
409 {
410  if (dim == 1) return k+1;
411  if (dim == 2) return (k+1)*(k+2)+2;
412  if (dim == 3) return ((k+1)*(k+2)*(k+3))/2+3*(k+1);
413  Assert(false, ExcNotImplemented());
414  return 0;
415 }
416 
417 
418 template class PolynomialsBDM<1>;
419 template class PolynomialsBDM<2>;
420 template class PolynomialsBDM<3>;
421 
422 
423 DEAL_II_NAMESPACE_CLOSE
PolynomialsBDM(const unsigned int k)
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
std::vector< Polynomials::Polynomial< double > > monomials
#define Assert(cond, exc)
Definition: exceptions.h:313
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static unsigned int compute_n_pols(unsigned int degree)
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcInternalError()