Reference documentation for deal.II version 8.5.1
polynomial_space.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2002 - 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 #include <deal.II/base/polynomial_space.h>
17 #include <deal.II/base/exceptions.h>
18 #include <deal.II/base/table.h>
19 
20 DEAL_II_NAMESPACE_OPEN
21 
22 
23 template <int dim>
24 unsigned int
26 {
27  unsigned int n_pols = n;
28  for (unsigned int i=1; i<dim; ++i)
29  {
30  n_pols *= (n+i);
31  n_pols /= (i+1);
32  }
33  return n_pols;
34 }
35 
36 
37 template <>
38 unsigned int
39 PolynomialSpace<0>::compute_n_pols (const unsigned int)
40 {
41  return 0;
42 }
43 
44 
45 template <>
46 void
48 compute_index (const unsigned int i,
49  unsigned int (&index)[1]) const
50 {
51  Assert(i<index_map.size(),
52  ExcIndexRange(i,0,index_map.size()));
53  const unsigned int n=index_map[i];
54  index[0] = n;
55 }
56 
57 
58 
59 template <>
60 void
62 compute_index (const unsigned int i,
63  unsigned int (&index)[2]) const
64 {
65  Assert(i<index_map.size(),
66  ExcIndexRange(i,0,index_map.size()));
67  const unsigned int n=index_map[i];
68  // there should be a better way to
69  // write this function (not
70  // linear in n_1d), someone
71  // should think about this...
72  const unsigned int n_1d=polynomials.size();
73  unsigned int k=0;
74  for (unsigned int iy=0; iy<n_1d; ++iy)
75  if (n < k+n_1d-iy)
76  {
77  index[0] = n-k;
78  index[1] = iy;
79  return;
80  }
81  else
82  k+=n_1d-iy;
83 }
84 
85 
86 
87 template <>
88 void
90 compute_index (const unsigned int i,
91  unsigned int (&index)[3]) const
92 {
93  Assert(i<index_map.size(),
94  ExcIndexRange(i,0,index_map.size()));
95  const unsigned int n=index_map[i];
96  // there should be a better way to
97  // write this function (not
98  // quadratic in n_1d), someone
99  // should think about this...
100  //
101  // (ah, and yes: the original
102  // algorithm was even cubic!)
103  const unsigned int n_1d=polynomials.size();
104  unsigned int k=0;
105  for (unsigned int iz=0; iz<n_1d; ++iz)
106  for (unsigned int iy=0; iy<n_1d-iz; ++iy)
107  if (n < k+n_1d-iy-iz)
108  {
109  index[0] = n-k;
110  index[1] = iy;
111  index[2] = iz;
112  return;
113  }
114  else
115  k += n_1d-iy-iz;
116 }
117 
118 
119 template <int dim>
120 void
122  const std::vector<unsigned int> &renumber)
123 {
124  Assert(renumber.size()==index_map.size(),
125  ExcDimensionMismatch(renumber.size(), index_map.size()));
126 
127  index_map=renumber;
128  for (unsigned int i=0; i<index_map.size(); ++i)
129  index_map_inverse[index_map[i]]=i;
130 }
131 
132 
133 
134 template <int dim>
135 double
137  const Point<dim> &p) const
138 {
139  unsigned int ix[dim];
140  compute_index(i,ix);
141  // take the product of the
142  // polynomials in the various space
143  // directions
144  double result = 1.;
145  for (unsigned int d=0; d<dim; ++d)
146  result *= polynomials[ix[d]].value(p(d));
147  return result;
148 }
149 
150 
151 
152 template <int dim>
155  const Point<dim> &p) const
156 {
157  unsigned int ix[dim];
158  compute_index(i,ix);
159 
160  Tensor<1,dim> result;
161  for (unsigned int d=0; d<dim; ++d)
162  result[d] = 1.;
163 
164  // get value and first derivative
165  std::vector<double> v(2);
166  for (unsigned int d=0; d<dim; ++d)
167  {
168  polynomials[ix[d]].value(p(d), v);
169  result[d] *= v[1];
170  for (unsigned int d1=0; d1<dim; ++d1)
171  if (d1 != d)
172  result[d1] *= v[0];
173  }
174  return result;
175 }
176 
177 
178 template <int dim>
181  const Point<dim> &p) const
182 {
183  unsigned int ix[dim];
184  compute_index(i,ix);
185 
186  Tensor<2,dim> result;
187  for (unsigned int d=0; d<dim; ++d)
188  for (unsigned int d1=0; d1<dim; ++d1)
189  result[d][d1] = 1.;
190 
191  // get value, first and second
192  // derivatives
193  std::vector<double> v(3);
194  for (unsigned int d=0; d<dim; ++d)
195  {
196  polynomials[ix[d]].value(p(d), v);
197  result[d][d] *= v[2];
198  for (unsigned int d1=0; d1<dim; ++d1)
199  {
200  if (d1 != d)
201  {
202  result[d][d1] *= v[1];
203  result[d1][d] *= v[1];
204  for (unsigned int d2=0; d2<dim; ++d2)
205  if (d2 != d)
206  result[d1][d2] *= v[0];
207  }
208  }
209  }
210  return result;
211 }
212 
213 
214 template <int dim>
215 void
217  std::vector<double> &values,
218  std::vector<Tensor<1,dim> > &grads,
219  std::vector<Tensor<2,dim> > &grad_grads,
220  std::vector<Tensor<3,dim> > &third_derivatives,
221  std::vector<Tensor<4,dim> > &fourth_derivatives) const
222 {
223  const unsigned int n_1d=polynomials.size();
224 
225  Assert(values.size()==n_pols || values.size()==0,
226  ExcDimensionMismatch2(values.size(), n_pols, 0));
227  Assert(grads.size()==n_pols|| grads.size()==0,
228  ExcDimensionMismatch2(grads.size(), n_pols, 0));
229  Assert(grad_grads.size()==n_pols|| grad_grads.size()==0,
230  ExcDimensionMismatch2(grad_grads.size(), n_pols, 0));
231  Assert(third_derivatives.size()==n_pols|| third_derivatives.size()==0,
232  ExcDimensionMismatch2(third_derivatives.size(), n_pols, 0));
233  Assert(fourth_derivatives.size()==n_pols|| fourth_derivatives.size()==0,
234  ExcDimensionMismatch2(fourth_derivatives.size(), n_pols, 0));
235 
236  unsigned int v_size=0;
237  bool update_values=false, update_grads=false, update_grad_grads=false;
238  bool update_3rd_derivatives=false, update_4th_derivatives=false;
239  if (values.size()==n_pols)
240  {
241  update_values=true;
242  v_size=1;
243  }
244  if (grads.size()==n_pols)
245  {
246  update_grads=true;
247  v_size=2;
248  }
249  if (grad_grads.size()==n_pols)
250  {
251  update_grad_grads=true;
252  v_size=3;
253  }
254  if (third_derivatives.size()==n_pols)
255  {
257  v_size=4;
258  }
259  if (fourth_derivatives.size()==n_pols)
260  {
261  update_4th_derivatives=true;
262  v_size=5;
263  }
264 
265  // Store data in a single
266  // object. Access is by
267  // v[d][n][o]
268  // d: coordinate direction
269  // n: number of 1d polynomial
270  // o: order of derivative
271  Table<2,std::vector<double> > v(dim, n_1d);
272  for (unsigned int d=0; d<v.size()[0]; ++d)
273  for (unsigned int i=0; i<v.size()[1]; ++i)
274  {
275  v(d,i).resize (v_size, 0.);
276  polynomials[i].value(p(d), v(d,i));
277  };
278 
279  if (update_values)
280  {
281  unsigned int k = 0;
282 
283  for (unsigned int iz=0; iz<((dim>2) ? n_1d : 1); ++iz)
284  for (unsigned int iy=0; iy<((dim>1) ? n_1d-iz : 1); ++iy)
285  for (unsigned int ix=0; ix<n_1d-iy-iz; ++ix)
286  values[index_map_inverse[k++]] =
287  v[0][ix][0]
288  * ((dim>1) ? v[1][iy][0] : 1.)
289  * ((dim>2) ? v[2][iz][0] : 1.);
290  }
291 
292  if (update_grads)
293  {
294  unsigned int k = 0;
295 
296  for (unsigned int iz=0; iz<((dim>2) ? n_1d : 1); ++iz)
297  for (unsigned int iy=0; iy<((dim>1) ? n_1d-iz : 1); ++iy)
298  for (unsigned int ix=0; ix<n_1d-iy-iz; ++ix)
299  {
300  const unsigned int k2=index_map_inverse[k++];
301  for (unsigned int d=0; d<dim; ++d)
302  grads[k2][d] = v[0][ix][(d==0) ? 1 : 0]
303  * ((dim>1) ? v[1][iy][(d==1) ? 1 : 0] : 1.)
304  * ((dim>2) ? v[2][iz][(d==2) ? 1 : 0] : 1.);
305  }
306  }
307 
308  if (update_grad_grads)
309  {
310  unsigned int k = 0;
311 
312  for (unsigned int iz=0; iz<((dim>2) ? n_1d : 1); ++iz)
313  for (unsigned int iy=0; iy<((dim>1) ? n_1d-iz : 1); ++iy)
314  for (unsigned int ix=0; ix<n_1d-iy-iz; ++ix)
315  {
316  const unsigned int k2=index_map_inverse[k++];
317  for (unsigned int d1=0; d1<dim; ++d1)
318  for (unsigned int d2=0; d2<dim; ++d2)
319  {
320  // Derivative
321  // order for each
322  // direction
323  const unsigned int
324  j0 = ((d1==0) ? 1 : 0) + ((d2==0) ? 1 : 0);
325  const unsigned int
326  j1 = ((d1==1) ? 1 : 0) + ((d2==1) ? 1 : 0);
327  const unsigned int
328  j2 = ((d1==2) ? 1 : 0) + ((d2==2) ? 1 : 0);
329 
330  grad_grads[k2][d1][d2] =
331  v[0][ix][j0]
332  * ((dim>1) ? v[1][iy][j1] : 1.)
333  * ((dim>2) ? v[2][iz][j2] : 1.);
334  }
335  }
336  }
337 
339  {
340  unsigned int k = 0;
341 
342  for (unsigned int iz=0; iz<((dim>2) ? n_1d : 1); ++iz)
343  for (unsigned int iy=0; iy<((dim>1) ? n_1d-iz : 1); ++iy)
344  for (unsigned int ix=0; ix<n_1d-iy-iz; ++ix)
345  {
346  const unsigned int k2=index_map_inverse[k++];
347  for (unsigned int d1=0; d1<dim; ++d1)
348  for (unsigned int d2=0; d2<dim; ++d2)
349  for (unsigned int d3=0; d3<dim; ++d3)
350  {
351  // Derivative
352  // order for each
353  // direction
354  std::vector<unsigned int> deriv_order (dim, 0);
355  for (unsigned int x=0; x<dim; ++x)
356  {
357  if (d1==x) ++deriv_order[x];
358  if (d2==x) ++deriv_order[x];
359  if (d3==x) ++deriv_order[x];
360  }
361 
362  third_derivatives[k2][d1][d2][d3] =
363  v[0][ix][deriv_order[0]]
364  * ((dim>1) ? v[1][iy][deriv_order[1]] : 1.)
365  * ((dim>2) ? v[2][iz][deriv_order[2]] : 1.);
366  }
367  }
368  }
369 
370  if (update_4th_derivatives)
371  {
372  unsigned int k = 0;
373 
374  for (unsigned int iz=0; iz<((dim>2) ? n_1d : 1); ++iz)
375  for (unsigned int iy=0; iy<((dim>1) ? n_1d-iz : 1); ++iy)
376  for (unsigned int ix=0; ix<n_1d-iy-iz; ++ix)
377  {
378  const unsigned int k2=index_map_inverse[k++];
379  for (unsigned int d1=0; d1<dim; ++d1)
380  for (unsigned int d2=0; d2<dim; ++d2)
381  for (unsigned int d3=0; d3<dim; ++d3)
382  for (unsigned int d4=0; d4<dim; ++d4)
383  {
384  // Derivative
385  // order for each
386  // direction
387  std::vector<unsigned int> deriv_order (dim, 0);
388  for (unsigned int x=0; x<dim; ++x)
389  {
390  if (d1==x) ++deriv_order[x];
391  if (d2==x) ++deriv_order[x];
392  if (d3==x) ++deriv_order[x];
393  if (d4==x) ++deriv_order[x];
394  }
395 
396  fourth_derivatives[k2][d1][d2][d3][d4] =
397  v[0][ix][deriv_order[0]]
398  * ((dim>1) ? v[1][iy][deriv_order[1]] : 1.)
399  * ((dim>2) ? v[2][iz][deriv_order[2]] : 1.);
400  }
401  }
402  }
403 }
404 
405 
406 template class PolynomialSpace<1>;
407 template class PolynomialSpace<2>;
408 template class PolynomialSpace<3>;
409 
410 DEAL_II_NAMESPACE_CLOSE
Shape function values.
static ::ExceptionBase & ExcDimensionMismatch2(int arg1, int arg2, int arg3)
void set_numbering(const std::vector< unsigned int > &renumber)
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
Third derivatives of shape functions.
#define Assert(cond, exc)
Definition: exceptions.h:313
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
void compute(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
Tensor< 2, dim > compute_grad_grad(const unsigned int i, const Point< dim > &p) const
double compute_value(const unsigned int i, const Point< dim > &p) const
static unsigned int compute_n_pols(const unsigned int n)
Tensor< 1, dim > compute_grad(const unsigned int i, const Point< dim > &p) const
Definition: table.h:33
unsigned int size(const unsigned int i) const
void compute_index(const unsigned int n, unsigned int(&index)[dim >0?dim:1]) const